mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 16:47:32 +00:00
feat: initial admin PAT has IAM_LOGIN_CLIENT (#10143)
# Which Problems Are Solved We provide a seamless way to initialize Zitadel and the login together. # How the Problems Are Solved Additionally to the `IAM_OWNER` role, a set up admin user also gets the `IAM_LOGIN_CLIENT` role if it is a machine user with a PAT. # Additional Changes - Simplifies the load balancing example, as the intermediate configuration step is not needed anymore. # Additional Context - Depends on #10116 - Contributes to https://github.com/zitadel/zitadel-charts/issues/332 - Contributes to https://github.com/zitadel/zitadel/issues/10016 --------- Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com>
This commit is contained in:
@@ -839,6 +839,13 @@ DefaultInstance:
|
|||||||
Pat:
|
Pat:
|
||||||
# date format: 2023-01-01T00:00:00Z
|
# date format: 2023-01-01T00:00:00Z
|
||||||
ExpirationDate: # ZITADEL_DEFAULTINSTANCE_ORG_MACHINE_PAT_EXPIRATIONDATE
|
ExpirationDate: # ZITADEL_DEFAULTINSTANCE_ORG_MACHINE_PAT_EXPIRATIONDATE
|
||||||
|
LoginClient:
|
||||||
|
Machine:
|
||||||
|
Username: # ZITADEL_DEFAULTINSTANCE_ORG_LOGINCLIENT_MACHINE_USERNAME
|
||||||
|
Name: # ZITADEL_DEFAULTINSTANCE_ORG_LOGINCLIENT_MACHINE_NAME
|
||||||
|
Pat:
|
||||||
|
# date format: 2023-01-01T00:00:00Z
|
||||||
|
ExpirationDate: # ZITADEL_DEFAULTINSTANCE_ORG_LOGINCLIENT_PAT_EXPIRATIONDATE
|
||||||
SecretGenerators:
|
SecretGenerators:
|
||||||
ClientSecret:
|
ClientSecret:
|
||||||
Length: 64 # ZITADEL_DEFAULTINSTANCE_SECRETGENERATORS_CLIENTSECRET_LENGTH
|
Length: 64 # ZITADEL_DEFAULTINSTANCE_SECRETGENERATORS_CLIENTSECRET_LENGTH
|
||||||
|
@@ -20,12 +20,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FirstInstance struct {
|
type FirstInstance struct {
|
||||||
InstanceName string
|
InstanceName string
|
||||||
DefaultLanguage language.Tag
|
DefaultLanguage language.Tag
|
||||||
Org command.InstanceOrgSetup
|
Org command.InstanceOrgSetup
|
||||||
MachineKeyPath string
|
MachineKeyPath string
|
||||||
PatPath string
|
PatPath string
|
||||||
Features *command.InstanceFeatures
|
LoginClientPatPath string
|
||||||
|
Features *command.InstanceFeatures
|
||||||
|
|
||||||
Skip bool
|
Skip bool
|
||||||
|
|
||||||
@@ -121,16 +122,18 @@ func (mig *FirstInstance) Execute(ctx context.Context, _ eventstore.Event) error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, token, key, _, err := cmd.SetUpInstance(ctx, &mig.instanceSetup)
|
_, token, key, loginClientToken, _, err := cmd.SetUpInstance(ctx, &mig.instanceSetup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if mig.instanceSetup.Org.Machine != nil &&
|
if (mig.instanceSetup.Org.Machine != nil &&
|
||||||
((mig.instanceSetup.Org.Machine.Pat != nil && token == "") ||
|
((mig.instanceSetup.Org.Machine.Pat != nil && token == "") ||
|
||||||
(mig.instanceSetup.Org.Machine.MachineKey != nil && key == nil)) {
|
(mig.instanceSetup.Org.Machine.MachineKey != nil && key == nil))) ||
|
||||||
|
(mig.instanceSetup.Org.LoginClient != nil &&
|
||||||
|
(mig.instanceSetup.Org.LoginClient.Pat != nil && loginClientToken == "")) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return mig.outputMachineAuthentication(key, token)
|
return mig.outputMachineAuthentication(key, token, loginClientToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mig *FirstInstance) verifyEncryptionKeys(ctx context.Context) (*crypto_db.Database, error) {
|
func (mig *FirstInstance) verifyEncryptionKeys(ctx context.Context) (*crypto_db.Database, error) {
|
||||||
@@ -150,7 +153,7 @@ func (mig *FirstInstance) verifyEncryptionKeys(ctx context.Context) (*crypto_db.
|
|||||||
return keyStorage, nil
|
return keyStorage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mig *FirstInstance) outputMachineAuthentication(key *command.MachineKey, token string) error {
|
func (mig *FirstInstance) outputMachineAuthentication(key *command.MachineKey, token, loginClientToken string) error {
|
||||||
if key != nil {
|
if key != nil {
|
||||||
keyDetails, err := key.Detail()
|
keyDetails, err := key.Detail()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -165,6 +168,11 @@ func (mig *FirstInstance) outputMachineAuthentication(key *command.MachineKey, t
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if loginClientToken != "" {
|
||||||
|
if err := outputStdoutOrPath(mig.LoginClientPatPath, loginClientToken); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@ FirstInstance:
|
|||||||
MachineKeyPath: # ZITADEL_FIRSTINSTANCE_MACHINEKEYPATH
|
MachineKeyPath: # ZITADEL_FIRSTINSTANCE_MACHINEKEYPATH
|
||||||
# The personal access token from the section FirstInstance.Org.Machine.Pat is written to the PatPath.
|
# The personal access token from the section FirstInstance.Org.Machine.Pat is written to the PatPath.
|
||||||
PatPath: # ZITADEL_FIRSTINSTANCE_PATPATH
|
PatPath: # ZITADEL_FIRSTINSTANCE_PATPATH
|
||||||
|
LoginClientPatPath: # ZITADEL_FIRSTINSTANCE_LOGINCLIENTPATPATH
|
||||||
InstanceName: ZITADEL # ZITADEL_FIRSTINSTANCE_INSTANCENAME
|
InstanceName: ZITADEL # ZITADEL_FIRSTINSTANCE_INSTANCENAME
|
||||||
DefaultLanguage: en # ZITADEL_FIRSTINSTANCE_DEFAULTLANGUAGE
|
DefaultLanguage: en # ZITADEL_FIRSTINSTANCE_DEFAULTLANGUAGE
|
||||||
Org:
|
Org:
|
||||||
@@ -46,6 +47,13 @@ FirstInstance:
|
|||||||
Pat:
|
Pat:
|
||||||
# date format: 2023-01-01T00:00:00Z
|
# date format: 2023-01-01T00:00:00Z
|
||||||
ExpirationDate: # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_PAT_EXPIRATIONDATE
|
ExpirationDate: # ZITADEL_FIRSTINSTANCE_ORG_MACHINE_PAT_EXPIRATIONDATE
|
||||||
|
LoginClient:
|
||||||
|
Machine:
|
||||||
|
Username: # ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_MACHINE_USERNAME
|
||||||
|
Name: # ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_MACHINE_NAME
|
||||||
|
Pat:
|
||||||
|
# date format: 2023-01-01T00:00:00Z
|
||||||
|
ExpirationDate: # ZITADEL_FIRSTINSTANCE_ORG_LOGINCLIENT_PAT_EXPIRATIONDATE
|
||||||
|
|
||||||
CorrectCreationDate:
|
CorrectCreationDate:
|
||||||
FailAfter: 5m # ZITADEL_CORRECTCREATIONDATE_FAILAFTER
|
FailAfter: 5m # ZITADEL_CORRECTCREATIONDATE_FAILAFTER
|
||||||
|
@@ -1 +1 @@
|
|||||||
.env-file
|
.env-file
|
@@ -41,17 +41,17 @@ services:
|
|||||||
user: root
|
user: root
|
||||||
entrypoint: '/bin/sh'
|
entrypoint: '/bin/sh'
|
||||||
command:
|
command:
|
||||||
- -c
|
- -c
|
||||||
- >
|
- >
|
||||||
/app/zitadel setup
|
/app/zitadel setup
|
||||||
--config /example-zitadel-config.yaml
|
--config /example-zitadel-config.yaml
|
||||||
--config /example-zitadel-secrets.yaml
|
--config /example-zitadel-secrets.yaml
|
||||||
--steps /example-zitadel-init-steps.yaml
|
--steps /example-zitadel-init-steps.yaml
|
||||||
--masterkey ${ZITADEL_MASTERKEY} &&
|
--masterkey ${ZITADEL_MASTERKEY} &&
|
||||||
mv /pat /.env-file/pat || exit 0 &&
|
mv /pat /.env-file/pat || exit 0 &&
|
||||||
echo ZITADEL_SERVICE_USER_TOKEN=$(cat /.env-file/pat) > /.env-file/.env &&
|
echo ZITADEL_SERVICE_USER_TOKEN=$(cat /.env-file/pat) > /.env-file/.env &&
|
||||||
chown -R 1001:${GID} /.env-file &&
|
chown -R 1001:${GID} /.env-file &&
|
||||||
chmod -R 770 /.env-file
|
chmod -R 770 /.env-file
|
||||||
environment:
|
environment:
|
||||||
- GID
|
- GID
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -154,4 +154,4 @@ networks:
|
|||||||
backend:
|
backend:
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
@@ -26,4 +26,4 @@ SAML.DefaultLoginURLV2: "/ui/v2/login/login?authRequest=" # ZITADEL_SAML_DEFAULT
|
|||||||
LogStore.Access.Stdout.Enabled: true
|
LogStore.Access.Stdout.Enabled: true
|
||||||
|
|
||||||
# Skipping the MFA init step allows us to immediately authenticate at the console
|
# Skipping the MFA init step allows us to immediately authenticate at the console
|
||||||
DefaultInstance.LoginPolicy.MfaInitSkipLifetime: "0s"
|
DefaultInstance.LoginPolicy.MfaInitSkipLifetime: "0s"
|
@@ -9,4 +9,4 @@ FirstInstance:
|
|||||||
Machine:
|
Machine:
|
||||||
Username: 'login-container'
|
Username: 'login-container'
|
||||||
Name: 'Login Container'
|
Name: 'Login Container'
|
||||||
Pat.ExpirationDate: '2029-01-01T00:00:00Z'
|
Pat.ExpirationDate: '2029-01-01T00:00:00Z'
|
@@ -71,4 +71,4 @@ Open your favorite internet browser at https://127.0.0.1.sslip.io/ui/console?log
|
|||||||
Your browser warns you about the insecure self-signed TLS certificate. As 127.0.0.1.sslip.io resolves to your localhost, you can safely proceed.
|
Your browser warns you about the insecure self-signed TLS certificate. As 127.0.0.1.sslip.io resolves to your localhost, you can safely proceed.
|
||||||
Use the password *Password1!* to log in.
|
Use the password *Password1!* to log in.
|
||||||
|
|
||||||
Read more about [the login process](/guides/integrate/login/oidc/login-users).
|
Read more about [the login process](/guides/integrate/login/oidc/login-users).
|
@@ -64,4 +64,4 @@ mv /tmp/zitadel-admin-sa.json $HOME/zitadel-admin-sa.json
|
|||||||
This key can be used to provision resources with for example [Terraform](/docs/guides/manage/terraform-provider).
|
This key can be used to provision resources with for example [Terraform](/docs/guides/manage/terraform-provider).
|
||||||
|
|
||||||
<Next components={props.components} />
|
<Next components={props.components} />
|
||||||
<Disclaimer components={props.components} />
|
<Disclaimer components={props.components} />
|
@@ -40,7 +40,7 @@ func (s *Server) GetInstance(ctx context.Context, req *system_pb.GetInstanceRequ
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) AddInstance(ctx context.Context, req *system_pb.AddInstanceRequest) (*system_pb.AddInstanceResponse, error) {
|
func (s *Server) AddInstance(ctx context.Context, req *system_pb.AddInstanceRequest) (*system_pb.AddInstanceResponse, error) {
|
||||||
id, _, _, details, err := s.command.SetUpInstance(ctx, AddInstancePbToSetupInstance(req, s.defaultInstance, s.externalDomain))
|
id, _, _, _, details, err := s.command.SetUpInstance(ctx, AddInstancePbToSetupInstance(req, s.defaultInstance, s.externalDomain))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -61,7 +61,7 @@ func (s *Server) UpdateInstance(ctx context.Context, req *system_pb.UpdateInstan
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) CreateInstance(ctx context.Context, req *system_pb.CreateInstanceRequest) (*system_pb.CreateInstanceResponse, error) {
|
func (s *Server) CreateInstance(ctx context.Context, req *system_pb.CreateInstanceRequest) (*system_pb.CreateInstanceResponse, error) {
|
||||||
id, pat, key, details, err := s.command.SetUpInstance(ctx, CreateInstancePbToSetupInstance(req, s.defaultInstance, s.externalDomain))
|
id, pat, key, _, details, err := s.command.SetUpInstance(ctx, CreateInstancePbToSetupInstance(req, s.defaultInstance, s.externalDomain))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -217,33 +217,33 @@ func (s *InstanceSetup) generateIDs(idGenerator id.Generator) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (string, string, *MachineKey, *domain.ObjectDetails, error) {
|
func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (string, string, *MachineKey, string, *domain.ObjectDetails, error) {
|
||||||
if err := setup.generateIDs(c.idGenerator); err != nil {
|
if err := setup.generateIDs(c.idGenerator); err != nil {
|
||||||
return "", "", nil, nil, err
|
return "", "", nil, "", nil, err
|
||||||
}
|
}
|
||||||
ctx = contextWithInstanceSetupInfo(ctx, setup.zitadel.instanceID, setup.zitadel.projectID, setup.zitadel.consoleAppID, c.externalDomain, setup.DefaultLanguage)
|
ctx = contextWithInstanceSetupInfo(ctx, setup.zitadel.instanceID, setup.zitadel.projectID, setup.zitadel.consoleAppID, c.externalDomain, setup.DefaultLanguage)
|
||||||
|
|
||||||
validations, pat, machineKey, err := setUpInstance(ctx, c, setup)
|
validations, pat, machineKey, loginClientPat, err := setUpInstance(ctx, c, setup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", nil, nil, err
|
return "", "", nil, "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:staticcheck
|
//nolint:staticcheck
|
||||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validations...)
|
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validations...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", nil, nil, err
|
return "", "", nil, "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.eventstore.Push(ctx, cmds...)
|
_, err = c.eventstore.Push(ctx, cmds...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", nil, nil, err
|
return "", "", nil, "", nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// RolePermissions need to be pushed in separate transaction.
|
// RolePermissions need to be pushed in separate transaction.
|
||||||
// https://github.com/zitadel/zitadel/issues/9293
|
// https://github.com/zitadel/zitadel/issues/9293
|
||||||
details, err := c.SynchronizeRolePermission(ctx, setup.zitadel.instanceID, setup.RolePermissionMappings)
|
details, err := c.SynchronizeRolePermission(ctx, setup.zitadel.instanceID, setup.RolePermissionMappings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", nil, nil, err
|
return "", "", nil, "", nil, err
|
||||||
}
|
}
|
||||||
details.ResourceOwner = setup.zitadel.orgID
|
details.ResourceOwner = setup.zitadel.orgID
|
||||||
|
|
||||||
@@ -251,8 +251,12 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
|
|||||||
if pat != nil {
|
if pat != nil {
|
||||||
token = pat.Token
|
token = pat.Token
|
||||||
}
|
}
|
||||||
|
var loginClientToken string
|
||||||
|
if loginClientPat != nil {
|
||||||
|
loginClientToken = loginClientPat.Token
|
||||||
|
}
|
||||||
|
|
||||||
return setup.zitadel.instanceID, token, machineKey, details, nil
|
return setup.zitadel.instanceID, token, machineKey, loginClientToken, details, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func contextWithInstanceSetupInfo(ctx context.Context, instanceID, projectID, consoleAppID, externalDomain string, defaultLanguage language.Tag) context.Context {
|
func contextWithInstanceSetupInfo(ctx context.Context, instanceID, projectID, consoleAppID, externalDomain string, defaultLanguage language.Tag) context.Context {
|
||||||
@@ -274,38 +278,38 @@ func contextWithInstanceSetupInfo(ctx context.Context, instanceID, projectID, co
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setUpInstance(ctx context.Context, c *Commands, setup *InstanceSetup) (validations []preparation.Validation, pat *PersonalAccessToken, machineKey *MachineKey, err error) {
|
func setUpInstance(ctx context.Context, c *Commands, setup *InstanceSetup) (validations []preparation.Validation, pat *PersonalAccessToken, machineKey *MachineKey, loginClientPat *PersonalAccessToken, err error) {
|
||||||
instanceAgg := instance.NewAggregate(setup.zitadel.instanceID)
|
instanceAgg := instance.NewAggregate(setup.zitadel.instanceID)
|
||||||
|
|
||||||
validations = setupInstanceElements(instanceAgg, setup)
|
validations = setupInstanceElements(instanceAgg, setup)
|
||||||
|
|
||||||
// default organization on setup'd instance
|
// default organization on setup'd instance
|
||||||
pat, machineKey, err = setupDefaultOrg(ctx, c, &validations, instanceAgg, setup.Org.Name, setup.Org.Machine, setup.Org.Human, setup.zitadel)
|
pat, machineKey, loginClientPat, err = setupDefaultOrg(ctx, c, &validations, instanceAgg, setup.Org.Name, setup.Org.Machine, setup.Org.Human, setup.Org.LoginClient, setup.zitadel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// domains
|
// domains
|
||||||
if err := setupGeneratedDomain(ctx, c, &validations, instanceAgg, setup.InstanceName); err != nil {
|
if err := setupGeneratedDomain(ctx, c, &validations, instanceAgg, setup.InstanceName); err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
setupCustomDomain(c, &validations, instanceAgg, setup.CustomDomain)
|
setupCustomDomain(c, &validations, instanceAgg, setup.CustomDomain)
|
||||||
|
|
||||||
// optional setting if set
|
// optional setting if set
|
||||||
setupMessageTexts(&validations, setup.MessageTexts, instanceAgg)
|
setupMessageTexts(&validations, setup.MessageTexts, instanceAgg)
|
||||||
if err := setupQuotas(c, &validations, setup.Quotas, setup.zitadel.instanceID); err != nil {
|
if err := setupQuotas(c, &validations, setup.Quotas, setup.zitadel.instanceID); err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
setupSMTPSettings(c, &validations, setup.SMTPConfiguration, instanceAgg)
|
setupSMTPSettings(c, &validations, setup.SMTPConfiguration, instanceAgg)
|
||||||
if err := setupWebKeys(c, &validations, setup.zitadel.instanceID, setup); err != nil {
|
if err := setupWebKeys(c, &validations, setup.zitadel.instanceID, setup); err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
setupOIDCSettings(c, &validations, setup.OIDCSettings, instanceAgg)
|
setupOIDCSettings(c, &validations, setup.OIDCSettings, instanceAgg)
|
||||||
setupFeatures(&validations, setup.Features, setup.zitadel.instanceID)
|
setupFeatures(&validations, setup.Features, setup.zitadel.instanceID)
|
||||||
setupLimits(c, &validations, limits.NewAggregate(setup.zitadel.limitsID, setup.zitadel.instanceID), setup.Limits)
|
setupLimits(c, &validations, limits.NewAggregate(setup.zitadel.limitsID, setup.zitadel.instanceID), setup.Limits)
|
||||||
setupRestrictions(c, &validations, restrictions.NewAggregate(setup.zitadel.restrictionsID, setup.zitadel.instanceID, setup.zitadel.instanceID), setup.Restrictions)
|
setupRestrictions(c, &validations, restrictions.NewAggregate(setup.zitadel.restrictionsID, setup.zitadel.instanceID, setup.zitadel.instanceID), setup.Restrictions)
|
||||||
setupInstanceCreatedMilestone(&validations, setup.zitadel.instanceID)
|
setupInstanceCreatedMilestone(&validations, setup.zitadel.instanceID)
|
||||||
return validations, pat, machineKey, nil
|
return validations, pat, machineKey, loginClientPat, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupInstanceElements(instanceAgg *instance.Aggregate, setup *InstanceSetup) []preparation.Validation {
|
func setupInstanceElements(instanceAgg *instance.Aggregate, setup *InstanceSetup) []preparation.Validation {
|
||||||
@@ -572,8 +576,9 @@ func setupDefaultOrg(ctx context.Context,
|
|||||||
name string,
|
name string,
|
||||||
machine *AddMachine,
|
machine *AddMachine,
|
||||||
human *AddHuman,
|
human *AddHuman,
|
||||||
|
loginClient *AddLoginClient,
|
||||||
ids ZitadelConfig,
|
ids ZitadelConfig,
|
||||||
) (pat *PersonalAccessToken, machineKey *MachineKey, err error) {
|
) (pat *PersonalAccessToken, machineKey *MachineKey, loginClientPat *PersonalAccessToken, err error) {
|
||||||
orgAgg := org.NewAggregate(ids.orgID)
|
orgAgg := org.NewAggregate(ids.orgID)
|
||||||
|
|
||||||
*validations = append(
|
*validations = append(
|
||||||
@@ -582,12 +587,12 @@ func setupDefaultOrg(ctx context.Context,
|
|||||||
commands.prepareSetDefaultOrg(instanceAgg, ids.orgID),
|
commands.prepareSetDefaultOrg(instanceAgg, ids.orgID),
|
||||||
)
|
)
|
||||||
|
|
||||||
projectOwner, pat, machineKey, err := setupAdmins(commands, validations, instanceAgg, orgAgg, machine, human)
|
projectOwner, pat, machineKey, loginClientPat, err := setupAdmins(commands, validations, instanceAgg, orgAgg, machine, human, loginClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
setupMinimalInterfaces(commands, validations, instanceAgg, orgAgg, projectOwner, ids)
|
setupMinimalInterfaces(commands, validations, instanceAgg, orgAgg, projectOwner, ids)
|
||||||
return pat, machineKey, nil
|
return pat, machineKey, loginClientPat, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupAdmins(commands *Commands,
|
func setupAdmins(commands *Commands,
|
||||||
@@ -596,21 +601,22 @@ func setupAdmins(commands *Commands,
|
|||||||
orgAgg *org.Aggregate,
|
orgAgg *org.Aggregate,
|
||||||
machine *AddMachine,
|
machine *AddMachine,
|
||||||
human *AddHuman,
|
human *AddHuman,
|
||||||
) (owner string, pat *PersonalAccessToken, machineKey *MachineKey, err error) {
|
loginClient *AddLoginClient,
|
||||||
|
) (owner string, pat *PersonalAccessToken, machineKey *MachineKey, loginClientPat *PersonalAccessToken, err error) {
|
||||||
if human == nil && machine == nil {
|
if human == nil && machine == nil {
|
||||||
return "", nil, nil, zerrors.ThrowInvalidArgument(nil, "INSTANCE-z1yi2q2ot7", "Error.Instance.NoAdmin")
|
return "", nil, nil, nil, zerrors.ThrowInvalidArgument(nil, "INSTANCE-z1yi2q2ot7", "Error.Instance.NoAdmin")
|
||||||
}
|
}
|
||||||
|
|
||||||
if machine != nil && machine.Machine != nil && !machine.Machine.IsZero() {
|
if machine != nil && machine.Machine != nil && !machine.Machine.IsZero() {
|
||||||
machineUserID, err := commands.idGenerator.Next()
|
machineUserID, err := commands.idGenerator.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, nil, err
|
return "", nil, nil, nil, err
|
||||||
}
|
}
|
||||||
owner = machineUserID
|
owner = machineUserID
|
||||||
|
|
||||||
pat, machineKey, err = setupMachineAdmin(commands, validations, machine, orgAgg.ID, machineUserID)
|
pat, machineKey, err = setupMachineAdmin(commands, validations, machine, orgAgg.ID, machineUserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, nil, err
|
return "", nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
setupAdminMembers(commands, validations, instanceAgg, orgAgg, machineUserID)
|
setupAdminMembers(commands, validations, instanceAgg, orgAgg, machineUserID)
|
||||||
@@ -618,7 +624,7 @@ func setupAdmins(commands *Commands,
|
|||||||
if human != nil {
|
if human != nil {
|
||||||
humanUserID, err := commands.idGenerator.Next()
|
humanUserID, err := commands.idGenerator.Next()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, nil, err
|
return "", nil, nil, nil, err
|
||||||
}
|
}
|
||||||
owner = humanUserID
|
owner = humanUserID
|
||||||
human.ID = humanUserID
|
human.ID = humanUserID
|
||||||
@@ -629,7 +635,18 @@ func setupAdmins(commands *Commands,
|
|||||||
|
|
||||||
setupAdminMembers(commands, validations, instanceAgg, orgAgg, humanUserID)
|
setupAdminMembers(commands, validations, instanceAgg, orgAgg, humanUserID)
|
||||||
}
|
}
|
||||||
return owner, pat, machineKey, nil
|
if loginClient != nil {
|
||||||
|
loginClientUserID, err := commands.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
loginClientPat, err = setupLoginClient(commands, validations, instanceAgg, loginClient, orgAgg.ID, loginClientUserID)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return owner, pat, machineKey, loginClientPat, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupMachineAdmin(commands *Commands, validations *[]preparation.Validation, machine *AddMachine, orgID, userID string) (pat *PersonalAccessToken, machineKey *MachineKey, err error) {
|
func setupMachineAdmin(commands *Commands, validations *[]preparation.Validation, machine *AddMachine, orgID, userID string) (pat *PersonalAccessToken, machineKey *MachineKey, err error) {
|
||||||
@@ -655,6 +672,22 @@ func setupMachineAdmin(commands *Commands, validations *[]preparation.Validation
|
|||||||
return pat, machineKey, nil
|
return pat, machineKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupLoginClient(commands *Commands, validations *[]preparation.Validation, instanceAgg *instance.Aggregate, loginClient *AddLoginClient, orgID, userID string) (pat *PersonalAccessToken, err error) {
|
||||||
|
*validations = append(*validations,
|
||||||
|
AddMachineCommand(user.NewAggregate(userID, orgID), loginClient.Machine),
|
||||||
|
commands.AddInstanceMemberCommand(instanceAgg, userID, domain.RoleIAMLoginClient),
|
||||||
|
)
|
||||||
|
if loginClient.Pat != nil {
|
||||||
|
pat = NewPersonalAccessToken(orgID, userID, loginClient.Pat.ExpirationDate, loginClient.Pat.Scopes, domain.UserTypeMachine)
|
||||||
|
pat.TokenID, err = commands.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
*validations = append(*validations, prepareAddPersonalAccessToken(pat, commands.keyAlgorithm))
|
||||||
|
}
|
||||||
|
return pat, nil
|
||||||
|
}
|
||||||
|
|
||||||
func setupAdminMembers(commands *Commands, validations *[]preparation.Validation, instanceAgg *instance.Aggregate, orgAgg *org.Aggregate, userID string) {
|
func setupAdminMembers(commands *Commands, validations *[]preparation.Validation, instanceAgg *instance.Aggregate, orgAgg *org.Aggregate, userID string) {
|
||||||
*validations = append(*validations,
|
*validations = append(*validations,
|
||||||
commands.AddOrgMemberCommand(orgAgg, userID, domain.RoleOrgOwner),
|
commands.AddOrgMemberCommand(orgAgg, userID, domain.RoleOrgOwner),
|
||||||
|
@@ -129,7 +129,7 @@ func oidcAppEvents(ctx context.Context, orgID, projectID, id, name, clientID str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func orgFilters(orgID string, machine, human bool) []expect {
|
func orgFilters(orgID string, machine, human, loginClient bool) []expect {
|
||||||
filters := []expect{
|
filters := []expect{
|
||||||
expectFilter(),
|
expectFilter(),
|
||||||
expectFilter(
|
expectFilter(
|
||||||
@@ -144,13 +144,17 @@ func orgFilters(orgID string, machine, human bool) []expect {
|
|||||||
filters = append(filters, humanFilters(orgID)...)
|
filters = append(filters, humanFilters(orgID)...)
|
||||||
filters = append(filters, adminMemberFilters(orgID, "USER")...)
|
filters = append(filters, adminMemberFilters(orgID, "USER")...)
|
||||||
}
|
}
|
||||||
|
if loginClient {
|
||||||
|
filters = append(filters, loginClientFilters(orgID, true)...)
|
||||||
|
filters = append(filters, instanceMemberFilters(orgID, "USER-LOGIN-CLIENT")...)
|
||||||
|
}
|
||||||
|
|
||||||
return append(filters,
|
return append(filters,
|
||||||
projectFilters()...,
|
projectFilters()...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func orgEvents(ctx context.Context, instanceID, orgID, name, projectID, defaultDomain string, externalSecure bool, machine, human bool) []eventstore.Command {
|
func orgEvents(ctx context.Context, instanceID, orgID, name, projectID, defaultDomain string, externalSecure bool, machine, human, loginClient bool) []eventstore.Command {
|
||||||
instanceAgg := instance.NewAggregate(instanceID)
|
instanceAgg := instance.NewAggregate(instanceID)
|
||||||
orgAgg := org.NewAggregate(orgID)
|
orgAgg := org.NewAggregate(orgID)
|
||||||
domain := strings.ToLower(name + "." + defaultDomain)
|
domain := strings.ToLower(name + "." + defaultDomain)
|
||||||
@@ -173,13 +177,17 @@ func orgEvents(ctx context.Context, instanceID, orgID, name, projectID, defaultD
|
|||||||
events = append(events, humanEvents(ctx, instanceID, orgID, userID)...)
|
events = append(events, humanEvents(ctx, instanceID, orgID, userID)...)
|
||||||
owner = userID
|
owner = userID
|
||||||
}
|
}
|
||||||
|
if loginClient {
|
||||||
|
userID := "USER-LOGIN-CLIENT"
|
||||||
|
events = append(events, loginClientEvents(ctx, instanceID, orgID, userID, "LOGIN-CLIENT-PAT")...)
|
||||||
|
}
|
||||||
|
|
||||||
events = append(events, projectAddedEvents(ctx, instanceID, orgID, projectID, owner, externalSecure)...)
|
events = append(events, projectAddedEvents(ctx, instanceID, orgID, projectID, owner, externalSecure)...)
|
||||||
return events
|
return events
|
||||||
}
|
}
|
||||||
|
|
||||||
func orgIDs() []string {
|
func orgIDs() []string {
|
||||||
return slices.Concat([]string{"USER-MACHINE", "PAT", "USER"}, projectClientIDs())
|
return slices.Concat([]string{"USER-MACHINE", "PAT", "USER", "USER-LOGIN-CLIENT", "LOGIN-CLIENT-PAT"}, projectClientIDs())
|
||||||
}
|
}
|
||||||
|
|
||||||
func instancePoliciesFilters(instanceID string) []expect {
|
func instancePoliciesFilters(instanceID string) []expect {
|
||||||
@@ -363,7 +371,7 @@ func instanceElementsConfig() *SecretGenerators {
|
|||||||
func setupInstanceFilters(instanceID, orgID, projectID, appID, domain string) []expect {
|
func setupInstanceFilters(instanceID, orgID, projectID, appID, domain string) []expect {
|
||||||
return slices.Concat(
|
return slices.Concat(
|
||||||
setupInstanceElementsFilters(instanceID),
|
setupInstanceElementsFilters(instanceID),
|
||||||
orgFilters(orgID, true, true),
|
orgFilters(orgID, true, true, true),
|
||||||
generatedDomainFilters(instanceID, orgID, projectID, appID, domain),
|
generatedDomainFilters(instanceID, orgID, projectID, appID, domain),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -371,7 +379,7 @@ func setupInstanceFilters(instanceID, orgID, projectID, appID, domain string) []
|
|||||||
func setupInstanceEvents(ctx context.Context, instanceID, orgID, projectID, appID, instanceName, orgName string, defaultLanguage language.Tag, domain string, externalSecure bool) []eventstore.Command {
|
func setupInstanceEvents(ctx context.Context, instanceID, orgID, projectID, appID, instanceName, orgName string, defaultLanguage language.Tag, domain string, externalSecure bool) []eventstore.Command {
|
||||||
return slices.Concat(
|
return slices.Concat(
|
||||||
setupInstanceElementsEvents(ctx, instanceID, instanceName, defaultLanguage),
|
setupInstanceElementsEvents(ctx, instanceID, instanceName, defaultLanguage),
|
||||||
orgEvents(ctx, instanceID, orgID, orgName, projectID, domain, externalSecure, true, true),
|
orgEvents(ctx, instanceID, orgID, orgName, projectID, domain, externalSecure, true, true, true),
|
||||||
generatedDomainEvents(ctx, instanceID, orgID, projectID, appID, domain),
|
generatedDomainEvents(ctx, instanceID, orgID, projectID, appID, domain),
|
||||||
instanceCreatedMilestoneEvent(ctx, instanceID),
|
instanceCreatedMilestoneEvent(ctx, instanceID),
|
||||||
)
|
)
|
||||||
@@ -380,9 +388,10 @@ func setupInstanceEvents(ctx context.Context, instanceID, orgID, projectID, appI
|
|||||||
func setupInstanceConfig() *InstanceSetup {
|
func setupInstanceConfig() *InstanceSetup {
|
||||||
conf := setupInstanceElementsConfig()
|
conf := setupInstanceElementsConfig()
|
||||||
conf.Org = InstanceOrgSetup{
|
conf.Org = InstanceOrgSetup{
|
||||||
Name: "ZITADEL",
|
Name: "ZITADEL",
|
||||||
Machine: instanceSetupMachineConfig(),
|
Machine: instanceSetupMachineConfig(),
|
||||||
Human: instanceSetupHumanConfig(),
|
Human: instanceSetupHumanConfig(),
|
||||||
|
LoginClient: instanceSetupLoginClientConfig(),
|
||||||
}
|
}
|
||||||
conf.CustomDomain = ""
|
conf.CustomDomain = ""
|
||||||
return conf
|
return conf
|
||||||
@@ -541,6 +550,43 @@ func instanceSetupMachineConfig() *AddMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loginClientFilters(orgID string, pat bool) []expect {
|
||||||
|
filters := []expect{
|
||||||
|
expectFilter(),
|
||||||
|
expectFilter(
|
||||||
|
org.NewDomainPolicyAddedEvent(
|
||||||
|
context.Background(),
|
||||||
|
&org.NewAggregate(orgID).Aggregate,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
if pat {
|
||||||
|
filters = append(filters,
|
||||||
|
expectFilter(),
|
||||||
|
expectFilter(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return filters
|
||||||
|
}
|
||||||
|
|
||||||
|
func instanceSetupLoginClientConfig() *AddLoginClient {
|
||||||
|
return &AddLoginClient{
|
||||||
|
Machine: &Machine{
|
||||||
|
Username: "zitadel-login-client",
|
||||||
|
Name: "ZITADEL-login-client",
|
||||||
|
Description: "Login Client",
|
||||||
|
AccessTokenType: domain.OIDCTokenTypeBearer,
|
||||||
|
},
|
||||||
|
Pat: &AddPat{
|
||||||
|
ExpirationDate: time.Time{},
|
||||||
|
Scopes: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func projectFilters() []expect {
|
func projectFilters() []expect {
|
||||||
return []expect{
|
return []expect{
|
||||||
expectFilter(),
|
expectFilter(),
|
||||||
@@ -551,11 +597,23 @@ func projectFilters() []expect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func adminMemberFilters(orgID, userID string) []expect {
|
func adminMemberFilters(orgID, userID string) []expect {
|
||||||
|
filters := append(
|
||||||
|
orgMemberFilters(orgID, userID),
|
||||||
|
instanceMemberFilters(orgID, userID)...,
|
||||||
|
)
|
||||||
|
return filters
|
||||||
|
}
|
||||||
|
func orgMemberFilters(orgID, userID string) []expect {
|
||||||
return []expect{
|
return []expect{
|
||||||
expectFilter(
|
expectFilter(
|
||||||
addHumanEvent(context.Background(), orgID, userID),
|
addHumanEvent(context.Background(), orgID, userID),
|
||||||
),
|
),
|
||||||
expectFilter(),
|
expectFilter(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func instanceMemberFilters(orgID, userID string) []expect {
|
||||||
|
return []expect{
|
||||||
expectFilter(
|
expectFilter(
|
||||||
addHumanEvent(context.Background(), orgID, userID),
|
addHumanEvent(context.Background(), orgID, userID),
|
||||||
),
|
),
|
||||||
@@ -631,6 +689,40 @@ func addMachineEvent(ctx context.Context, orgID, userID string) *user.MachineAdd
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loginClientEvents all events from setup to create the login client user
|
||||||
|
func loginClientEvents(ctx context.Context, instanceID, orgID, userID, patID string) []eventstore.Command {
|
||||||
|
agg := user.NewAggregate(userID, orgID)
|
||||||
|
instanceAgg := instance.NewAggregate(instanceID)
|
||||||
|
events := []eventstore.Command{
|
||||||
|
addLoginClientEvent(ctx, orgID, userID),
|
||||||
|
instance.NewMemberAddedEvent(ctx, &instanceAgg.Aggregate, userID, domain.RoleIAMLoginClient),
|
||||||
|
}
|
||||||
|
if patID != "" {
|
||||||
|
events = append(events,
|
||||||
|
user.NewPersonalAccessTokenAddedEvent(
|
||||||
|
ctx,
|
||||||
|
&agg.Aggregate,
|
||||||
|
patID,
|
||||||
|
time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC),
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return events
|
||||||
|
}
|
||||||
|
|
||||||
|
func addLoginClientEvent(ctx context.Context, orgID, userID string) *user.MachineAddedEvent {
|
||||||
|
agg := user.NewAggregate(userID, orgID)
|
||||||
|
return user.NewMachineAddedEvent(ctx,
|
||||||
|
&agg.Aggregate,
|
||||||
|
"zitadel-login-client",
|
||||||
|
"ZITADEL-login-client",
|
||||||
|
"Login Client",
|
||||||
|
false,
|
||||||
|
domain.OIDCTokenTypeBearer,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func testSetup(ctx context.Context, c *Commands, validations []preparation.Validation) error {
|
func testSetup(ctx context.Context, c *Commands, validations []preparation.Validation) error {
|
||||||
//nolint:staticcheck
|
//nolint:staticcheck
|
||||||
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validations...)
|
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, validations...)
|
||||||
@@ -715,6 +807,13 @@ func TestCommandSide_setupMinimalInterfaces(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func validZitadelRoles() []authz.RoleMapping {
|
||||||
|
return []authz.RoleMapping{
|
||||||
|
{Role: domain.RoleOrgOwner, Permissions: []string{""}},
|
||||||
|
{Role: domain.RoleIAMOwner, Permissions: []string{""}},
|
||||||
|
{Role: domain.RoleIAMLoginClient, Permissions: []string{""}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCommandSide_setupAdmins(t *testing.T) {
|
func TestCommandSide_setupAdmins(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
@@ -730,12 +829,14 @@ func TestCommandSide_setupAdmins(t *testing.T) {
|
|||||||
orgAgg *org.Aggregate
|
orgAgg *org.Aggregate
|
||||||
machine *AddMachine
|
machine *AddMachine
|
||||||
human *AddHuman
|
human *AddHuman
|
||||||
|
loginClient *AddLoginClient
|
||||||
}
|
}
|
||||||
type res struct {
|
type res struct {
|
||||||
owner string
|
owner string
|
||||||
pat bool
|
pat bool
|
||||||
machineKey bool
|
machineKey bool
|
||||||
err func(error) bool
|
loginClientPat bool
|
||||||
|
err func(error) bool
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -763,10 +864,7 @@ func TestCommandSide_setupAdmins(t *testing.T) {
|
|||||||
),
|
),
|
||||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "USER"),
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "USER"),
|
||||||
userPasswordHasher: mockPasswordHasher("x"),
|
userPasswordHasher: mockPasswordHasher("x"),
|
||||||
roles: []authz.RoleMapping{
|
roles: validZitadelRoles(),
|
||||||
{Role: domain.RoleOrgOwner, Permissions: []string{""}},
|
|
||||||
{Role: domain.RoleIAMOwner, Permissions: []string{""}},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
|
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
|
||||||
@@ -800,11 +898,8 @@ func TestCommandSide_setupAdmins(t *testing.T) {
|
|||||||
},
|
},
|
||||||
)...,
|
)...,
|
||||||
),
|
),
|
||||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "USER-MACHINE", "PAT"),
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "USER-MACHINE", "PAT"),
|
||||||
roles: []authz.RoleMapping{
|
roles: validZitadelRoles(),
|
||||||
{Role: domain.RoleOrgOwner, Permissions: []string{""}},
|
|
||||||
{Role: domain.RoleIAMOwner, Permissions: []string{""}},
|
|
||||||
},
|
|
||||||
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
@@ -850,11 +945,8 @@ func TestCommandSide_setupAdmins(t *testing.T) {
|
|||||||
),
|
),
|
||||||
userPasswordHasher: mockPasswordHasher("x"),
|
userPasswordHasher: mockPasswordHasher("x"),
|
||||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "USER-MACHINE", "PAT", "USER"),
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "USER-MACHINE", "PAT", "USER"),
|
||||||
roles: []authz.RoleMapping{
|
roles: validZitadelRoles(),
|
||||||
{Role: domain.RoleOrgOwner, Permissions: []string{""}},
|
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
{Role: domain.RoleIAMOwner, Permissions: []string{""}},
|
|
||||||
},
|
|
||||||
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
|
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
|
||||||
@@ -870,6 +962,63 @@ func TestCommandSide_setupAdmins(t *testing.T) {
|
|||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "human, machine and login client, ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: expectEventstore(
|
||||||
|
slices.Concat(
|
||||||
|
machineFilters("ORG", true),
|
||||||
|
adminMemberFilters("ORG", "USER-MACHINE"),
|
||||||
|
humanFilters("ORG"),
|
||||||
|
adminMemberFilters("ORG", "USER"),
|
||||||
|
loginClientFilters("ORG", true),
|
||||||
|
instanceMemberFilters("ORG", "USER-LOGIN-CLIENT"),
|
||||||
|
[]expect{
|
||||||
|
expectPush(
|
||||||
|
slices.Concat(
|
||||||
|
machineEvents(context.Background(),
|
||||||
|
"INSTANCE",
|
||||||
|
"ORG",
|
||||||
|
"USER-MACHINE",
|
||||||
|
"PAT",
|
||||||
|
),
|
||||||
|
humanEvents(context.Background(),
|
||||||
|
"INSTANCE",
|
||||||
|
"ORG",
|
||||||
|
"USER",
|
||||||
|
),
|
||||||
|
loginClientEvents(context.Background(),
|
||||||
|
"INSTANCE",
|
||||||
|
"ORG",
|
||||||
|
"USER-LOGIN-CLIENT",
|
||||||
|
"LOGIN-CLIENT-PAT",
|
||||||
|
),
|
||||||
|
)...,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)...,
|
||||||
|
),
|
||||||
|
userPasswordHasher: mockPasswordHasher("x"),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "USER-MACHINE", "PAT", "USER", "USER-LOGIN-CLIENT", "LOGIN-CLIENT-PAT"),
|
||||||
|
roles: validZitadelRoles(),
|
||||||
|
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
|
||||||
|
instanceAgg: instance.NewAggregate("INSTANCE"),
|
||||||
|
orgAgg: org.NewAggregate("ORG"),
|
||||||
|
machine: instanceSetupMachineConfig(),
|
||||||
|
human: instanceSetupHumanConfig(),
|
||||||
|
loginClient: instanceSetupLoginClientConfig(),
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
owner: "USER",
|
||||||
|
pat: true,
|
||||||
|
machineKey: false,
|
||||||
|
loginClientPat: true,
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
@@ -881,7 +1030,7 @@ func TestCommandSide_setupAdmins(t *testing.T) {
|
|||||||
keyAlgorithm: tt.fields.keyAlgorithm,
|
keyAlgorithm: tt.fields.keyAlgorithm,
|
||||||
}
|
}
|
||||||
validations := make([]preparation.Validation, 0)
|
validations := make([]preparation.Validation, 0)
|
||||||
owner, pat, mk, err := setupAdmins(r, &validations, tt.args.instanceAgg, tt.args.orgAgg, tt.args.machine, tt.args.human)
|
owner, pat, mk, loginClientPat, err := setupAdmins(r, &validations, tt.args.instanceAgg, tt.args.orgAgg, tt.args.machine, tt.args.human, tt.args.loginClient)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
@@ -905,6 +1054,9 @@ func TestCommandSide_setupAdmins(t *testing.T) {
|
|||||||
if tt.res.machineKey {
|
if tt.res.machineKey {
|
||||||
assert.NotNil(t, mk)
|
assert.NotNil(t, mk)
|
||||||
}
|
}
|
||||||
|
if tt.res.loginClientPat {
|
||||||
|
assert.NotNil(t, loginClientPat)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -924,12 +1076,14 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
|
|||||||
orgName string
|
orgName string
|
||||||
machine *AddMachine
|
machine *AddMachine
|
||||||
human *AddHuman
|
human *AddHuman
|
||||||
|
loginClient *AddLoginClient
|
||||||
ids ZitadelConfig
|
ids ZitadelConfig
|
||||||
}
|
}
|
||||||
type res struct {
|
type res struct {
|
||||||
pat bool
|
pat bool
|
||||||
machineKey bool
|
machineKey bool
|
||||||
err func(error) bool
|
loginClientPat bool
|
||||||
|
err func(error) bool
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -938,7 +1092,7 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
|
|||||||
res res
|
res res
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "human and machine, ok",
|
name: "human, machine and login client, ok",
|
||||||
fields: fields{
|
fields: fields{
|
||||||
eventstore: expectEventstore(
|
eventstore: expectEventstore(
|
||||||
slices.Concat(
|
slices.Concat(
|
||||||
@@ -946,6 +1100,7 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
|
|||||||
"ORG",
|
"ORG",
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
[]expect{
|
[]expect{
|
||||||
expectPush(
|
expectPush(
|
||||||
@@ -959,6 +1114,7 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
|
|||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
)...,
|
)...,
|
||||||
),
|
),
|
||||||
@@ -967,11 +1123,8 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
|
|||||||
),
|
),
|
||||||
userPasswordHasher: mockPasswordHasher("x"),
|
userPasswordHasher: mockPasswordHasher("x"),
|
||||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, orgIDs()...),
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, orgIDs()...),
|
||||||
roles: []authz.RoleMapping{
|
roles: validZitadelRoles(),
|
||||||
{Role: domain.RoleOrgOwner, Permissions: []string{""}},
|
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
{Role: domain.RoleIAMOwner, Permissions: []string{""}},
|
|
||||||
},
|
|
||||||
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
|
ctx: contextWithInstanceSetupInfo(context.Background(), "INSTANCE", "PROJECT", "console-id", "DOMAIN", language.Dutch),
|
||||||
@@ -1007,6 +1160,18 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
|
|||||||
Password: "password",
|
Password: "password",
|
||||||
PasswordChangeRequired: false,
|
PasswordChangeRequired: false,
|
||||||
},
|
},
|
||||||
|
loginClient: &AddLoginClient{
|
||||||
|
Machine: &Machine{
|
||||||
|
Username: "zitadel-login-client",
|
||||||
|
Name: "ZITADEL-login-client",
|
||||||
|
Description: "Login Client",
|
||||||
|
AccessTokenType: domain.OIDCTokenTypeBearer,
|
||||||
|
},
|
||||||
|
Pat: &AddPat{
|
||||||
|
ExpirationDate: time.Time{},
|
||||||
|
Scopes: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
ids: ZitadelConfig{
|
ids: ZitadelConfig{
|
||||||
instanceID: "INSTANCE",
|
instanceID: "INSTANCE",
|
||||||
orgID: "ORG",
|
orgID: "ORG",
|
||||||
@@ -1018,9 +1183,10 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
res: res{
|
res: res{
|
||||||
pat: true,
|
pat: true,
|
||||||
machineKey: false,
|
machineKey: false,
|
||||||
err: nil,
|
loginClientPat: true,
|
||||||
|
err: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1034,7 +1200,7 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
|
|||||||
keyAlgorithm: tt.fields.keyAlgorithm,
|
keyAlgorithm: tt.fields.keyAlgorithm,
|
||||||
}
|
}
|
||||||
validations := make([]preparation.Validation, 0)
|
validations := make([]preparation.Validation, 0)
|
||||||
pat, mk, err := setupDefaultOrg(tt.args.ctx, r, &validations, tt.args.instanceAgg, tt.args.orgName, tt.args.machine, tt.args.human, tt.args.ids)
|
pat, mk, loginClientPat, err := setupDefaultOrg(tt.args.ctx, r, &validations, tt.args.instanceAgg, tt.args.orgName, tt.args.machine, tt.args.human, tt.args.loginClient, tt.args.ids)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
@@ -1057,6 +1223,9 @@ func TestCommandSide_setupDefaultOrg(t *testing.T) {
|
|||||||
if tt.res.machineKey {
|
if tt.res.machineKey {
|
||||||
assert.NotNil(t, mk)
|
assert.NotNil(t, mk)
|
||||||
}
|
}
|
||||||
|
if tt.res.loginClientPat {
|
||||||
|
assert.NotNil(t, loginClientPat)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1140,9 +1309,10 @@ func TestCommandSide_setUpInstance(t *testing.T) {
|
|||||||
setup *InstanceSetup
|
setup *InstanceSetup
|
||||||
}
|
}
|
||||||
type res struct {
|
type res struct {
|
||||||
pat bool
|
pat bool
|
||||||
machineKey bool
|
machineKey bool
|
||||||
err func(error) bool
|
loginClientPat bool
|
||||||
|
err func(error) bool
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -1175,11 +1345,8 @@ func TestCommandSide_setUpInstance(t *testing.T) {
|
|||||||
),
|
),
|
||||||
userPasswordHasher: mockPasswordHasher("x"),
|
userPasswordHasher: mockPasswordHasher("x"),
|
||||||
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, orgIDs()...),
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, orgIDs()...),
|
||||||
roles: []authz.RoleMapping{
|
roles: validZitadelRoles(),
|
||||||
{Role: domain.RoleOrgOwner, Permissions: []string{""}},
|
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
{Role: domain.RoleIAMOwner, Permissions: []string{""}},
|
|
||||||
},
|
|
||||||
keyAlgorithm: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
|
||||||
generateDomain: func(string, string) (string, error) {
|
generateDomain: func(string, string) (string, error) {
|
||||||
return "DOMAIN", nil
|
return "DOMAIN", nil
|
||||||
},
|
},
|
||||||
@@ -1204,7 +1371,7 @@ func TestCommandSide_setUpInstance(t *testing.T) {
|
|||||||
GenerateDomain: tt.fields.generateDomain,
|
GenerateDomain: tt.fields.generateDomain,
|
||||||
}
|
}
|
||||||
|
|
||||||
validations, pat, mk, err := setUpInstance(tt.args.ctx, r, tt.args.setup)
|
validations, pat, mk, loginClientPat, err := setUpInstance(tt.args.ctx, r, tt.args.setup)
|
||||||
if tt.res.err == nil {
|
if tt.res.err == nil {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
@@ -1227,6 +1394,9 @@ func TestCommandSide_setUpInstance(t *testing.T) {
|
|||||||
if tt.res.machineKey {
|
if tt.res.machineKey {
|
||||||
assert.NotNil(t, mk)
|
assert.NotNil(t, mk)
|
||||||
}
|
}
|
||||||
|
if tt.res.loginClientPat {
|
||||||
|
assert.NotNil(t, loginClientPat)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -24,9 +24,15 @@ type InstanceOrgSetup struct {
|
|||||||
CustomDomain string
|
CustomDomain string
|
||||||
Human *AddHuman
|
Human *AddHuman
|
||||||
Machine *AddMachine
|
Machine *AddMachine
|
||||||
|
LoginClient *AddLoginClient
|
||||||
Roles []string
|
Roles []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddLoginClient struct {
|
||||||
|
Machine *Machine
|
||||||
|
Pat *AddPat
|
||||||
|
}
|
||||||
|
|
||||||
type OrgSetup struct {
|
type OrgSetup struct {
|
||||||
Name string
|
Name string
|
||||||
CustomDomain string
|
CustomDomain string
|
||||||
|
@@ -14,6 +14,7 @@ const (
|
|||||||
RoleOrgOwner = "ORG_OWNER"
|
RoleOrgOwner = "ORG_OWNER"
|
||||||
RoleOrgProjectCreator = "ORG_PROJECT_CREATOR"
|
RoleOrgProjectCreator = "ORG_PROJECT_CREATOR"
|
||||||
RoleIAMOwner = "IAM_OWNER"
|
RoleIAMOwner = "IAM_OWNER"
|
||||||
|
RoleIAMLoginClient = "IAM_LOGIN_CLIENT"
|
||||||
RoleProjectOwner = "PROJECT_OWNER"
|
RoleProjectOwner = "PROJECT_OWNER"
|
||||||
RoleProjectOwnerGlobal = "PROJECT_OWNER_GLOBAL"
|
RoleProjectOwnerGlobal = "PROJECT_OWNER_GLOBAL"
|
||||||
RoleProjectGrantOwner = "PROJECT_GRANT_OWNER"
|
RoleProjectGrantOwner = "PROJECT_GRANT_OWNER"
|
||||||
|
Reference in New Issue
Block a user