2022-04-06 08:13:40 +02:00
|
|
|
package setup
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2022-04-12 16:20:17 +02:00
|
|
|
"fmt"
|
2022-12-09 13:04:33 +00:00
|
|
|
"os"
|
2022-04-28 10:30:41 +02:00
|
|
|
"strings"
|
2022-04-06 08:13:40 +02:00
|
|
|
|
2022-05-03 15:58:38 +02:00
|
|
|
"golang.org/x/text/language"
|
|
|
|
|
2022-04-27 01:01:45 +02:00
|
|
|
"github.com/zitadel/zitadel/internal/api/authz"
|
2024-11-04 11:44:51 +01:00
|
|
|
"github.com/zitadel/zitadel/internal/cache/connector"
|
2022-04-27 01:01:45 +02:00
|
|
|
"github.com/zitadel/zitadel/internal/command"
|
|
|
|
"github.com/zitadel/zitadel/internal/config/systemdefaults"
|
|
|
|
"github.com/zitadel/zitadel/internal/crypto"
|
|
|
|
crypto_db "github.com/zitadel/zitadel/internal/crypto/database"
|
2023-08-22 12:49:22 +02:00
|
|
|
"github.com/zitadel/zitadel/internal/database"
|
2022-09-23 14:08:10 +02:00
|
|
|
"github.com/zitadel/zitadel/internal/domain"
|
2022-04-27 01:01:45 +02:00
|
|
|
"github.com/zitadel/zitadel/internal/eventstore"
|
2022-04-06 08:13:40 +02:00
|
|
|
)
|
|
|
|
|
2022-07-27 10:22:20 +02:00
|
|
|
type FirstInstance struct {
|
2022-05-03 15:58:38 +02:00
|
|
|
InstanceName string
|
|
|
|
DefaultLanguage language.Tag
|
2023-08-11 16:19:14 +02:00
|
|
|
Org command.InstanceOrgSetup
|
2022-12-09 13:04:33 +00:00
|
|
|
MachineKeyPath string
|
2023-06-15 08:16:39 +02:00
|
|
|
PatPath string
|
2024-02-28 10:55:54 +02:00
|
|
|
Features *command.InstanceFeatures
|
2022-04-12 16:20:17 +02:00
|
|
|
|
2024-05-30 11:35:30 +02:00
|
|
|
Skip bool
|
|
|
|
|
2022-04-28 10:30:41 +02:00
|
|
|
instanceSetup command.InstanceSetup
|
2022-04-12 16:20:17 +02:00
|
|
|
userEncryptionKey *crypto.KeyConfig
|
2022-05-13 14:13:07 +02:00
|
|
|
smtpEncryptionKey *crypto.KeyConfig
|
2023-06-15 08:16:39 +02:00
|
|
|
oidcEncryptionKey *crypto.KeyConfig
|
2022-04-12 16:20:17 +02:00
|
|
|
masterKey string
|
2023-08-22 12:49:22 +02:00
|
|
|
db *database.DB
|
2022-04-12 16:20:17 +02:00
|
|
|
es *eventstore.Eventstore
|
|
|
|
defaults systemdefaults.SystemDefaults
|
|
|
|
zitadelRoles []authz.RoleMapping
|
2022-04-28 10:30:41 +02:00
|
|
|
externalDomain string
|
2022-04-21 12:37:39 +02:00
|
|
|
externalSecure bool
|
2022-04-25 11:16:36 +02:00
|
|
|
externalPort uint16
|
2022-07-27 10:22:20 +02:00
|
|
|
domain string
|
2022-04-06 08:13:40 +02:00
|
|
|
}
|
|
|
|
|
2024-01-25 17:28:20 +01:00
|
|
|
func (mig *FirstInstance) Execute(ctx context.Context, _ eventstore.Event) error {
|
2024-05-30 11:35:30 +02:00
|
|
|
if mig.Skip {
|
|
|
|
return nil
|
|
|
|
}
|
2024-01-25 17:28:20 +01:00
|
|
|
keyStorage, err := mig.verifyEncryptionKeys(ctx)
|
2022-04-12 16:20:17 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
userAlg, err := crypto.NewAESCrypto(mig.userEncryptionKey, keyStorage)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-05-13 14:13:07 +02:00
|
|
|
smtpEncryption, err := crypto.NewAESCrypto(mig.smtpEncryptionKey, keyStorage)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-06-15 08:16:39 +02:00
|
|
|
oidcEncryption, err := crypto.NewAESCrypto(mig.oidcEncryptionKey, keyStorage)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-11-04 11:44:51 +01:00
|
|
|
cmd, err := command.StartCommands(ctx,
|
|
|
|
mig.es,
|
|
|
|
connector.Connectors{},
|
2022-04-20 16:59:37 +02:00
|
|
|
mig.defaults,
|
|
|
|
mig.zitadelRoles,
|
|
|
|
nil,
|
|
|
|
nil,
|
2022-04-28 10:30:41 +02:00
|
|
|
mig.externalDomain,
|
2022-04-25 11:16:36 +02:00
|
|
|
mig.externalSecure,
|
|
|
|
mig.externalPort,
|
2022-04-20 16:59:37 +02:00
|
|
|
nil,
|
|
|
|
nil,
|
2022-05-13 14:13:07 +02:00
|
|
|
smtpEncryption,
|
2022-04-20 16:59:37 +02:00
|
|
|
nil,
|
|
|
|
userAlg,
|
|
|
|
nil,
|
2023-06-15 08:16:39 +02:00
|
|
|
oidcEncryption,
|
2022-09-12 17:18:08 +01:00
|
|
|
nil,
|
|
|
|
nil,
|
2023-04-25 09:02:29 +02:00
|
|
|
nil,
|
2023-05-05 17:34:53 +02:00
|
|
|
nil,
|
2024-11-28 11:06:52 +01:00
|
|
|
nil,
|
2023-07-10 15:27:00 +02:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
2023-08-23 10:04:29 +02:00
|
|
|
nil,
|
2022-09-12 17:18:08 +01:00
|
|
|
)
|
2022-04-21 12:37:39 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-04-28 10:30:41 +02:00
|
|
|
mig.instanceSetup.InstanceName = mig.InstanceName
|
2022-07-27 10:22:20 +02:00
|
|
|
mig.instanceSetup.CustomDomain = mig.externalDomain
|
2022-05-03 15:58:38 +02:00
|
|
|
mig.instanceSetup.DefaultLanguage = mig.DefaultLanguage
|
2022-04-28 10:30:41 +02:00
|
|
|
mig.instanceSetup.Org = mig.Org
|
2022-09-23 14:08:10 +02:00
|
|
|
// check if username is email style or else append @<orgname>.<custom-domain>
|
|
|
|
//this way we have the same value as before changing `UserLoginMustBeDomain` to false
|
|
|
|
if !mig.instanceSetup.DomainPolicy.UserLoginMustBeDomain && !strings.Contains(mig.instanceSetup.Org.Human.Username, "@") {
|
2023-10-11 09:55:01 +02:00
|
|
|
orgDomain, err := domain.NewIAMDomainName(mig.instanceSetup.Org.Name, mig.instanceSetup.CustomDomain)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
mig.instanceSetup.Org.Human.Username = mig.instanceSetup.Org.Human.Username + "@" + orgDomain
|
2022-09-23 14:08:10 +02:00
|
|
|
}
|
2023-03-14 20:20:38 +01:00
|
|
|
mig.instanceSetup.Org.Human.Email.Address = mig.instanceSetup.Org.Human.Email.Address.Normalize()
|
2022-04-28 10:30:41 +02:00
|
|
|
if mig.instanceSetup.Org.Human.Email.Address == "" {
|
2023-03-14 20:20:38 +01:00
|
|
|
mig.instanceSetup.Org.Human.Email.Address = domain.EmailAddress(mig.instanceSetup.Org.Human.Username)
|
|
|
|
if !strings.Contains(string(mig.instanceSetup.Org.Human.Email.Address), "@") {
|
2023-10-11 09:55:01 +02:00
|
|
|
orgDomain, err := domain.NewIAMDomainName(mig.instanceSetup.Org.Name, mig.instanceSetup.CustomDomain)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
mig.instanceSetup.Org.Human.Email.Address = domain.EmailAddress(mig.instanceSetup.Org.Human.Username + "@" + orgDomain)
|
2022-09-23 14:08:10 +02:00
|
|
|
}
|
2022-04-28 10:30:41 +02:00
|
|
|
}
|
|
|
|
|
2023-06-15 08:16:39 +02:00
|
|
|
_, token, key, _, err := cmd.SetUpInstance(ctx, &mig.instanceSetup)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if mig.instanceSetup.Org.Machine != nil &&
|
|
|
|
((mig.instanceSetup.Org.Machine.Pat != nil && token == "") ||
|
|
|
|
(mig.instanceSetup.Org.Machine.MachineKey != nil && key == nil)) {
|
2022-12-09 13:04:33 +00:00
|
|
|
return err
|
|
|
|
}
|
2024-01-25 17:28:20 +01:00
|
|
|
return mig.outputMachineAuthentication(key, token)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mig *FirstInstance) verifyEncryptionKeys(ctx context.Context) (*crypto_db.Database, error) {
|
|
|
|
keyStorage, err := crypto_db.NewKeyStorage(mig.db, mig.masterKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("cannot start key storage: %w", err)
|
|
|
|
}
|
|
|
|
if err = verifyKey(ctx, mig.userEncryptionKey, keyStorage); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err = verifyKey(ctx, mig.smtpEncryptionKey, keyStorage); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err = verifyKey(ctx, mig.oidcEncryptionKey, keyStorage); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return keyStorage, nil
|
|
|
|
}
|
2022-12-09 13:04:33 +00:00
|
|
|
|
2024-01-25 17:28:20 +01:00
|
|
|
func (mig *FirstInstance) outputMachineAuthentication(key *command.MachineKey, token string) error {
|
2023-06-15 08:16:39 +02:00
|
|
|
if key != nil {
|
|
|
|
keyDetails, err := key.Detail()
|
2022-12-09 13:04:33 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-06-15 08:16:39 +02:00
|
|
|
if err := outputStdoutOrPath(mig.MachineKeyPath, string(keyDetails)); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-12-09 13:04:33 +00:00
|
|
|
}
|
2023-06-15 08:16:39 +02:00
|
|
|
if token != "" {
|
|
|
|
if err := outputStdoutOrPath(mig.PatPath, token); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2022-12-09 13:04:33 +00:00
|
|
|
|
2023-06-15 08:16:39 +02:00
|
|
|
func outputStdoutOrPath(path string, content string) (err error) {
|
|
|
|
f := os.Stdout
|
|
|
|
if path != "" {
|
|
|
|
f, err = os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
2022-12-09 13:04:33 +00:00
|
|
|
}
|
2023-06-15 08:16:39 +02:00
|
|
|
_, err = fmt.Fprintln(f, content)
|
2022-04-06 08:13:40 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-07-27 10:22:20 +02:00
|
|
|
func (mig *FirstInstance) String() string {
|
2022-04-06 08:13:40 +02:00
|
|
|
return "03_default_instance"
|
|
|
|
}
|
2022-04-12 16:20:17 +02:00
|
|
|
|
2024-01-04 17:12:20 +01:00
|
|
|
func verifyKey(ctx context.Context, key *crypto.KeyConfig, storage crypto.KeyStorage) (err error) {
|
2022-04-12 16:20:17 +02:00
|
|
|
_, err = crypto.LoadKey(key.EncryptionKeyID, storage)
|
|
|
|
if err == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
k, err := crypto.NewKey(key.EncryptionKeyID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2024-01-04 17:12:20 +01:00
|
|
|
return storage.CreateKeys(ctx, k)
|
2022-04-12 16:20:17 +02:00
|
|
|
}
|