feat: Instance create (#4502)

* feat(instance): implement create instance with direct machine user and credentials

* fix: deprecated add endpoint and variable declaration

* fix(instance): update logic for pats and machinekeys

* fix(instance): unit test corrections and additional unit test for pats and machinekeys

* fix(instance-create): include review changes

* fix(instance-create): linter fixes

* move iframe usage to solution scenarios configurations

* Revert "move iframe usage to solution scenarios configurations"

This reverts commit 9db31f3808e6dfcae9907bc574c072436a19865a.

* fix merge

* fix: add review suggestions

Co-authored-by: Livio Spring <[email protected]>

* fix: add review changes

* fix: add review changes for default definitions

* fix: add review changes for machinekey details

* fix: add machinekey output when setup with machineuser

* fix: add changes from review

* fix instance converter for machine and allow overwriting of further machine fields

Co-authored-by: Livio Spring <[email protected]>
This commit is contained in:
Stefan Benz
2022-12-09 14:04:33 +01:00
committed by GitHub
co-authored by Livio Spring
parent c5ebeea590
commit 47ffa52f0f
27 changed files with 1403 additions and 354 deletions
+23 -1
View File
@@ -41,7 +41,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) {
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 {
return nil, err
}
@@ -62,6 +62,28 @@ func (s *Server) UpdateInstance(ctx context.Context, req *system_pb.UpdateInstan
}, nil
}
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))
if err != nil {
return nil, err
}
var machineKey []byte
if key != nil {
machineKey, err = key.Detail()
if err != nil {
return nil, err
}
}
return &system_pb.CreateInstanceResponse{
Pat: pat,
MachineKey: machineKey,
InstanceId: id,
Details: object.AddToDetailsPb(details.Sequence, details.EventDate, details.ResourceOwner),
}, nil
}
func (s *Server) RemoveInstance(ctx context.Context, req *system_pb.RemoveInstanceRequest) (*system_pb.RemoveInstanceResponse, error) {
ctx = authz.WithInstanceID(ctx, req.InstanceId)
details, err := s.command.RemoveInstance(ctx, req.InstanceId)
@@ -3,10 +3,13 @@ package system
import (
"strings"
"github.com/zitadel/oidc/v2/pkg/oidc"
"golang.org/x/text/language"
"github.com/zitadel/zitadel/internal/api/grpc/authn"
instance_grpc "github.com/zitadel/zitadel/internal/api/grpc/instance"
"github.com/zitadel/zitadel/internal/api/grpc/object"
z_oidc "github.com/zitadel/zitadel/internal/api/oidc"
"github.com/zitadel/zitadel/internal/command"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/query"
@@ -14,6 +17,123 @@ import (
system_pb "github.com/zitadel/zitadel/pkg/grpc/system"
)
func CreateInstancePbToSetupInstance(req *system_pb.CreateInstanceRequest, defaultInstance command.InstanceSetup, externalDomain string) *command.InstanceSetup {
if req.InstanceName != "" {
defaultInstance.InstanceName = req.InstanceName
defaultInstance.Org.Name = req.InstanceName
}
if req.CustomDomain != "" {
defaultInstance.CustomDomain = req.CustomDomain
}
if req.FirstOrgName != "" {
defaultInstance.Org.Name = req.FirstOrgName
}
if user := req.GetMachine(); user != nil {
defaultMachine := command.AddMachine{}
if defaultInstance.Org.Machine != nil {
defaultMachine = *defaultInstance.Org.Machine
}
defaultInstance.Org.Machine = createInstancePbToAddMachine(user, defaultMachine)
defaultInstance.Org.Human = nil
}
if user := req.GetHuman(); user != nil {
defaultHuman := command.AddHuman{}
if defaultInstance.Org.Human != nil {
defaultHuman = *defaultInstance.Org.Human
}
defaultInstance.Org.Human = createInstancePbToAddHuman(user, defaultHuman, defaultInstance.DomainPolicy.UserLoginMustBeDomain, defaultInstance.Org.Name, externalDomain)
defaultInstance.Org.Machine = nil
}
if lang := language.Make(req.DefaultLanguage); lang != language.Und {
defaultInstance.DefaultLanguage = lang
}
return &defaultInstance
}
func createInstancePbToAddHuman(user *system_pb.CreateInstanceRequest_Human, defaultHuman command.AddHuman, userLoginMustBeDomain bool, org, externalDomain string) *command.AddHuman {
if user.Email != nil {
defaultHuman.Email.Address = user.Email.Email
defaultHuman.Email.Verified = user.Email.IsEmailVerified
}
if user.Profile != nil {
if user.Profile.FirstName != "" {
defaultHuman.FirstName = user.Profile.FirstName
}
if user.Profile.LastName != "" {
defaultHuman.LastName = user.Profile.LastName
}
if user.Profile.PreferredLanguage != "" {
lang, err := language.Parse(user.Profile.PreferredLanguage)
if err == nil {
defaultHuman.PreferredLanguage = lang
}
}
}
// check if default username is email style or else append @<orgname>.<custom-domain>
// this way we have the same value as before changing `UserLoginMustBeDomain` to false
if !userLoginMustBeDomain && !strings.Contains(defaultHuman.Username, "@") {
defaultHuman.Username = defaultHuman.Username + "@" + domain.NewIAMDomainName(org, externalDomain)
}
if user.UserName != "" {
defaultHuman.Username = user.UserName
}
if user.Password != nil {
defaultHuman.Password = user.Password.Password
defaultHuman.PasswordChangeRequired = user.Password.PasswordChangeRequired
}
return &defaultHuman
}
func createInstancePbToAddMachine(user *system_pb.CreateInstanceRequest_Machine, defaultMachine command.AddMachine) *command.AddMachine {
machine := command.Machine{}
if defaultMachine.Machine != nil {
machine = *defaultMachine.Machine
}
if user.UserName != "" {
machine.Username = user.UserName
}
if user.Name != "" {
machine.Name = user.Name
}
defaultMachine.Machine = &machine
if defaultMachine.Pat != nil || user.PersonalAccessToken != nil {
pat := command.AddPat{}
if defaultMachine.Pat != nil {
pat = *defaultMachine.Pat
}
// scopes are currently static and can not be overwritten
pat.Scopes = []string{oidc.ScopeOpenID, z_oidc.ScopeUserMetaData, z_oidc.ScopeResourceOwner}
if user.PersonalAccessToken.ExpirationDate != nil {
pat.ExpirationDate = user.PersonalAccessToken.ExpirationDate.AsTime()
}
defaultMachine.Pat = &pat
}
if defaultMachine.MachineKey != nil || user.MachineKey != nil {
machineKey := command.AddMachineKey{}
if defaultMachine.MachineKey != nil {
machineKey = *defaultMachine.MachineKey
}
if user.MachineKey != nil {
if user.MachineKey.Type != 0 {
machineKey.Type = authn.KeyTypeToDomain(user.MachineKey.Type)
}
if user.MachineKey.ExpirationDate != nil {
machineKey.ExpirationDate = user.MachineKey.ExpirationDate.AsTime()
}
}
defaultMachine.MachineKey = &machineKey
}
return &defaultMachine
}
func AddInstancePbToSetupInstance(req *system_pb.AddInstanceRequest, defaultInstance command.InstanceSetup, externalDomain string) *command.InstanceSetup {
if req.InstanceName != "" {
defaultInstance.InstanceName = req.InstanceName