mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 00:17:32 +00:00
feat: dynamic issuer (#3481)
* feat: dynamic issuer * dynamic domain handling * key rotation durations * feat: dynamic issuer * make webauthn displayname dynamic
This commit is contained in:
@@ -42,7 +42,7 @@ type Commands struct {
|
||||
domainVerificationValidator func(domain, token, verifier string, checkType http.CheckType) error
|
||||
|
||||
multifactors domain.MultifactorConfigs
|
||||
webauthn *webauthn_helper.WebAuthN
|
||||
webauthnConfig *webauthn_helper.Config
|
||||
keySize int
|
||||
keyAlgorithm crypto.EncryptionAlgorithm
|
||||
privateKeyLifetime time.Duration
|
||||
@@ -60,7 +60,7 @@ func StartCommands(es *eventstore.Eventstore,
|
||||
zitadelRoles []authz.RoleMapping,
|
||||
staticStore static.Storage,
|
||||
authZRepo authz_repo.Repository,
|
||||
webAuthN webauthn_helper.Config,
|
||||
webAuthN *webauthn_helper.Config,
|
||||
idpConfigEncryption,
|
||||
otpEncryption,
|
||||
smtpEncryption,
|
||||
@@ -84,6 +84,7 @@ func StartCommands(es *eventstore.Eventstore,
|
||||
userEncryption: userEncryption,
|
||||
domainVerificationAlg: domainVerificationEncryption,
|
||||
keyAlgorithm: oidcEncryption,
|
||||
webauthnConfig: webAuthN,
|
||||
}
|
||||
|
||||
instance_repo.RegisterEventMappers(repo.eventstore)
|
||||
@@ -107,11 +108,6 @@ func StartCommands(es *eventstore.Eventstore,
|
||||
|
||||
repo.domainVerificationGenerator = crypto.NewEncryptionGenerator(defaults.DomainVerification.VerificationGenerator, repo.domainVerificationAlg)
|
||||
repo.domainVerificationValidator = http.ValidateDomain
|
||||
web, err := webauthn_helper.StartServer(webAuthN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.webauthn = web
|
||||
|
||||
repo.tokenVerifier = authZRepo
|
||||
return repo, nil
|
||||
|
@@ -28,16 +28,6 @@ const (
|
||||
consolePostLogoutPath = console.HandlerPrefix + "/signedout"
|
||||
)
|
||||
|
||||
type AddInstance struct {
|
||||
InstanceName string
|
||||
CustomDomain string
|
||||
FirstOrgName string
|
||||
OwnerEmail string
|
||||
OwnerUsername string
|
||||
OwnerFirstName string
|
||||
OwnerLastName string
|
||||
}
|
||||
|
||||
type InstanceSetup struct {
|
||||
zitadel ZitadelConfig
|
||||
InstanceName string
|
||||
@@ -301,7 +291,7 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup, exte
|
||||
}
|
||||
|
||||
if setup.CustomDomain != "" {
|
||||
validations = append(validations, c.addInstanceDomain(instanceAgg, setup.CustomDomain, false))
|
||||
validations = append(validations, addInstanceDomain(instanceAgg, setup.CustomDomain, false))
|
||||
}
|
||||
|
||||
console := &addOIDCApp{
|
||||
|
@@ -15,7 +15,7 @@ import (
|
||||
|
||||
func (c *Commands) AddInstanceDomain(ctx context.Context, instanceDomain string) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
validation := c.addInstanceDomain(instanceAgg, instanceDomain, false)
|
||||
validation := addInstanceDomain(instanceAgg, instanceDomain, false)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -33,7 +33,7 @@ func (c *Commands) AddInstanceDomain(ctx context.Context, instanceDomain string)
|
||||
|
||||
func (c *Commands) SetPrimaryInstanceDomain(ctx context.Context, instanceDomain string) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
validation := c.setPrimaryInstanceDomain(instanceAgg, instanceDomain)
|
||||
validation := setPrimaryInstanceDomain(instanceAgg, instanceDomain)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -51,7 +51,7 @@ func (c *Commands) SetPrimaryInstanceDomain(ctx context.Context, instanceDomain
|
||||
|
||||
func (c *Commands) RemoveInstanceDomain(ctx context.Context, instanceDomain string) (*domain.ObjectDetails, error) {
|
||||
instanceAgg := instance.NewAggregate(authz.GetInstance(ctx).InstanceID())
|
||||
validation := c.removeInstanceDomain(instanceAgg, instanceDomain)
|
||||
validation := removeInstanceDomain(instanceAgg, instanceDomain)
|
||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -69,16 +69,16 @@ func (c *Commands) RemoveInstanceDomain(ctx context.Context, instanceDomain stri
|
||||
|
||||
func (c *Commands) addGeneratedInstanceDomain(a *instance.Aggregate, instanceName string) preparation.Validation {
|
||||
domain := domain.NewGeneratedInstanceDomain(instanceName, c.iamDomain)
|
||||
return c.addInstanceDomain(a, domain, true)
|
||||
return addInstanceDomain(a, domain, true)
|
||||
}
|
||||
|
||||
func (c *Commands) addInstanceDomain(a *instance.Aggregate, instanceDomain string, generated bool) preparation.Validation {
|
||||
func addInstanceDomain(a *instance.Aggregate, instanceDomain string, generated bool) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if instanceDomain = strings.TrimSpace(instanceDomain); instanceDomain == "" {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "INST-28nlD", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
domainWriteModel, err := c.getInstanceDomainWriteModel(ctx, instanceDomain)
|
||||
domainWriteModel, err := getInstanceDomainWriteModel(ctx, filter, instanceDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func (c *Commands) addInstanceDomain(a *instance.Aggregate, instanceDomain strin
|
||||
events := []eventstore.Command{
|
||||
instance.NewDomainAddedEvent(ctx, &a.Aggregate, instanceDomain, generated),
|
||||
}
|
||||
appWriteModel, err := c.getOIDCAppWriteModel(ctx, authz.GetInstance(ctx).ProjectID(), authz.GetInstance(ctx).ConsoleApplicationID(), "")
|
||||
appWriteModel, err := getOIDCAppWriteModel(ctx, filter, authz.GetInstance(ctx).ProjectID(), authz.GetInstance(ctx).ConsoleApplicationID(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -115,13 +115,13 @@ func (c *Commands) addInstanceDomain(a *instance.Aggregate, instanceDomain strin
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) setPrimaryInstanceDomain(a *instance.Aggregate, instanceDomain string) preparation.Validation {
|
||||
func setPrimaryInstanceDomain(a *instance.Aggregate, instanceDomain string) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if instanceDomain = strings.TrimSpace(instanceDomain); instanceDomain == "" {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "INST-9mWjf", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
domainWriteModel, err := c.getInstanceDomainWriteModel(ctx, instanceDomain)
|
||||
domainWriteModel, err := getInstanceDomainWriteModel(ctx, filter, instanceDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -133,13 +133,13 @@ func (c *Commands) setPrimaryInstanceDomain(a *instance.Aggregate, instanceDomai
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) removeInstanceDomain(a *instance.Aggregate, instanceDomain string) preparation.Validation {
|
||||
func removeInstanceDomain(a *instance.Aggregate, instanceDomain string) preparation.Validation {
|
||||
return func() (preparation.CreateCommands, error) {
|
||||
if instanceDomain = strings.TrimSpace(instanceDomain); instanceDomain == "" {
|
||||
return nil, errors.ThrowInvalidArgument(nil, "INST-39nls", "Errors.Invalid.Argument")
|
||||
}
|
||||
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||
domainWriteModel, err := c.getInstanceDomainWriteModel(ctx, instanceDomain)
|
||||
domainWriteModel, err := getInstanceDomainWriteModel(ctx, filter, instanceDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -154,11 +154,16 @@ func (c *Commands) removeInstanceDomain(a *instance.Aggregate, instanceDomain st
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Commands) getInstanceDomainWriteModel(ctx context.Context, domain string) (*InstanceDomainWriteModel, error) {
|
||||
func getInstanceDomainWriteModel(ctx context.Context, filter preparation.FilterToQueryReducer, domain string) (*InstanceDomainWriteModel, error) {
|
||||
domainWriteModel := NewInstanceDomainWriteModel(ctx, domain)
|
||||
err := c.eventstore.FilterToQueryReducer(ctx, domainWriteModel)
|
||||
events, err := filter(ctx, domainWriteModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return domainWriteModel, nil
|
||||
if len(events) == 0 {
|
||||
return domainWriteModel, nil
|
||||
}
|
||||
domainWriteModel.AppendEvents(events...)
|
||||
err = domainWriteModel.Reduce()
|
||||
return domainWriteModel, err
|
||||
}
|
||||
|
@@ -10,12 +10,7 @@ import (
|
||||
"github.com/caos/zitadel/internal/repository/keypair"
|
||||
)
|
||||
|
||||
const (
|
||||
oidcUser = "OIDC"
|
||||
)
|
||||
|
||||
func (c *Commands) GenerateSigningKeyPair(ctx context.Context, algorithm string) error {
|
||||
ctx = setOIDCCtx(ctx)
|
||||
privateCrypto, publicCrypto, err := crypto.GenerateEncryptedKeyPair(c.keySize, c.keyAlgorithm)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -28,8 +23,7 @@ func (c *Commands) GenerateSigningKeyPair(ctx context.Context, algorithm string)
|
||||
privateKeyExp := time.Now().UTC().Add(c.privateKeyLifetime)
|
||||
publicKeyExp := time.Now().UTC().Add(c.publicKeyLifetime)
|
||||
|
||||
//TODO: InstanceID not available here?
|
||||
keyPairWriteModel := NewKeyPairWriteModel(keyID, "system") //TODO: change with multi issuer
|
||||
keyPairWriteModel := NewKeyPairWriteModel(keyID, authz.GetInstance(ctx).InstanceID())
|
||||
keyAgg := KeyPairAggregateFromWriteModel(&keyPairWriteModel.WriteModel)
|
||||
_, err = c.eventstore.Push(ctx, keypair.NewAddedEvent(
|
||||
ctx,
|
||||
@@ -40,8 +34,3 @@ func (c *Commands) GenerateSigningKeyPair(ctx context.Context, algorithm string)
|
||||
privateKeyExp, publicKeyExp))
|
||||
return err
|
||||
}
|
||||
|
||||
func setOIDCCtx(ctx context.Context) context.Context {
|
||||
//TODO: InstanceID not available here?
|
||||
return authz.SetCtxData(ctx, authz.CtxData{UserID: oidcUser, OrgID: authz.GetInstance(ctx).InstanceID()})
|
||||
}
|
||||
|
@@ -3,8 +3,7 @@ package command
|
||||
import (
|
||||
"github.com/caos/zitadel/internal/domain"
|
||||
"github.com/caos/zitadel/internal/eventstore"
|
||||
keypair "github.com/caos/zitadel/internal/repository/keypair"
|
||||
"github.com/caos/zitadel/internal/repository/project"
|
||||
"github.com/caos/zitadel/internal/repository/keypair"
|
||||
)
|
||||
|
||||
type KeyPairWriteModel struct {
|
||||
@@ -52,7 +51,7 @@ func (wm *KeyPairWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||
ResourceOwner(wm.ResourceOwner).
|
||||
AddQuery().
|
||||
AggregateTypes(project.AggregateType).
|
||||
AggregateTypes(keypair.AggregateType).
|
||||
AggregateIDs(wm.AggregateID).
|
||||
EventTypes(keypair.AddedEventType).
|
||||
Builder()
|
||||
|
@@ -321,3 +321,17 @@ func (c *Commands) getOIDCAppWriteModel(ctx context.Context, projectID, appID, r
|
||||
}
|
||||
return appWriteModel, nil
|
||||
}
|
||||
|
||||
func getOIDCAppWriteModel(ctx context.Context, filter preparation.FilterToQueryReducer, projectID, appID, resourceOwner string) (*OIDCApplicationWriteModel, error) {
|
||||
appWriteModel := NewOIDCApplicationWriteModelWithAppID(projectID, appID, resourceOwner)
|
||||
events, err := filter(ctx, appWriteModel.Query())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(events) == 0 {
|
||||
return appWriteModel, nil
|
||||
}
|
||||
appWriteModel.AppendEvents(events...)
|
||||
err = appWriteModel.Reduce()
|
||||
return appWriteModel, err
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/caos/oidc/pkg/oidc"
|
||||
"github.com/caos/oidc/v2/pkg/oidc"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
|
@@ -157,7 +157,7 @@ func (c *Commands) addHumanWebAuthN(ctx context.Context, userID, resourceowner s
|
||||
if accountName == "" {
|
||||
accountName = user.EmailAddress
|
||||
}
|
||||
webAuthN, err := c.webauthn.BeginRegistration(user, accountName, authenticatorPlatform, domain.UserVerificationRequirementDiscouraged, isLoginUI, tokens...)
|
||||
webAuthN, err := c.webauthnConfig.BeginRegistration(ctx, user, accountName, authenticatorPlatform, domain.UserVerificationRequirementDiscouraged, isLoginUI, tokens...)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
@@ -272,7 +272,7 @@ func (c *Commands) verifyHumanWebAuthN(ctx context.Context, userID, resourceowne
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
_, token := domain.GetTokenToVerify(tokens)
|
||||
webAuthN, err := c.webauthn.FinishRegistration(user, token, tokenName, credentialData, userAgentID != "")
|
||||
webAuthN, err := c.webauthnConfig.FinishRegistration(ctx, user, token, tokenName, credentialData, userAgentID != "")
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
@@ -343,7 +343,7 @@ func (c *Commands) beginWebAuthNLogin(ctx context.Context, userID, resourceOwner
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
webAuthNLogin, err := c.webauthn.BeginLogin(human, domain.UserVerificationRequirementDiscouraged, isLoginUI, tokens...)
|
||||
webAuthNLogin, err := c.webauthnConfig.BeginLogin(ctx, human, domain.UserVerificationRequirementDiscouraged, isLoginUI, tokens...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -454,7 +454,7 @@ func (c *Commands) finishWebAuthNLogin(ctx context.Context, userID, resourceOwne
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
keyID, signCount, err := c.webauthn.FinishLogin(human, webAuthN, credentialData, isLoginUI, tokens...)
|
||||
keyID, signCount, err := c.webauthnConfig.FinishLogin(ctx, human, webAuthN, credentialData, isLoginUI, tokens...)
|
||||
if err != nil && keyID == nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user