fix: use system secret config if generator type does not exist on instance (#6420)

* fix: use system secret config if generator type does not exist on instance

* remove unused idGenerator
This commit is contained in:
Livio Spring 2023-08-23 10:04:29 +02:00 committed by GitHub
parent 37c527f18e
commit cbd2ef0612
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 195 additions and 42 deletions

View File

@ -91,6 +91,7 @@ func (mig *FirstInstance) Execute(ctx context.Context) error {
0,
0,
0,
nil,
)
if err != nil {
return err

View File

@ -57,6 +57,7 @@ func (mig *externalConfigChange) Execute(ctx context.Context) error {
0,
0,
0,
nil,
)
if err != nil {

View File

@ -202,6 +202,7 @@ func startZitadel(config *Config, masterKey string, server chan<- *Server) error
config.OIDC.DefaultAccessTokenLifetime,
config.OIDC.DefaultRefreshTokenExpiration,
config.OIDC.DefaultRefreshTokenIdleExpiration,
config.DefaultInstance.SecretGenerators,
)
if err != nil {
return fmt.Errorf("cannot start commands: %w", err)

View File

@ -71,6 +71,7 @@ type Commands struct {
privateKeyLifetime time.Duration
publicKeyLifetime time.Duration
certificateLifetime time.Duration
defaultSecretGenerators *SecretGenerators
}
func StartCommands(
@ -89,6 +90,7 @@ func StartCommands(
defaultAccessTokenLifetime,
defaultRefreshTokenLifetime,
defaultRefreshTokenIdleLifetime time.Duration,
defaultSecretGenerators *SecretGenerators,
) (repo *Commands, err error) {
if externalDomain == "" {
return nil, errors.ThrowInvalidArgument(nil, "COMMAND-Df21s", "no external domain specified")
@ -125,6 +127,7 @@ func StartCommands(
defaultAccessTokenLifetime: defaultAccessTokenLifetime,
defaultRefreshTokenLifetime: defaultRefreshTokenLifetime,
defaultRefreshTokenIdleLifetime: defaultRefreshTokenIdleLifetime,
defaultSecretGenerators: defaultSecretGenerators,
}
instance_repo.RegisterEventMappers(repo.eventstore)

View File

@ -76,3 +76,26 @@ func secretGeneratorConfig(ctx context.Context, filter preparation.FilterToQuery
IncludeSymbols: wm.IncludeSymbols,
}, nil
}
func secretGeneratorConfigWithDefault(ctx context.Context, filter preparation.FilterToQueryReducer, typ domain.SecretGeneratorType, defaultGenerator *crypto.GeneratorConfig) (*crypto.GeneratorConfig, error) {
wm := NewInstanceSecretGeneratorConfigWriteModel(ctx, typ)
events, err := filter(ctx, wm.Query())
if err != nil {
return nil, err
}
wm.AppendEvents(events...)
if err := wm.Reduce(); err != nil {
return nil, err
}
if wm.State != domain.SecretGeneratorStateActive {
return defaultGenerator, nil
}
return &crypto.GeneratorConfig{
Length: wm.Length,
Expiry: wm.Expiry,
IncludeLowerLetters: wm.IncludeLowerLetters,
IncludeUpperLetters: wm.IncludeUpperLetters,
IncludeDigits: wm.IncludeDigits,
IncludeSymbols: wm.IncludeSymbols,
}, nil
}

View File

@ -34,23 +34,11 @@ const (
type InstanceSetup struct {
zitadel ZitadelConfig
idGenerator id.Generator
InstanceName string
CustomDomain string
DefaultLanguage language.Tag
Org InstanceOrgSetup
SecretGenerators struct {
PasswordSaltCost uint
ClientSecret *crypto.GeneratorConfig
InitializeUserCode *crypto.GeneratorConfig
EmailVerificationCode *crypto.GeneratorConfig
PhoneVerificationCode *crypto.GeneratorConfig
PasswordVerificationCode *crypto.GeneratorConfig
PasswordlessInitCode *crypto.GeneratorConfig
DomainVerification *crypto.GeneratorConfig
OTPSMS *crypto.GeneratorConfig
OTPEmail *crypto.GeneratorConfig
}
SecretGenerators *SecretGenerators
PasswordComplexityPolicy struct {
MinLength uint64
HasLowercase bool
@ -126,6 +114,19 @@ type InstanceSetup struct {
}
}
type SecretGenerators struct {
PasswordSaltCost uint
ClientSecret *crypto.GeneratorConfig
InitializeUserCode *crypto.GeneratorConfig
EmailVerificationCode *crypto.GeneratorConfig
PhoneVerificationCode *crypto.GeneratorConfig
PasswordVerificationCode *crypto.GeneratorConfig
PasswordlessInitCode *crypto.GeneratorConfig
DomainVerification *crypto.GeneratorConfig
OTPSMS *crypto.GeneratorConfig
OTPEmail *crypto.GeneratorConfig
}
type ZitadelConfig struct {
projectID string
mgmtAppID string

View File

@ -278,6 +278,7 @@ func (c *Commands) HumanSendOTPSMS(ctx context.Context, userID, resourceOwner st
authRequest,
smsWriteModel,
domain.SecretGeneratorTypeOTPSMS,
c.defaultSecretGenerators.OTPSMS,
codeAddedEvent,
)
}
@ -398,6 +399,7 @@ func (c *Commands) HumanSendOTPEmail(ctx context.Context, userID, resourceOwner
authRequest,
smsWriteModel,
domain.SecretGeneratorTypeOTPEmail,
c.defaultSecretGenerators.OTPEmail,
codeAddedEvent,
)
}
@ -442,6 +444,7 @@ func (c *Commands) sendHumanOTP(
authRequest *domain.AuthRequest,
writeModelByID func(ctx context.Context, userID string, resourceOwner string) (OTPWriteModel, error),
secretGeneratorType domain.SecretGeneratorType,
defaultSecretGenerator *crypto.GeneratorConfig,
codeAddedEvent func(ctx context.Context, aggregate *eventstore.Aggregate, code *crypto.CryptoValue, expiry time.Duration, info *user.AuthRequestInfo) eventstore.Command,
) (err error) {
if userID == "" {
@ -454,7 +457,7 @@ func (c *Commands) sendHumanOTP(
if !existingOTP.OTPAdded() {
return caos_errs.ThrowPreconditionFailed(nil, "COMMAND-SFD52", "Errors.User.MFA.OTP.NotReady")
}
config, err := secretGeneratorConfig(ctx, c.eventstore.Filter, secretGeneratorType)
config, err := secretGeneratorConfigWithDefault(ctx, c.eventstore.Filter, secretGeneratorType, defaultSecretGenerator)
if err != nil {
return err
}

View File

@ -1249,9 +1249,20 @@ func TestCommandSide_RemoveHumanOTPSMS(t *testing.T) {
func TestCommandSide_HumanSendOTPSMS(t *testing.T) {
ctx := authz.NewMockContext("inst1", "org1", "user1")
defaultGenerators := &SecretGenerators{
OTPSMS: &crypto.GeneratorConfig{
Length: 8,
Expiry: time.Hour,
IncludeLowerLetters: true,
IncludeUpperLetters: true,
IncludeDigits: true,
IncludeSymbols: true,
},
}
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
userEncryption crypto.EncryptionAlgorithm
defaultSecretGenerators *SecretGenerators
}
type (
args struct {
@ -1275,6 +1286,7 @@ func TestCommandSide_HumanSendOTPSMS(t *testing.T) {
name: "userid missing, invalid argument error",
fields: fields{
eventstore: expectEventstore(),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
@ -1291,6 +1303,7 @@ func TestCommandSide_HumanSendOTPSMS(t *testing.T) {
eventstore: expectEventstore(
expectFilter(),
),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
@ -1344,6 +1357,51 @@ func TestCommandSide_HumanSendOTPSMS(t *testing.T) {
),
),
userEncryption: crypto.CreateMockEncryptionAlgWithCode(gomock.NewController(t), "12345678"),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
userID: "user1",
resourceOwner: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "successful add (without secret config)",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanOTPSMSAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
),
),
),
expectFilter(),
expectPush(
[]*repository.Event{
eventFromEventPusherWithInstanceID("inst1",
user.NewHumanOTPSMSCodeAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("12345678"),
},
time.Hour,
nil,
),
),
},
),
),
userEncryption: crypto.CreateMockEncryptionAlgWithCode(gomock.NewController(t), "12345678"),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
@ -1407,6 +1465,7 @@ func TestCommandSide_HumanSendOTPSMS(t *testing.T) {
),
),
userEncryption: crypto.CreateMockEncryptionAlgWithCode(gomock.NewController(t), "12345678"),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
@ -1434,6 +1493,7 @@ func TestCommandSide_HumanSendOTPSMS(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
userEncryption: tt.fields.userEncryption,
defaultSecretGenerators: tt.fields.defaultSecretGenerators,
}
err := r.HumanSendOTPSMS(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.authRequest)
assert.ErrorIs(t, err, tt.res.err)
@ -2176,9 +2236,20 @@ func TestCommandSide_RemoveHumanOTPEmail(t *testing.T) {
func TestCommandSide_HumanSendOTPEmail(t *testing.T) {
ctx := authz.NewMockContext("inst1", "org1", "user1")
defaultGenerators := &SecretGenerators{
OTPEmail: &crypto.GeneratorConfig{
Length: 8,
Expiry: time.Hour,
IncludeLowerLetters: true,
IncludeUpperLetters: true,
IncludeDigits: true,
IncludeSymbols: true,
},
}
type fields struct {
eventstore func(*testing.T) *eventstore.Eventstore
userEncryption crypto.EncryptionAlgorithm
defaultSecretGenerators *SecretGenerators
}
type (
args struct {
@ -2202,6 +2273,7 @@ func TestCommandSide_HumanSendOTPEmail(t *testing.T) {
name: "userid missing, invalid argument error",
fields: fields{
eventstore: expectEventstore(),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
@ -2218,6 +2290,7 @@ func TestCommandSide_HumanSendOTPEmail(t *testing.T) {
eventstore: expectEventstore(
expectFilter(),
),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
@ -2271,6 +2344,51 @@ func TestCommandSide_HumanSendOTPEmail(t *testing.T) {
),
),
userEncryption: crypto.CreateMockEncryptionAlgWithCode(gomock.NewController(t), "12345678"),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
userID: "user1",
resourceOwner: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "successful add (without secret config)",
fields: fields{
eventstore: expectEventstore(
expectFilter(
eventFromEventPusher(
user.NewHumanOTPEmailAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
),
),
),
expectFilter(),
expectPush(
[]*repository.Event{
eventFromEventPusherWithInstanceID("inst1",
user.NewHumanOTPEmailCodeAddedEvent(ctx,
&user.NewAggregate("user1", "org1").Aggregate,
&crypto.CryptoValue{
CryptoType: crypto.TypeEncryption,
Algorithm: "enc",
KeyID: "id",
Crypted: []byte("12345678"),
},
time.Hour,
nil,
),
),
},
),
),
userEncryption: crypto.CreateMockEncryptionAlgWithCode(gomock.NewController(t), "12345678"),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
@ -2334,6 +2452,7 @@ func TestCommandSide_HumanSendOTPEmail(t *testing.T) {
),
),
userEncryption: crypto.CreateMockEncryptionAlgWithCode(gomock.NewController(t), "12345678"),
defaultSecretGenerators: defaultGenerators,
},
args: args{
ctx: ctx,
@ -2361,6 +2480,7 @@ func TestCommandSide_HumanSendOTPEmail(t *testing.T) {
r := &Commands{
eventstore: tt.fields.eventstore(t),
userEncryption: tt.fields.userEncryption,
defaultSecretGenerators: tt.fields.defaultSecretGenerators,
}
err := r.HumanSendOTPEmail(tt.args.ctx, tt.args.userID, tt.args.resourceOwner, tt.args.authRequest)
assert.ErrorIs(t, err, tt.res.err)