250 lines
7.0 KiB
Go
250 lines
7.0 KiB
Go
package terminus
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/mail"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/beclab/Olares/cli/pkg/core/logger"
|
|
corev1 "k8s.io/api/core/v1"
|
|
|
|
"github.com/beclab/Olares/cli/pkg/common"
|
|
cc "github.com/beclab/Olares/cli/pkg/core/common"
|
|
"github.com/beclab/Olares/cli/pkg/core/connector"
|
|
"github.com/beclab/Olares/cli/pkg/core/task"
|
|
"github.com/beclab/Olares/cli/pkg/core/util"
|
|
accounttemplates "github.com/beclab/Olares/cli/pkg/terminus/templates"
|
|
"github.com/beclab/Olares/cli/pkg/utils"
|
|
"github.com/pkg/errors"
|
|
|
|
ctrl "sigs.k8s.io/controller-runtime"
|
|
)
|
|
|
|
type GetUserInfo struct {
|
|
common.KubeAction
|
|
}
|
|
|
|
func (s *GetUserInfo) Execute(runtime connector.Runtime) error {
|
|
var err error
|
|
s.KubeConf.Arg.User.DomainName, err = s.getDomainName()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logger.Infof("using Domain Name: %s", s.KubeConf.Arg.User.DomainName)
|
|
s.KubeConf.Arg.User.UserName, err = s.getUserName()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logger.Infof("using Olares Local Name: %s", s.KubeConf.Arg.User.UserName)
|
|
s.KubeConf.Arg.User.Email, err = s.getUserEmail()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logger.Infof("using Olares ID: %s", s.KubeConf.Arg.User.Email)
|
|
s.KubeConf.Arg.User.Password, s.KubeConf.Arg.User.EncryptedPassword, err = s.getUserPassword()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if s.KubeConf.Arg.User.Password != "" {
|
|
logger.Infof("using password: %s", s.KubeConf.Arg.User.Password)
|
|
} else {
|
|
logger.Infof("using already encrypted password")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *GetUserInfo) getDomainName() (string, error) {
|
|
domainName := s.KubeConf.Arg.User.DomainName
|
|
if len(domainName) > 0 {
|
|
if !utils.IsValidDomain(domainName) {
|
|
return "", errors.New(fmt.Sprintf("invalid domain name \"%s\", please reset", domainName))
|
|
}
|
|
return domainName, nil
|
|
}
|
|
|
|
reader, err := utils.GetBufIOReaderOfTerminalInput()
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "failed to get terminal input reader")
|
|
}
|
|
LOOP:
|
|
fmt.Printf("\nEnter the domain name ( %s by default ): ", cc.DefaultDomainName)
|
|
domainName, err = reader.ReadString('\n')
|
|
if err != nil && err.Error() != "EOF" {
|
|
return domainName, errors.Wrap(errors.WithStack(err), "read domain name failed")
|
|
}
|
|
domainName = strings.TrimSpace(domainName)
|
|
if domainName == "" {
|
|
return cc.DefaultDomainName, nil
|
|
}
|
|
|
|
if !utils.IsValidDomain(domainName) {
|
|
fmt.Printf("\ninvalid domain name, please try again")
|
|
goto LOOP
|
|
}
|
|
return domainName, nil
|
|
}
|
|
|
|
func (s *GetUserInfo) getUserName() (string, error) {
|
|
userName := s.KubeConf.Arg.User.UserName
|
|
if strings.Contains(userName, "@") {
|
|
userName = strings.Split(userName, "@")[0]
|
|
}
|
|
userName = strings.TrimSpace(userName)
|
|
if len(userName) > 0 {
|
|
if err := utils.ValidateUserName(userName); err != nil {
|
|
return "", fmt.Errorf("invalid username \"%s\": %s, please reset", userName, err.Error())
|
|
}
|
|
return userName, nil
|
|
}
|
|
reader, err := utils.GetBufIOReaderOfTerminalInput()
|
|
if err != nil {
|
|
return "", errors.Wrap(err, "failed to get terminal input reader")
|
|
}
|
|
LOOP:
|
|
fmt.Printf("\nEnter the Olares ID (which you registered in the LarePass app): ")
|
|
userName, err = reader.ReadString('\n')
|
|
if err != nil && err.Error() != "EOF" {
|
|
return "", errors.Wrap(errors.WithStack(err), "read username failed")
|
|
}
|
|
if strings.Contains(userName, "@") {
|
|
userName = strings.Split(userName, "@")[0]
|
|
}
|
|
userName = strings.TrimSpace(userName)
|
|
if err := utils.ValidateUserName(userName); err != nil {
|
|
fmt.Printf("\ninvalid username: %s, please try again", err.Error())
|
|
goto LOOP
|
|
}
|
|
|
|
return userName, nil
|
|
}
|
|
|
|
func (s *GetUserInfo) getUserEmail() (string, error) {
|
|
userEmail := strings.TrimSpace(os.Getenv("TERMINUS_OS_EMAIL"))
|
|
if len(userEmail) == 0 {
|
|
return s.KubeConf.Arg.User.UserName + "@" + s.KubeConf.Arg.User.DomainName, nil
|
|
}
|
|
if _, err := mail.ParseAddress(userEmail); err != nil {
|
|
return "", fmt.Errorf("invalid email address \"%s\" set in env: %s, please reset", userEmail, err.Error())
|
|
}
|
|
return userEmail, nil
|
|
}
|
|
|
|
func (s *GetUserInfo) getUserPassword() (string, string, error) {
|
|
// currently only used in the installation flow by LarePass -> Olaresd,
|
|
// when this env var is passed in, it is already encrypted
|
|
// make this one priority over the password set in the arg specailly
|
|
// to ensure the larepass installation flow works as expected
|
|
encryptedPassword := strings.TrimSpace(os.Getenv(common.EnvLegacyEncryptedOSPassword))
|
|
if len(encryptedPassword) != 32 && len(encryptedPassword) != 0 {
|
|
return "", "", fmt.Errorf("invalid password \"%s\" set in env: length should be equal 32, please reset", encryptedPassword)
|
|
|
|
}
|
|
if len(encryptedPassword) == 0 {
|
|
if s.KubeConf.Arg.User.Password != "" {
|
|
return s.KubeConf.Arg.User.Password, utils.EncryptPassword(s.KubeConf.Arg.User.Password), nil
|
|
} else {
|
|
return utils.GenerateEncryptedPassword(8)
|
|
}
|
|
}
|
|
return "", encryptedPassword, nil
|
|
}
|
|
|
|
type SetAccountValues struct {
|
|
common.KubeAction
|
|
}
|
|
|
|
func (p *SetAccountValues) Execute(runtime connector.Runtime) error {
|
|
var accountFile = path.Join(runtime.GetInstallerDir(), "wizard", "config", "account", accounttemplates.AccountValues.Name())
|
|
|
|
var data = util.Data{
|
|
"UserName": p.KubeConf.Arg.User.UserName,
|
|
"Password": p.KubeConf.Arg.User.EncryptedPassword,
|
|
"Email": p.KubeConf.Arg.User.Email,
|
|
"DomainName": p.KubeConf.Arg.User.DomainName,
|
|
}
|
|
|
|
accountStr, err := util.Render(accounttemplates.AccountValues, data)
|
|
if err != nil {
|
|
return errors.Wrap(errors.WithStack(err), "render account template failed")
|
|
}
|
|
|
|
if err := util.WriteFile(accountFile, []byte(accountStr), cc.FileMode0644); err != nil {
|
|
return errors.Wrap(errors.WithStack(err), fmt.Sprintf("write account %s failed", accountFile))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type InstallAccount struct {
|
|
common.KubeAction
|
|
}
|
|
|
|
func (t *InstallAccount) Execute(runtime connector.Runtime) error {
|
|
config, err := ctrl.GetConfig()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ns := corev1.NamespaceDefault
|
|
actionConfig, settings, err := utils.InitConfig(config, ns)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var ctx, cancel = context.WithTimeout(context.Background(), 5*time.Minute)
|
|
defer cancel()
|
|
|
|
var accountPath = path.Join(runtime.GetInstallerDir(), "wizard", "config", "account")
|
|
|
|
if !util.IsExist(accountPath) {
|
|
return fmt.Errorf("account not exists")
|
|
}
|
|
|
|
vals := make(map[string]interface{})
|
|
if si := runtime.GetSystemInfo(); si.GetNATGateway() != "" {
|
|
vals["nat_gateway_ip"] = si.GetNATGateway()
|
|
}
|
|
|
|
if err := utils.UpgradeCharts(ctx, actionConfig, settings, common.ChartNameAccount, accountPath, "", ns, vals, false); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type InstallAccountModule struct {
|
|
common.KubeModule
|
|
}
|
|
|
|
func (m *InstallAccountModule) Init() {
|
|
logger.InfoInstallationProgress("Installing account ...")
|
|
m.Name = "InstallAccount"
|
|
|
|
getUserInfo := &task.LocalTask{
|
|
Name: "GetUserInfo",
|
|
Action: new(GetUserInfo),
|
|
}
|
|
|
|
setAccountValues := &task.LocalTask{
|
|
Name: "SetAccountValues",
|
|
Action: &SetAccountValues{},
|
|
Retry: 1,
|
|
}
|
|
|
|
installAccount := &task.LocalTask{
|
|
Name: "InstallAccount",
|
|
Action: &InstallAccount{},
|
|
Retry: 1,
|
|
}
|
|
|
|
m.Tasks = []task.Interface{
|
|
getUserInfo,
|
|
setAccountValues,
|
|
installAccount,
|
|
}
|
|
}
|