chore: merge rc into next (#6037)

### Definition of Ready

- [ ] I am happy with the code
- [ ] Short description of the feature/issue is added in the pr
description
- [ ] PR is linked to the corresponding user story
- [ ] Acceptance criteria are met
- [ ] All open todos and follow ups are defined in a new ticket and
justified
- [ ] Deviations from the acceptance criteria and design are agreed with
the PO and documented.
- [ ] No debug or dead code
- [ ] My code has no repetitions
- [ ] Critical parts are tested automatically
- [ ] Where possible E2E tests are implemented
- [ ] Documentation/examples are up-to-date
- [ ] All non-functional requirements are met
- [ ] Functionality of the acceptance criteria is checked manually on
the dev system.
This commit is contained in:
Silvan 2023-06-15 17:29:20 +02:00 committed by GitHub
commit 55d589cd44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 84 additions and 31 deletions

View File

@ -1,10 +1,7 @@
blank_issues_enabled: true blank_issues_enabled: true
contact_links: contact_links:
- name: 🚀 Feature Request
url: https://github.com/zitadel/zitadel/discussions/categories/ideas
about: Tell us about your idea in the discussions
- name: ❓ Questions - name: ❓ Questions
url: https://github.com/zitadel/zitadel/discussions/categories/q-a url: https://github.com/zitadel/zitadel/discussions/categories/q-a
about: Ask for help in our Q&A discussions about: Ask for help in our Q&A discussions
- name: 💬 ZITADEL Chat - name: 💬 ZITADEL Community Chat
url: https://zitadel.com/chat url: https://zitadel.com/chat

View File

@ -1,6 +1,5 @@
name: 📄 Documentation name: 📄 Documentation
description: Create an issue for missing or wrong documentation. description: Create an issue for missing or wrong documentation.
title:
labels: ["docs"] labels: ["docs"]
body: body:
- type: markdown - type: markdown

View File

@ -1,6 +1,5 @@
name: 🛠️ Improvement name: 🛠️ Improvement
description: description: "Create an new issue for an improvment in ZITADEL"
title:
labels: ["improvement"] labels: ["improvement"]
body: body:
- type: markdown - type: markdown

View File

@ -1,6 +1,5 @@
name: 💡 Proposal / Feature request name: 💡 Proposal / Feature request
description: description: "Create an issue for a feature request/proposal."
title:
labels: ["enhancement"] labels: ["enhancement"]
body: body:
- type: markdown - type: markdown

View File

@ -23,10 +23,12 @@ type FirstInstance struct {
DefaultLanguage language.Tag DefaultLanguage language.Tag
Org command.OrgSetup Org command.OrgSetup
MachineKeyPath string MachineKeyPath string
PatPath string
instanceSetup command.InstanceSetup instanceSetup command.InstanceSetup
userEncryptionKey *crypto.KeyConfig userEncryptionKey *crypto.KeyConfig
smtpEncryptionKey *crypto.KeyConfig smtpEncryptionKey *crypto.KeyConfig
oidcEncryptionKey *crypto.KeyConfig
masterKey string masterKey string
db *sql.DB db *sql.DB
es *eventstore.Eventstore es *eventstore.Eventstore
@ -59,6 +61,14 @@ func (mig *FirstInstance) Execute(ctx context.Context) error {
return err return err
} }
if err = verifyKey(mig.oidcEncryptionKey, keyStorage); err != nil {
return err
}
oidcEncryption, err := crypto.NewAESCrypto(mig.oidcEncryptionKey, keyStorage)
if err != nil {
return err
}
cmd, err := command.StartCommands(mig.es, cmd, err := command.StartCommands(mig.es,
mig.defaults, mig.defaults,
mig.zitadelRoles, mig.zitadelRoles,
@ -73,13 +83,12 @@ func (mig *FirstInstance) Execute(ctx context.Context) error {
nil, nil,
userAlg, userAlg,
nil, nil,
nil, oidcEncryption,
nil, nil,
nil, nil,
nil, nil,
nil, nil,
) )
if err != nil { if err != nil {
return err return err
} }
@ -101,25 +110,43 @@ func (mig *FirstInstance) Execute(ctx context.Context) error {
} }
} }
_, _, key, _, err := cmd.SetUpInstance(ctx, &mig.instanceSetup) _, token, key, _, err := cmd.SetUpInstance(ctx, &mig.instanceSetup)
if key == nil { 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)) {
return err return err
} }
if key != nil {
keyDetails, err := key.Detail()
if err != nil {
return err
}
if err := outputStdoutOrPath(mig.MachineKeyPath, string(keyDetails)); err != nil {
return err
}
}
if token != "" {
if err := outputStdoutOrPath(mig.PatPath, token); err != nil {
return err
}
}
return nil
}
func outputStdoutOrPath(path string, content string) (err error) {
f := os.Stdout f := os.Stdout
if mig.MachineKeyPath != "" { if path != "" {
f, err = os.OpenFile(mig.MachineKeyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) f, err = os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer f.Close()
} }
_, err = fmt.Fprintln(f, content)
keyDetails, err := key.Detail()
if err != nil {
return err
}
_, err = fmt.Fprintln(f, string(keyDetails))
return err return err
} }

View File

@ -72,6 +72,7 @@ type Steps struct {
type encryptionKeyConfig struct { type encryptionKeyConfig struct {
User *crypto.KeyConfig User *crypto.KeyConfig
SMTP *crypto.KeyConfig SMTP *crypto.KeyConfig
OIDC *crypto.KeyConfig
} }
func MustNewSteps(v *viper.Viper) *Steps { func MustNewSteps(v *viper.Viper) *Steps {

View File

@ -75,6 +75,7 @@ func Setup(config *Config, steps *Steps, masterKey string) {
steps.FirstInstance.instanceSetup = config.DefaultInstance steps.FirstInstance.instanceSetup = config.DefaultInstance
steps.FirstInstance.userEncryptionKey = config.EncryptionKeys.User steps.FirstInstance.userEncryptionKey = config.EncryptionKeys.User
steps.FirstInstance.smtpEncryptionKey = config.EncryptionKeys.SMTP steps.FirstInstance.smtpEncryptionKey = config.EncryptionKeys.SMTP
steps.FirstInstance.oidcEncryptionKey = config.EncryptionKeys.OIDC
steps.FirstInstance.masterKey = masterKey steps.FirstInstance.masterKey = masterKey
steps.FirstInstance.db = dbClient.DB steps.FirstInstance.db = dbClient.DB
steps.FirstInstance.es = eventstoreClient steps.FirstInstance.es = eventstoreClient

View File

@ -1,5 +1,6 @@
FirstInstance: FirstInstance:
MachineKeyPath: MachineKeyPath:
PatPath:
InstanceName: ZITADEL InstanceName: ZITADEL
DefaultLanguage: en DefaultLanguage: en
Org: Org:
@ -30,6 +31,8 @@ FirstInstance:
MachineKey: MachineKey:
ExpirationDate: ExpirationDate:
Type: Type:
Pat:
ExpirationDate:
CorrectCreationDate: CorrectCreationDate:
FailAfter: 5m FailAfter: 5m

View File

@ -113,13 +113,11 @@ func createInstancePbToAddMachine(req *system_pb.CreateInstanceRequest_Machine,
// Scopes are currently static and can not be overwritten // Scopes are currently static and can not be overwritten
Scopes: []string{oidc.ScopeOpenID, z_oidc.ScopeUserMetaData, z_oidc.ScopeResourceOwner}, Scopes: []string{oidc.ScopeOpenID, z_oidc.ScopeUserMetaData, z_oidc.ScopeResourceOwner},
} }
if req.GetPersonalAccessToken().GetExpirationDate().IsValid() {
if !defaultMachine.Pat.ExpirationDate.IsZero() {
pat.ExpirationDate = defaultMachine.Pat.ExpirationDate
} else if req.PersonalAccessToken.ExpirationDate.IsValid() {
pat.ExpirationDate = req.PersonalAccessToken.ExpirationDate.AsTime() pat.ExpirationDate = req.PersonalAccessToken.ExpirationDate.AsTime()
} else if defaultMachine.Pat != nil && !defaultMachine.Pat.ExpirationDate.IsZero() {
pat.ExpirationDate = defaultMachine.Pat.ExpirationDate
} }
machine.Pat = &pat machine.Pat = &pat
} }

View File

@ -292,14 +292,14 @@ func (l *Login) handleExternalUserAuthenticated(
l.renderError(w, r, authReq, externalErr) l.renderError(w, r, authReq, externalErr)
return return
} }
externalUser, externalUserChange, err := l.runPostExternalAuthenticationActions(externalUser, tokens(session), authReq, r, user, externalErr) externalUser, externalUserChange, err := l.runPostExternalAuthenticationActions(externalUser, tokens(session), authReq, r, user, nil)
if err != nil { if err != nil {
l.renderError(w, r, authReq, err) l.renderError(w, r, authReq, err)
return return
} }
// if action is done and no user linked then link or register // if action is done and no user linked then link or register
if errors.IsNotFound(externalErr) { if errors.IsNotFound(externalErr) {
l.externalUserNotExisting(w, r, authReq, provider, externalUser) l.externalUserNotExisting(w, r, authReq, provider, externalUser, externalUserChange)
return return
} }
if provider.IsAutoUpdate || len(externalUser.Metadatas) > 0 || externalUserChange { if provider.IsAutoUpdate || len(externalUser.Metadatas) > 0 || externalUserChange {
@ -334,7 +334,7 @@ func (l *Login) handleExternalUserAuthenticated(
// * external not found overview: // * external not found overview:
// - creation by user // - creation by user
// - linking to existing user // - linking to existing user
func (l *Login) externalUserNotExisting(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, provider *query.IDPTemplate, externalUser *domain.ExternalUser) { func (l *Login) externalUserNotExisting(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest, provider *query.IDPTemplate, externalUser *domain.ExternalUser, changed bool) {
resourceOwner := authz.GetInstance(r.Context()).DefaultOrganisationID() resourceOwner := authz.GetInstance(r.Context()).DefaultOrganisationID()
if authReq.RequestedOrgID != "" && authReq.RequestedOrgID != resourceOwner { if authReq.RequestedOrgID != "" && authReq.RequestedOrgID != resourceOwner {
@ -360,6 +360,12 @@ func (l *Login) externalUserNotExisting(w http.ResponseWriter, r *http.Request,
l.renderExternalNotFoundOption(w, r, authReq, orgIAMPolicy, human, idpLink, err) l.renderExternalNotFoundOption(w, r, authReq, orgIAMPolicy, human, idpLink, err)
return return
} }
if changed {
if err := l.authRepo.SetLinkingUser(r.Context(), authReq, externalUser); err != nil {
l.renderError(w, r, authReq, err)
return
}
}
l.autoCreateExternalUser(w, r, authReq) l.autoCreateExternalUser(w, r, authReq)
} }

View File

@ -17,6 +17,7 @@ type AuthRequestRepository interface {
CheckLoginName(ctx context.Context, id, loginName, userAgentID string) error CheckLoginName(ctx context.Context, id, loginName, userAgentID string) error
CheckExternalUserLogin(ctx context.Context, authReqID, userAgentID string, user *domain.ExternalUser, info *domain.BrowserInfo) error CheckExternalUserLogin(ctx context.Context, authReqID, userAgentID string, user *domain.ExternalUser, info *domain.BrowserInfo) error
SetExternalUserLogin(ctx context.Context, authReqID, userAgentID string, user *domain.ExternalUser) error SetExternalUserLogin(ctx context.Context, authReqID, userAgentID string, user *domain.ExternalUser) error
SetLinkingUser(ctx context.Context, request *domain.AuthRequest, externalUser *domain.ExternalUser) error
SelectUser(ctx context.Context, id, userID, userAgentID string) error SelectUser(ctx context.Context, id, userID, userAgentID string) error
SelectExternalIDP(ctx context.Context, authReqID, idpConfigID, userAgentID string) error SelectExternalIDP(ctx context.Context, authReqID, idpConfigID, userAgentID string) error
VerifyPassword(ctx context.Context, id, userID, resourceOwner, password, userAgentID string, info *domain.BrowserInfo) error VerifyPassword(ctx context.Context, id, userID, resourceOwner, password, userAgentID string, info *domain.BrowserInfo) error

View File

@ -278,6 +278,16 @@ func (repo *AuthRequestRepo) SetExternalUserLogin(ctx context.Context, authReqID
return repo.AuthRequests.UpdateAuthRequest(ctx, request) return repo.AuthRequests.UpdateAuthRequest(ctx, request)
} }
func (repo *AuthRequestRepo) SetLinkingUser(ctx context.Context, request *domain.AuthRequest, externalUser *domain.ExternalUser) error {
for i, user := range request.LinkingUsers {
if user.ExternalUserID == externalUser.ExternalUserID {
request.LinkingUsers[i] = externalUser
return repo.AuthRequests.UpdateAuthRequest(ctx, request)
}
}
return nil
}
func (repo *AuthRequestRepo) setLinkingUser(ctx context.Context, request *domain.AuthRequest, externalUser *domain.ExternalUser) error { func (repo *AuthRequestRepo) setLinkingUser(ctx context.Context, request *domain.AuthRequest, externalUser *domain.ExternalUser) error {
request.LinkingUsers = append(request.LinkingUsers, externalUser) request.LinkingUsers = append(request.LinkingUsers, externalUser)
return repo.AuthRequests.UpdateAuthRequest(ctx, request) return repo.AuthRequests.UpdateAuthRequest(ctx, request)

View File

@ -351,6 +351,10 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
Event: instance.OIDCIDPMigratedAzureADEventType, Event: instance.OIDCIDPMigratedAzureADEventType,
Reduce: p.reduceOIDCIDPMigratedAzureAD, Reduce: p.reduceOIDCIDPMigratedAzureAD,
}, },
{
Event: instance.OIDCIDPMigratedGoogleEventType,
Reduce: p.reduceOIDCIDPMigratedGoogle,
},
{ {
Event: instance.JWTIDPAddedEventType, Event: instance.JWTIDPAddedEventType,
Reduce: p.reduceJWTIDPAdded, Reduce: p.reduceJWTIDPAdded,
@ -472,6 +476,14 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
Event: org.OIDCIDPChangedEventType, Event: org.OIDCIDPChangedEventType,
Reduce: p.reduceOIDCIDPChanged, Reduce: p.reduceOIDCIDPChanged,
}, },
{
Event: org.OIDCIDPMigratedAzureADEventType,
Reduce: p.reduceOIDCIDPMigratedAzureAD,
},
{
Event: org.OIDCIDPMigratedGoogleEventType,
Reduce: p.reduceOIDCIDPMigratedGoogle,
},
{ {
Event: org.JWTIDPAddedEventType, Event: org.JWTIDPAddedEventType,
Reduce: p.reduceJWTIDPAdded, Reduce: p.reduceJWTIDPAdded,

View File

@ -263,7 +263,7 @@ func NewOIDCIDPMigratedGoogleEvent(
eventstore.NewBaseEventForPush( eventstore.NewBaseEventForPush(
ctx, ctx,
aggregate, aggregate,
OIDCIDPMigratedAzureADEventType, OIDCIDPMigratedGoogleEventType,
), ),
id, id,
name, name,