fix(import): add import for app and machine keys (#4536)

* fix(import): add import for app and machine keys

* fix(export): add review changes

* fix(import): Apply suggestions from code review

Co-authored-by: Livio Spring <livio.a@gmail.com>

* fix(import): add review changes

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Stefan Benz 2022-10-18 16:07:30 +01:00 committed by GitHub
parent 3270a94291
commit 556f381a5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 648 additions and 131 deletions

View File

@ -1889,6 +1889,8 @@ This is an empty request
| jwt_idps | repeated zitadel.v1.v1.DataJWTIDP | - | |
| user_links | repeated zitadel.idp.v1.IDPUserLink | - | |
| domains | repeated zitadel.org.v1.Domain | - | |
| app_keys | repeated zitadel.v1.v1.DataAppKey | - | |
| machine_keys | repeated zitadel.v1.v1.DataMachineKey | - | |
@ -2909,6 +2911,8 @@ This is an empty response
| user_links | repeated ImportDataSuccessUserLinks | - | |
| user_metadata | repeated ImportDataSuccessUserMetadata | - | |
| domains | repeated string | - | |
| app_keys | repeated string | - | |
| machine_keys | repeated string | - | |

View File

@ -45,6 +45,23 @@ title: zitadel/v1.proto
### DataAppKey
| Field | Type | Description | Validation |
| ----- | ---- | ----------- | ----------- |
| id | string | - | |
| project_id | string | - | |
| app_id | string | - | |
| client_id | string | - | |
| type | zitadel.authn.v1.KeyType | - | |
| expiration_date | google.protobuf.Timestamp | - | |
| public_key | bytes | - | |
### DataHumanUser
@ -69,6 +86,21 @@ title: zitadel/v1.proto
### DataMachineKey
| Field | Type | Description | Validation |
| ----- | ---- | ----------- | ----------- |
| key_id | string | - | |
| user_id | string | - | |
| type | zitadel.authn.v1.KeyType | - | |
| expiration_date | google.protobuf.Timestamp | - | |
| public_key | bytes | - | |
### DataMachineUser
@ -147,6 +179,8 @@ title: zitadel/v1.proto
| idps | repeated zitadel.management.v1.AddIDPToLoginPolicyRequest | - | |
| user_links | repeated zitadel.idp.v1.IDPUserLink | - | |
| domains | repeated zitadel.org.v1.Domain | - | |
| app_keys | repeated DataAppKey | - | |
| machine_keys | repeated DataMachineKey | - | |

View File

@ -4,7 +4,9 @@ import (
"context"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/timestamppb"
authn_grpc "github.com/zitadel/zitadel/internal/api/grpc/authn"
text_grpc "github.com/zitadel/zitadel/internal/api/grpc/text"
"github.com/zitadel/zitadel/internal/domain"
caos_errors "github.com/zitadel/zitadel/internal/errors"
@ -156,7 +158,7 @@ func (s *Server) ExportData(ctx context.Context, req *admin_pb.ExportDataRequest
/******************************************************************************************************************
Users
******************************************************************************************************************/
org.HumanUsers, org.MachineUsers, org.UserMetadata, err = s.getUsers(ctx, org.GetOrgId(), req.WithPasswords, req.WithOtp)
org.HumanUsers, org.MachineUsers, org.UserMetadata, org.MachineKeys, err = s.getUsers(ctx, org.GetOrgId(), req.WithPasswords, req.WithOtp)
if err != nil {
return nil, err
}
@ -170,7 +172,7 @@ func (s *Server) ExportData(ctx context.Context, req *admin_pb.ExportDataRequest
/******************************************************************************************************************
Project and Applications
******************************************************************************************************************/
org.Projects, org.ProjectRoles, org.OidcApps, org.ApiApps, err = s.getProjectsAndApps(ctx, org.GetOrgId())
org.Projects, org.ProjectRoles, org.OidcApps, org.ApiApps, org.AppKeys, err = s.getProjectsAndApps(ctx, org.GetOrgId())
if err != nil {
return nil, err
}
@ -392,17 +394,15 @@ func (s *Server) getLoginPolicy(ctx context.Context, orgID string) (_ *managemen
}
idpLinksQuery, err := s.query.IDPLoginPolicyLinks(ctx, orgID, &query.IDPLoginPolicyLinksSearchQuery{})
if err != nil && !caos_errors.IsNotFound(err) {
if err != nil {
return nil, err
}
idpLinks := make([]*management_pb.AddCustomLoginPolicyRequest_IDP, 0)
if !caos_errors.IsNotFound(err) && idpLinksQuery != nil {
for _, idpLink := range idpLinksQuery.Links {
idpLinks = append(idpLinks, &management_pb.AddCustomLoginPolicyRequest_IDP{
IdpId: idpLink.IDPID,
OwnerType: idp_pb.IDPOwnerType(idpLink.IDPType),
})
}
for _, idpLink := range idpLinksQuery.Links {
idpLinks = append(idpLinks, &management_pb.AddCustomLoginPolicyRequest_IDP{
IdpId: idpLink.IDPID,
OwnerType: idp_pb.IDPOwnerType(idpLink.IDPType),
})
}
return &management_pb.AddCustomLoginPolicyRequest{
@ -437,21 +437,19 @@ func (s *Server) getUserLinks(ctx context.Context, orgID string) (_ []*idp_pb.ID
return nil, err
}
idpUserLinks, err := s.query.IDPUserLinks(ctx, &query.IDPUserLinksSearchQuery{Queries: []query.SearchQuery{userLinksResourceOwner}})
if err != nil && !caos_errors.IsNotFound(err) {
if err != nil {
return nil, err
}
userLinks := make([]*idp_pb.IDPUserLink, 0)
if !caos_errors.IsNotFound(err) && idpUserLinks != nil {
for _, idpUserLink := range idpUserLinks.Links {
userLinks = append(userLinks, &idp_pb.IDPUserLink{
UserId: idpUserLink.UserID,
IdpId: idpUserLink.IDPID,
IdpName: idpUserLink.IDPName,
ProvidedUserId: idpUserLink.ProvidedUserID,
ProvidedUserName: idpUserLink.ProvidedUsername,
IdpType: idp_pb.IDPType(idpUserLink.IDPType),
})
}
for _, idpUserLink := range idpUserLinks.Links {
userLinks = append(userLinks, &idp_pb.IDPUserLink{
UserId: idpUserLink.UserID,
IdpId: idpUserLink.IDPID,
IdpName: idpUserLink.IDPName,
ProvidedUserId: idpUserLink.ProvidedUserID,
ProvidedUserName: idpUserLink.ProvidedUsername,
IdpType: idp_pb.IDPType(idpUserLink.IDPType),
})
}
return userLinks, nil
@ -511,24 +509,22 @@ func (s *Server) getPrivacyPolicy(ctx context.Context, orgID string) (_ *managem
return nil, nil
}
func (s *Server) getUsers(ctx context.Context, org string, withPasswords bool, withOTP bool) (_ []*v1_pb.DataHumanUser, _ []*v1_pb.DataMachineUser, _ []*management_pb.SetUserMetadataRequest, err error) {
func (s *Server) getUsers(ctx context.Context, org string, withPasswords bool, withOTP bool) (_ []*v1_pb.DataHumanUser, _ []*v1_pb.DataMachineUser, _ []*management_pb.SetUserMetadataRequest, _ []*v1_pb.DataMachineKey, err error) {
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
orgSearch, err := query.NewUserResourceOwnerSearchQuery(org, query.TextEquals)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
users, err := s.query.SearchUsers(ctx, &query.UserSearchQueries{Queries: []query.SearchQuery{orgSearch}})
if err != nil && !caos_errors.IsNotFound(err) {
return nil, nil, nil, err
if err != nil {
return nil, nil, nil, nil, err
}
humanUsers := make([]*v1_pb.DataHumanUser, 0)
machineUsers := make([]*v1_pb.DataMachineUser, 0)
userMetadata := make([]*management_pb.SetUserMetadataRequest, 0)
if err != nil && caos_errors.IsNotFound(err) {
return humanUsers, machineUsers, userMetadata, nil
}
machineKeys := make([]*v1_pb.DataMachineKey, 0)
for _, user := range users.Users {
switch user.Type {
case domain.UserTypeHuman:
@ -563,7 +559,7 @@ func (s *Server) getUsers(ctx context.Context, org string, withPasswords bool, w
hashedPassword, hashAlgorithm, err := s.query.GetHumanPassword(ctx, org, user.ID)
pwspan.EndWithError(err)
if err != nil && !caos_errors.IsNotFound(err) {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
if err == nil && hashedPassword != nil {
dataUser.User.HashedPassword = &management_pb.ImportHumanUserRequest_HashedPassword{
@ -577,7 +573,7 @@ func (s *Server) getUsers(ctx context.Context, org string, withPasswords bool, w
code, err := s.query.GetHumanOTPSecret(ctx, user.ID, org)
otpspan.EndWithError(err)
if err != nil && !caos_errors.IsNotFound(err) {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
if err == nil && code != "" {
dataUser.User.OtpCode = code
@ -594,17 +590,40 @@ func (s *Server) getUsers(ctx context.Context, org string, withPasswords bool, w
Description: user.Machine.Description,
},
})
userIDQuery, err := query.NewAuthNKeyAggregateIDQuery(user.ID)
if err != nil {
return nil, nil, nil, nil, err
}
orgIDQuery, err := query.NewAuthNKeyResourceOwnerQuery(org)
if err != nil {
return nil, nil, nil, nil, err
}
keys, err := s.query.SearchAuthNKeysData(ctx, &query.AuthNKeySearchQueries{Queries: []query.SearchQuery{userIDQuery, orgIDQuery}})
if err != nil {
return nil, nil, nil, nil, err
}
for _, key := range keys.AuthNKeysData {
machineKeys = append(machineKeys, &v1_pb.DataMachineKey{
KeyId: key.ID,
UserId: user.ID,
Type: authn_grpc.KeyTypeToPb(key.Type),
ExpirationDate: timestamppb.New(key.Expiration),
PublicKey: key.PublicKey,
})
}
}
ctx, metaspan := tracing.NewSpan(ctx)
metadataOrgSearch, err := query.NewUserMetadataResourceOwnerSearchQuery(org)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
metadataList, err := s.query.SearchUserMetadata(ctx, false, user.ID, &query.UserMetadataSearchQueries{Queries: []query.SearchQuery{metadataOrgSearch}})
metaspan.EndWithError(err)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
for _, metadata := range metadataList.Metadata {
userMetadata = append(userMetadata, &management_pb.SetUserMetadataRequest{
@ -614,7 +633,7 @@ func (s *Server) getUsers(ctx context.Context, org string, withPasswords bool, w
})
}
}
return humanUsers, machineUsers, userMetadata, nil
return humanUsers, machineUsers, userMetadata, machineKeys, nil
}
func (s *Server) getTriggerActions(ctx context.Context, org string, processedActions []string) (_ []*management_pb.SetTriggerActionsRequest, err error) {
@ -655,13 +674,10 @@ func (s *Server) getActions(ctx context.Context, org string) ([]*v1_pb.DataActio
return nil, err
}
queriedActions, err := s.query.SearchActions(ctx, &query.ActionSearchQueries{Queries: []query.SearchQuery{actionSearch}})
if err != nil && !caos_errors.IsNotFound(err) {
if err != nil {
return nil, err
}
actions := make([]*v1_pb.DataAction, len(queriedActions.Actions))
if err != nil && caos_errors.IsNotFound(err) {
return actions, nil
}
for i, action := range queriedActions.Actions {
timeout := durationpb.New(action.Timeout())
@ -679,23 +695,21 @@ func (s *Server) getActions(ctx context.Context, org string) ([]*v1_pb.DataActio
return actions, nil
}
func (s *Server) getProjectsAndApps(ctx context.Context, org string) ([]*v1_pb.DataProject, []*management_pb.AddProjectRoleRequest, []*v1_pb.DataOIDCApplication, []*v1_pb.DataAPIApplication, error) {
func (s *Server) getProjectsAndApps(ctx context.Context, org string) ([]*v1_pb.DataProject, []*management_pb.AddProjectRoleRequest, []*v1_pb.DataOIDCApplication, []*v1_pb.DataAPIApplication, []*v1_pb.DataAppKey, error) {
projectSearch, err := query.NewProjectResourceOwnerSearchQuery(org)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
queriedProjects, err := s.query.SearchProjects(ctx, &query.ProjectSearchQueries{Queries: []query.SearchQuery{projectSearch}})
if err != nil && !caos_errors.IsNotFound(err) {
return nil, nil, nil, nil, err
if err != nil {
return nil, nil, nil, nil, nil, err
}
projects := make([]*v1_pb.DataProject, len(queriedProjects.Projects))
orgProjectRoles := make([]*management_pb.AddProjectRoleRequest, 0)
oidcApps := make([]*v1_pb.DataOIDCApplication, 0)
apiApps := make([]*v1_pb.DataAPIApplication, 0)
if err != nil && caos_errors.IsNotFound(err) {
return projects, orgProjectRoles, oidcApps, apiApps, nil
}
appKeys := make([]*v1_pb.DataAppKey, 0)
for i, queriedProject := range queriedProjects.Projects {
projects[i] = &v1_pb.DataProject{
ProjectId: queriedProject.ID,
@ -710,81 +724,104 @@ func (s *Server) getProjectsAndApps(ctx context.Context, org string) ([]*v1_pb.D
projectRoleSearch, err := query.NewProjectRoleProjectIDSearchQuery(queriedProject.ID)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
queriedProjectRoles, err := s.query.SearchProjectRoles(ctx, false, &query.ProjectRoleSearchQueries{Queries: []query.SearchQuery{projectRoleSearch}})
if err != nil && !caos_errors.IsNotFound(err) {
return nil, nil, nil, nil, err
if err != nil {
return nil, nil, nil, nil, nil, err
}
if queriedProjectRoles != nil {
for _, role := range queriedProjectRoles.ProjectRoles {
orgProjectRoles = append(orgProjectRoles, &management_pb.AddProjectRoleRequest{
ProjectId: role.ProjectID,
RoleKey: role.Key,
DisplayName: role.DisplayName,
Group: role.Group,
})
}
for _, role := range queriedProjectRoles.ProjectRoles {
orgProjectRoles = append(orgProjectRoles, &management_pb.AddProjectRoleRequest{
ProjectId: role.ProjectID,
RoleKey: role.Key,
DisplayName: role.DisplayName,
Group: role.Group,
})
}
appSearch, err := query.NewAppProjectIDSearchQuery(queriedProject.ID)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
apps, err := s.query.SearchApps(ctx, &query.AppSearchQueries{Queries: []query.SearchQuery{appSearch}})
if err != nil && !caos_errors.IsNotFound(err) {
return nil, nil, nil, nil, err
if err != nil {
return nil, nil, nil, nil, nil, err
}
if apps != nil {
for _, app := range apps.Apps {
if app.OIDCConfig != nil {
responseTypes := make([]app_pb.OIDCResponseType, 0)
for _, ty := range app.OIDCConfig.ResponseTypes {
responseTypes = append(responseTypes, app_pb.OIDCResponseType(ty))
}
grantTypes := make([]app_pb.OIDCGrantType, 0)
for _, ty := range app.OIDCConfig.GrantTypes {
grantTypes = append(grantTypes, app_pb.OIDCGrantType(ty))
}
oidcApps = append(oidcApps, &v1_pb.DataOIDCApplication{
AppId: app.ID,
App: &management_pb.AddOIDCAppRequest{
ProjectId: app.ProjectID,
Name: app.Name,
RedirectUris: app.OIDCConfig.RedirectURIs,
ResponseTypes: responseTypes,
GrantTypes: grantTypes,
AppType: app_pb.OIDCAppType(app.OIDCConfig.AppType),
AuthMethodType: app_pb.OIDCAuthMethodType(app.OIDCConfig.AuthMethodType),
PostLogoutRedirectUris: app.OIDCConfig.PostLogoutRedirectURIs,
Version: app_pb.OIDCVersion(app.OIDCConfig.Version),
DevMode: app.OIDCConfig.IsDevMode,
AccessTokenType: app_pb.OIDCTokenType(app.OIDCConfig.AccessTokenType),
AccessTokenRoleAssertion: app.OIDCConfig.AssertAccessTokenRole,
IdTokenRoleAssertion: app.OIDCConfig.AssertIDTokenRole,
IdTokenUserinfoAssertion: app.OIDCConfig.AssertIDTokenUserinfo,
ClockSkew: durationpb.New(app.OIDCConfig.ClockSkew),
AdditionalOrigins: app.OIDCConfig.AdditionalOrigins,
},
})
for _, app := range apps.Apps {
if app.OIDCConfig != nil {
responseTypes := make([]app_pb.OIDCResponseType, 0)
for _, ty := range app.OIDCConfig.ResponseTypes {
responseTypes = append(responseTypes, app_pb.OIDCResponseType(ty))
}
if app.APIConfig != nil {
apiApps = append(apiApps, &v1_pb.DataAPIApplication{
AppId: app.ID,
App: &management_pb.AddAPIAppRequest{
ProjectId: app.ProjectID,
Name: app.Name,
AuthMethodType: app_pb.APIAuthMethodType(app.APIConfig.AuthMethodType),
},
})
grantTypes := make([]app_pb.OIDCGrantType, 0)
for _, ty := range app.OIDCConfig.GrantTypes {
grantTypes = append(grantTypes, app_pb.OIDCGrantType(ty))
}
oidcApps = append(oidcApps, &v1_pb.DataOIDCApplication{
AppId: app.ID,
App: &management_pb.AddOIDCAppRequest{
ProjectId: app.ProjectID,
Name: app.Name,
RedirectUris: app.OIDCConfig.RedirectURIs,
ResponseTypes: responseTypes,
GrantTypes: grantTypes,
AppType: app_pb.OIDCAppType(app.OIDCConfig.AppType),
AuthMethodType: app_pb.OIDCAuthMethodType(app.OIDCConfig.AuthMethodType),
PostLogoutRedirectUris: app.OIDCConfig.PostLogoutRedirectURIs,
Version: app_pb.OIDCVersion(app.OIDCConfig.Version),
DevMode: app.OIDCConfig.IsDevMode,
AccessTokenType: app_pb.OIDCTokenType(app.OIDCConfig.AccessTokenType),
AccessTokenRoleAssertion: app.OIDCConfig.AssertAccessTokenRole,
IdTokenRoleAssertion: app.OIDCConfig.AssertIDTokenRole,
IdTokenUserinfoAssertion: app.OIDCConfig.AssertIDTokenUserinfo,
ClockSkew: durationpb.New(app.OIDCConfig.ClockSkew),
AdditionalOrigins: app.OIDCConfig.AdditionalOrigins,
},
})
}
if app.APIConfig != nil {
apiApps = append(apiApps, &v1_pb.DataAPIApplication{
AppId: app.ID,
App: &management_pb.AddAPIAppRequest{
ProjectId: app.ProjectID,
Name: app.Name,
AuthMethodType: app_pb.APIAuthMethodType(app.APIConfig.AuthMethodType),
},
})
}
appIDQuery, err := query.NewAuthNKeyObjectIDQuery(app.ID)
if err != nil {
return nil, nil, nil, nil, nil, err
}
projectIDQuery, err := query.NewAuthNKeyAggregateIDQuery(app.ProjectID)
if err != nil {
return nil, nil, nil, nil, nil, err
}
orgIDQuery, err := query.NewAuthNKeyResourceOwnerQuery(org)
if err != nil {
return nil, nil, nil, nil, nil, err
}
keys, err := s.query.SearchAuthNKeysData(ctx, &query.AuthNKeySearchQueries{Queries: []query.SearchQuery{appIDQuery, projectIDQuery, orgIDQuery}})
if err != nil {
return nil, nil, nil, nil, nil, err
}
for _, key := range keys.AuthNKeysData {
appKeys = append(appKeys, &v1_pb.DataAppKey{
Id: key.ID,
ProjectId: app.ProjectID,
AppId: app.ID,
Type: authn_grpc.KeyTypeToPb(key.Type),
ExpirationDate: timestamppb.New(key.Expiration),
ClientId: key.Identifier,
PublicKey: key.PublicKey,
})
}
}
}
return projects, orgProjectRoles, oidcApps, apiApps, nil
return projects, orgProjectRoles, oidcApps, apiApps, appKeys, nil
}
func (s *Server) getNecessaryProjectGrantMembersForOrg(ctx context.Context, org string, processedProjects []string, processedGrants []string, processedUsers []string) ([]*management_pb.AddProjectGrantMemberRequest, error) {

View File

@ -19,6 +19,7 @@ import (
"github.com/zitadel/zitadel/internal/api/authz"
action_grpc "github.com/zitadel/zitadel/internal/api/grpc/action"
"github.com/zitadel/zitadel/internal/api/grpc/authn"
"github.com/zitadel/zitadel/internal/api/grpc/management"
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
@ -63,6 +64,8 @@ type count struct {
orgMemberLen int
projectGrantMemberCount int
projectGrantMemberLen int
appKeysCount int
machineKeysCount int
}
func (c *count) getProgress() string {
@ -336,6 +339,8 @@ func (s *Server) importData(ctx context.Context, orgs []*admin_pb.DataOrg) (*adm
count.projectMembersLen += len(org.GetProjectMembers())
count.orgMemberLen += len(org.GetOrgMembers())
count.projectGrantMemberLen += len(org.GetProjectGrantMembers())
count.machineKeysCount += len(org.GetMachineKeys())
count.appKeysCount += len(org.GetAppKeys())
}
for _, org := range orgs {
@ -583,6 +588,31 @@ func (s *Server) importData(ctx context.Context, orgs []*admin_pb.DataOrg) (*adm
successOrg.UserMetadata = append(successOrg.UserMetadata, &admin_pb.ImportDataSuccessUserMetadata{UserId: userMetadata.GetId(), Key: userMetadata.GetKey()})
}
}
if org.MachineKeys != nil {
for _, key := range org.GetMachineKeys() {
logging.Debugf("import machine_user_key: %s", key.KeyId)
_, err := s.command.AddUserMachineKeyWithID(ctx, &domain.MachineKey{
ObjectRoot: models.ObjectRoot{
AggregateID: key.UserId,
ResourceOwner: org.GetOrgId(),
},
KeyID: key.KeyId,
Type: authn.KeyTypeToDomain(key.Type),
ExpirationDate: key.ExpirationDate.AsTime(),
PublicKey: key.PublicKey,
}, org.GetOrgId())
if err != nil {
errors = append(errors, &admin_pb.ImportDataError{Type: "machine_user_key", Id: key.KeyId, Message: err.Error()})
if isCtxTimeout(ctx) {
return &admin_pb.ImportDataResponse{Errors: errors, Success: success}, count, err
}
continue
}
count.machineKeysCount += 1
logging.Debugf("successful machine_user_key %d: %s", count.machineKeysCount, key.KeyId)
successOrg.MachineKeys = append(successOrg.MachineKeys, key.KeyId)
}
}
if org.UserLinks != nil {
for _, userLinks := range org.GetUserLinks() {
logging.Debugf("import userlink: %s", userLinks.GetUserId()+"_"+userLinks.GetIdpId()+"_"+userLinks.GetProvidedUserId()+"_"+userLinks.GetProvidedUserName())
@ -652,6 +682,33 @@ func (s *Server) importData(ctx context.Context, orgs []*admin_pb.DataOrg) (*adm
successOrg.ApiAppIds = append(successOrg.ApiAppIds, app.GetAppId())
}
}
if org.AppKeys != nil {
for _, key := range org.GetAppKeys() {
logging.Debugf("import app_key: %s", key.Id)
_, err := s.command.AddApplicationKeyWithID(ctx, &domain.ApplicationKey{
ObjectRoot: models.ObjectRoot{
AggregateID: key.ProjectId,
ResourceOwner: org.GetOrgId(),
},
ApplicationID: key.AppId,
ClientID: key.ClientId,
KeyID: key.Id,
Type: authn.KeyTypeToDomain(key.Type),
ExpirationDate: key.ExpirationDate.AsTime(),
PublicKey: key.PublicKey,
}, org.GetOrgId())
if err != nil {
errors = append(errors, &admin_pb.ImportDataError{Type: "app_key", Id: key.Id, Message: err.Error()})
if isCtxTimeout(ctx) {
return &admin_pb.ImportDataResponse{Errors: errors, Success: success}, count, err
}
continue
}
count.appKeysCount += 1
logging.Debugf("successful app_key %d: %s", count.appKeysCount, key.Id)
successOrg.AppKeys = append(successOrg.AppKeys, key.Id)
}
}
if org.Actions != nil {
for _, action := range org.GetActions() {
logging.Debugf("import action: %s", action.GetActionId())
@ -848,6 +905,8 @@ func (s *Server) dataOrgsV1ToDataOrgs(ctx context.Context, dataOrgs *v1_pb.Impor
JwtIdps: orgV1.GetJwtIdps(),
UserLinks: orgV1.GetUserLinks(),
Domains: orgV1.GetDomains(),
AppKeys: orgV1.GetAppKeys(),
MachineKeys: orgV1.GetMachineKeys(),
}
if orgV1.IamPolicy != nil {
defaultDomainPolicy, err := s.query.DefaultDomainPolicy(ctx)

View File

@ -76,7 +76,7 @@ func (c *Commands) AddAPIApplicationWithID(ctx context.Context, apiApp *domain.A
return nil, err
}
if existingAPI.State != domain.AppStateUnspecified {
return nil, errors.ThrowPreconditionFailed(nil, "PROJECT-mabu12", "Errors.Application.AlreadyExisting")
return nil, errors.ThrowPreconditionFailed(nil, "PROJECT-mabu12", "Errors.Project.App.AlreadyExisting")
}
project, err := c.getProjectByID(ctx, apiApp.AggregateID, resourceOwner)
if err != nil {
@ -88,7 +88,7 @@ func (c *Commands) AddAPIApplicationWithID(ctx context.Context, apiApp *domain.A
func (c *Commands) AddAPIApplication(ctx context.Context, apiApp *domain.APIApp, resourceOwner string, appSecretGenerator crypto.Generator) (_ *domain.APIApp, err error) {
if apiApp == nil || apiApp.AggregateID == "" {
return nil, errors.ThrowInvalidArgument(nil, "PROJECT-5m9E", "Errors.Application.Invalid")
return nil, errors.ThrowInvalidArgument(nil, "PROJECT-5m9E", "Errors.Project.App.Invalid")
}
project, err := c.getProjectByID(ctx, apiApp.AggregateID, resourceOwner)
if err != nil {
@ -96,7 +96,7 @@ func (c *Commands) AddAPIApplication(ctx context.Context, apiApp *domain.APIApp,
}
if !apiApp.IsValid() {
return nil, errors.ThrowInvalidArgument(nil, "PROJECT-Bff2g", "Errors.Application.Invalid")
return nil, errors.ThrowInvalidArgument(nil, "PROJECT-Bff2g", "Errors.Project.App.Invalid")
}
appID, err := c.idGenerator.Next()

View File

@ -6,8 +6,27 @@ import (
"github.com/zitadel/zitadel/internal/domain"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/repository/project"
"github.com/zitadel/zitadel/internal/telemetry/tracing"
)
func (c *Commands) AddApplicationKeyWithID(ctx context.Context, key *domain.ApplicationKey, resourceOwner string) (_ *domain.ApplicationKey, err error) {
writeModel, err := c.applicationKeyWriteModelByID(ctx, key.AggregateID, key.ApplicationID, key.KeyID, resourceOwner)
if err != nil {
return nil, err
}
if writeModel.State != domain.AppStateUnspecified {
return nil, errors.ThrowPreconditionFailed(nil, "COMMAND-so20alo", "Errors.Project.App.Key.AlreadyExisting")
}
application, err := c.getApplicationWriteModel(ctx, key.AggregateID, key.ApplicationID, resourceOwner)
if err != nil {
return nil, err
}
if !application.State.Exists() {
return nil, errors.ThrowPreconditionFailed(nil, "COMMAND-sak24", "Errors.Project.App.NotFound")
}
return c.addApplicationKey(ctx, key, resourceOwner)
}
func (c *Commands) AddApplicationKey(ctx context.Context, key *domain.ApplicationKey, resourceOwner string) (_ *domain.ApplicationKey, err error) {
if key.AggregateID == "" || key.ApplicationID == "" {
return nil, errors.ThrowInvalidArgument(nil, "COMMAND-55m9fs", "Errors.IDMissing")
@ -17,12 +36,18 @@ func (c *Commands) AddApplicationKey(ctx context.Context, key *domain.Applicatio
return nil, err
}
if !application.State.Exists() {
return nil, errors.ThrowPreconditionFailed(nil, "COMMAND-sak25", "Errors.Application.NotFound")
return nil, errors.ThrowPreconditionFailed(nil, "COMMAND-sak25", "Errors.Project.App.NotFound")
}
key.KeyID, err = c.idGenerator.Next()
if err != nil {
return nil, err
}
return c.addApplicationKey(ctx, key, resourceOwner)
}
func (c *Commands) addApplicationKey(ctx context.Context, key *domain.ApplicationKey, resourceOwner string) (_ *domain.ApplicationKey, err error) {
keyWriteModel := NewApplicationKeyWriteModel(key.AggregateID, key.ApplicationID, key.KeyID, resourceOwner)
err = c.eventstore.FilterToQueryReducer(ctx, keyWriteModel)
if err != nil {
@ -37,11 +62,13 @@ func (c *Commands) AddApplicationKey(ctx context.Context, key *domain.Applicatio
return nil, err
}
err = domain.SetNewAuthNKeyPair(key, c.applicationKeySize)
if err != nil {
return nil, err
if len(key.PublicKey) == 0 {
err = domain.SetNewAuthNKeyPair(key, c.applicationKeySize)
if err != nil {
return nil, err
}
key.ClientID = keyWriteModel.ClientID
}
key.ClientID = keyWriteModel.ClientID
pushedEvents, err := c.eventstore.Push(ctx,
project.NewApplicationKeyAddedEvent(
@ -61,7 +88,10 @@ func (c *Commands) AddApplicationKey(ctx context.Context, key *domain.Applicatio
if err != nil {
return nil, err
}
result := applicationKeyWriteModelToKey(keyWriteModel, key.PrivateKey)
result := applicationKeyWriteModelToKey(keyWriteModel)
if len(key.PrivateKey) > 0 {
result.PrivateKey = key.PrivateKey
}
return result, nil
}
@ -72,7 +102,7 @@ func (c *Commands) RemoveApplicationKey(ctx context.Context, projectID, applicat
return nil, err
}
if !keyWriteModel.State.Exists() {
return nil, errors.ThrowNotFound(nil, "COMMAND-4m77G", "Errors.Application.Key.NotFound")
return nil, errors.ThrowNotFound(nil, "COMMAND-4m77G", "Errors.Project.App.Key.NotFound")
}
pushedEvents, err := c.eventstore.Push(ctx, project.NewApplicationKeyRemovedEvent(ctx, ProjectAggregateFromWriteModel(&keyWriteModel.WriteModel), keyID))
@ -85,3 +115,18 @@ func (c *Commands) RemoveApplicationKey(ctx context.Context, projectID, applicat
}
return writeModelToObjectDetails(&keyWriteModel.WriteModel), nil
}
func (c *Commands) applicationKeyWriteModelByID(ctx context.Context, projectID, appID, keyID, resourceOwner string) (writeModel *ApplicationKeyWriteModel, err error) {
if appID == "" {
return nil, errors.ThrowInvalidArgument(nil, "COMMAND-029sn", "Errors.Project.App.NotFound")
}
ctx, span := tracing.NewSpan(ctx)
defer func() { span.EndWithError(err) }()
writeModel = NewApplicationKeyWriteModel(projectID, appID, keyID, resourceOwner)
err = c.eventstore.FilterToQueryReducer(ctx, writeModel)
if err != nil {
return nil, err
}
return writeModel, nil
}

View File

@ -40,7 +40,7 @@ type addOIDCApp struct {
ClientSecretPlain string
}
//AddOIDCAppCommand prepares the commands to add an oidc app. The ClientID will be set during the CreateCommands
// AddOIDCAppCommand prepares the commands to add an oidc app. The ClientID will be set during the CreateCommands
func (c *Commands) AddOIDCAppCommand(app *addOIDCApp, clientSecretAlg crypto.HashAlgorithm) preparation.Validation {
return func() (preparation.CreateCommands, error) {
if app.ID == "" {
@ -122,7 +122,7 @@ func (c *Commands) AddOIDCApplicationWithID(ctx context.Context, oidcApp *domain
return nil, err
}
if existingApp.State != domain.AppStateUnspecified {
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-lxowmp", "Errors.Application.AlreadyExisting")
return nil, caos_errs.ThrowPreconditionFailed(nil, "PROJECT-lxowmp", "Errors.Project.App.AlreadyExisting")
}
project, err := c.getProjectByID(ctx, oidcApp.AggregateID, resourceOwner)
@ -135,7 +135,7 @@ func (c *Commands) AddOIDCApplicationWithID(ctx context.Context, oidcApp *domain
func (c *Commands) AddOIDCApplication(ctx context.Context, oidcApp *domain.OIDCApp, resourceOwner string, appSecretGenerator crypto.Generator) (_ *domain.OIDCApp, err error) {
if oidcApp == nil || oidcApp.AggregateID == "" {
return nil, caos_errs.ThrowInvalidArgument(nil, "PROJECT-34Fm0", "Errors.Application.Invalid")
return nil, caos_errs.ThrowInvalidArgument(nil, "PROJECT-34Fm0", "Errors.Project.App.Invalid")
}
project, err := c.getProjectByID(ctx, oidcApp.AggregateID, resourceOwner)
if err != nil {
@ -143,7 +143,7 @@ func (c *Commands) AddOIDCApplication(ctx context.Context, oidcApp *domain.OIDCA
}
if oidcApp.AppName == "" || !oidcApp.IsValid() {
return nil, caos_errs.ThrowInvalidArgument(nil, "PROJECT-1n8df", "Errors.Application.Invalid")
return nil, caos_errs.ThrowInvalidArgument(nil, "PROJECT-1n8df", "Errors.Project.App.Invalid")
}
appID, err := c.idGenerator.Next()

View File

@ -98,7 +98,7 @@ func memberWriteModelToProjectGrantMember(writeModel *ProjectGrantMemberWriteMod
}
}
func applicationKeyWriteModelToKey(wm *ApplicationKeyWriteModel, privateKey []byte) *domain.ApplicationKey {
func applicationKeyWriteModelToKey(wm *ApplicationKeyWriteModel) *domain.ApplicationKey {
return &domain.ApplicationKey{
ObjectRoot: writeModelToObjectRoot(wm.WriteModel),
ApplicationID: wm.AppID,
@ -106,6 +106,5 @@ func applicationKeyWriteModelToKey(wm *ApplicationKeyWriteModel, privateKey []by
KeyID: wm.KeyID,
Type: wm.KeyType,
ExpirationDate: wm.ExpirationDate,
PrivateKey: privateKey,
}
}

View File

@ -9,34 +9,51 @@ import (
"github.com/zitadel/zitadel/internal/telemetry/tracing"
)
func (c *Commands) AddUserMachineKey(ctx context.Context, machineKey *domain.MachineKey, resourceOwner string) (*domain.MachineKey, error) {
err := c.checkUserExists(ctx, machineKey.AggregateID, resourceOwner)
func (c *Commands) AddUserMachineKeyWithID(ctx context.Context, machineKey *domain.MachineKey, resourceOwner string) (*domain.MachineKey, error) {
writeModel, err := c.machineKeyWriteModelByID(ctx, machineKey.AggregateID, machineKey.KeyID, resourceOwner)
if err != nil {
return nil, err
}
if writeModel.State != domain.MachineKeyStateUnspecified {
return nil, errors.ThrowNotFound(nil, "COMMAND-p22101", "Errors.User.Machine.Key.AlreadyExisting")
}
return c.addUserMachineKey(ctx, machineKey, resourceOwner)
}
func (c *Commands) AddUserMachineKey(ctx context.Context, machineKey *domain.MachineKey, resourceOwner string) (*domain.MachineKey, error) {
keyID, err := c.idGenerator.Next()
if err != nil {
return nil, err
}
keyWriteModel := NewMachineKeyWriteModel(machineKey.AggregateID, keyID, resourceOwner)
err = c.eventstore.FilterToQueryReducer(ctx, keyWriteModel)
machineKey.KeyID = keyID
return c.addUserMachineKey(ctx, machineKey, resourceOwner)
}
func (c *Commands) addUserMachineKey(ctx context.Context, machineKey *domain.MachineKey, resourceOwner string) (*domain.MachineKey, error) {
err := c.checkUserExists(ctx, machineKey.AggregateID, resourceOwner)
if err != nil {
return nil, err
}
if err = domain.EnsureValidExpirationDate(machineKey); err != nil {
keyWriteModel := NewMachineKeyWriteModel(machineKey.AggregateID, machineKey.KeyID, resourceOwner)
if err := c.eventstore.FilterToQueryReducer(ctx, keyWriteModel); err != nil {
return nil, err
}
if err = domain.SetNewAuthNKeyPair(machineKey, c.machineKeySize); err != nil {
if err := domain.EnsureValidExpirationDate(machineKey); err != nil {
return nil, err
}
if len(machineKey.PublicKey) == 0 {
if err := domain.SetNewAuthNKeyPair(machineKey, c.machineKeySize); err != nil {
return nil, err
}
}
events, err := c.eventstore.Push(ctx,
user.NewMachineKeyAddedEvent(
ctx,
UserAggregateFromWriteModel(&keyWriteModel.WriteModel),
keyID,
machineKey.KeyID,
machineKey.Type,
machineKey.ExpirationDate,
machineKey.PublicKey))
@ -49,7 +66,9 @@ func (c *Commands) AddUserMachineKey(ctx context.Context, machineKey *domain.Mac
}
key := keyWriteModelToMachineKey(keyWriteModel)
key.PrivateKey = machineKey.PrivateKey
if len(machineKey.PrivateKey) > 0 {
key.PrivateKey = machineKey.PrivateKey
}
return key, nil
}

View File

@ -84,6 +84,23 @@ type AuthNKey struct {
Type domain.AuthNKeyType
}
type AuthNKeysData struct {
SearchResponse
AuthNKeysData []*AuthNKeyData
}
type AuthNKeyData struct {
ID string
CreationDate time.Time
ResourceOwner string
Sequence uint64
Expiration time.Time
Type domain.AuthNKeyType
Identifier string
PublicKey []byte
}
type AuthNKeySearchQueries struct {
SearchRequest
Queries []SearchQuery
@ -122,6 +139,30 @@ func (q *Queries) SearchAuthNKeys(ctx context.Context, queries *AuthNKeySearchQu
return authNKeys, err
}
func (q *Queries) SearchAuthNKeysData(ctx context.Context, queries *AuthNKeySearchQueries) (authNKeys *AuthNKeysData, err error) {
query, scan := prepareAuthNKeysDataQuery()
query = queries.toQuery(query)
stmt, args, err := query.Where(
sq.Eq{
AuthNKeyColumnEnabled.identifier(): true,
},
).ToSql()
if err != nil {
return nil, errors.ThrowInvalidArgument(err, "QUERY-SAg3f", "Errors.Query.InvalidRequest")
}
rows, err := q.client.QueryContext(ctx, stmt, args...)
if err != nil {
return nil, errors.ThrowInternal(err, "QUERY-Dbi53", "Errors.Internal")
}
authNKeys, err = scan(rows)
if err != nil {
return nil, err
}
authNKeys.LatestSequence, err = q.latestSequence(ctx, authNKeyTable)
return authNKeys, err
}
func (q *Queries) GetAuthNKeyByID(ctx context.Context, shouldTriggerBulk bool, id string, queries ...SearchQuery) (*AuthNKey, error) {
if shouldTriggerBulk {
projection.AuthNKeyProjection.Trigger(ctx)
@ -270,3 +311,50 @@ func prepareAuthNKeyPublicKeyQuery() (sq.SelectBuilder, func(row *sql.Row) ([]by
return publicKey, nil
}
}
func prepareAuthNKeysDataQuery() (sq.SelectBuilder, func(rows *sql.Rows) (*AuthNKeysData, error)) {
return sq.Select(
AuthNKeyColumnID.identifier(),
AuthNKeyColumnCreationDate.identifier(),
AuthNKeyColumnResourceOwner.identifier(),
AuthNKeyColumnSequence.identifier(),
AuthNKeyColumnExpiration.identifier(),
AuthNKeyColumnType.identifier(),
AuthNKeyColumnIdentifier.identifier(),
AuthNKeyColumnPublicKey.identifier(),
countColumn.identifier(),
).From(authNKeyTable.identifier()).PlaceholderFormat(sq.Dollar),
func(rows *sql.Rows) (*AuthNKeysData, error) {
authNKeys := make([]*AuthNKeyData, 0)
var count uint64
for rows.Next() {
authNKey := new(AuthNKeyData)
err := rows.Scan(
&authNKey.ID,
&authNKey.CreationDate,
&authNKey.ResourceOwner,
&authNKey.Sequence,
&authNKey.Expiration,
&authNKey.Type,
&authNKey.Identifier,
&authNKey.PublicKey,
&count,
)
if err != nil {
return nil, err
}
authNKeys = append(authNKeys, authNKey)
}
if err := rows.Close(); err != nil {
return nil, errors.ThrowInternal(err, "QUERY-Dgfn3", "Errors.Query.CloseRows")
}
return &AuthNKeysData{
AuthNKeysData: authNKeys,
SearchResponse: SearchResponse{
Count: count,
},
}, nil
}
}

View File

@ -182,6 +182,189 @@ func Test_AuthNKeyPrepares(t *testing.T) {
},
object: nil,
},
{
name: "prepareAuthNKeysDataQuery no result",
prepare: prepareAuthNKeysDataQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys.id,`+
` projections.authn_keys.creation_date,`+
` projections.authn_keys.resource_owner,`+
` projections.authn_keys.sequence,`+
` projections.authn_keys.expiration,`+
` projections.authn_keys.type,`+
` projections.authn_keys.identifier,`+
` projections.authn_keys.public_key,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys`),
nil,
nil,
),
},
object: &AuthNKeysData{AuthNKeysData: []*AuthNKeyData{}},
},
{
name: "prepareAuthNKeysDataQuery one result",
prepare: prepareAuthNKeysDataQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys.id,`+
` projections.authn_keys.creation_date,`+
` projections.authn_keys.resource_owner,`+
` projections.authn_keys.sequence,`+
` projections.authn_keys.expiration,`+
` projections.authn_keys.type,`+
` projections.authn_keys.identifier,`+
` projections.authn_keys.public_key,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys`),
[]string{
"id",
"creation_date",
"resource_owner",
"sequence",
"expiration",
"type",
"identifier",
"public_key",
"count",
},
[][]driver.Value{
{
"id",
testNow,
"ro",
uint64(20211109),
testNow,
1,
"identifier",
[]byte("public"),
},
},
),
},
object: &AuthNKeysData{
SearchResponse: SearchResponse{
Count: 1,
},
AuthNKeysData: []*AuthNKeyData{
{
ID: "id",
CreationDate: testNow,
ResourceOwner: "ro",
Sequence: 20211109,
Expiration: testNow,
Type: domain.AuthNKeyTypeJSON,
Identifier: "identifier",
PublicKey: []byte("public"),
},
},
},
},
{
name: "prepareAuthNKeysDataQuery multiple result",
prepare: prepareAuthNKeysDataQuery,
want: want{
sqlExpectations: mockQueries(
regexp.QuoteMeta(`SELECT projections.authn_keys.id,`+
` projections.authn_keys.creation_date,`+
` projections.authn_keys.resource_owner,`+
` projections.authn_keys.sequence,`+
` projections.authn_keys.expiration,`+
` projections.authn_keys.type,`+
` projections.authn_keys.identifier,`+
` projections.authn_keys.public_key,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys`),
[]string{
"id",
"creation_date",
"resource_owner",
"sequence",
"expiration",
"type",
"identifier",
"public_key",
"count",
},
[][]driver.Value{
{
"id-1",
testNow,
"ro",
uint64(20211109),
testNow,
1,
"identifier1",
[]byte("public1"),
},
{
"id-2",
testNow,
"ro",
uint64(20211109),
testNow,
1,
"identifier2",
[]byte("public2"),
},
},
),
},
object: &AuthNKeysData{
SearchResponse: SearchResponse{
Count: 2,
},
AuthNKeysData: []*AuthNKeyData{
{
ID: "id-1",
CreationDate: testNow,
ResourceOwner: "ro",
Sequence: 20211109,
Expiration: testNow,
Type: domain.AuthNKeyTypeJSON,
Identifier: "identifier1",
PublicKey: []byte("public1"),
},
{
ID: "id-2",
CreationDate: testNow,
ResourceOwner: "ro",
Sequence: 20211109,
Expiration: testNow,
Type: domain.AuthNKeyTypeJSON,
Identifier: "identifier2",
PublicKey: []byte("public2"),
},
},
},
},
{
name: "prepareAuthNKeysDataQuery sql err",
prepare: prepareAuthNKeysDataQuery,
want: want{
sqlExpectations: mockQueryErr(
regexp.QuoteMeta(`SELECT projections.authn_keys.id,`+
` projections.authn_keys.creation_date,`+
` projections.authn_keys.resource_owner,`+
` projections.authn_keys.sequence,`+
` projections.authn_keys.expiration,`+
` projections.authn_keys.type,`+
` projections.authn_keys.identifier,`+
` projections.authn_keys.public_key,`+
` COUNT(*) OVER ()`+
` FROM projections.authn_keys`),
sql.ErrConnDone,
),
err: func(err error) (error, bool) {
if !errors.Is(err, sql.ErrConnDone) {
return fmt.Errorf("err should be sql.ErrConnDone got: %w", err), false
}
return nil, true
},
},
object: nil,
},
{
name: "prepareAuthNKeyQuery no result",
prepare: prepareAuthNKeyQuery,

View File

@ -85,7 +85,8 @@ Errors:
NotChanged: Adresse wurde nicht geändert
Machine:
Key:
NotFound: Maschinen Key nicht gefunden
NotFound: Maschinen Schlüssel nicht gefunden
AlreadyExisting: Machine Schlüssel exisiert bereits
PAT:
NotFound: Persönliches Access Token nicht gefunden
NotHuman: Der Benutzer muss eine Person sein
@ -264,6 +265,9 @@ Errors:
APIAuthMethodNoSecret: Gewählte API Auth Method benötigt kein Secret
AuthMethodNoPrivateKeyJWT: Gewählte Auth Method benötigt keinen Key
ClientSecretInvalid: Client Secret ist ungültig
Key:
AlreadyExisting: Applikationsschlüssel existiert bereits
NotFound: Applikationsschlüssel nicht gefunden
RequiredFieldsMissing: Benötigte Felder fehlen
Grant:
AlreadyExists: Projekt Grant existiert bereits

View File

@ -86,6 +86,7 @@ Errors:
Machine:
Key:
NotFound: Machine key not found
AlreadyExisting: Machine key already existing
PAT:
NotFound: Personal Access Token not found
NotHuman: The User must be personal
@ -264,6 +265,9 @@ Errors:
APIAuthMethodNoSecret: Chosen API Auth Method does not require a secret
AuthMethodNoPrivateKeyJWT: Chosen Auth Method does not require a key
ClientSecretInvalid: Client Secret is invalid
Key:
AlreadyExisting: Application key already existing
NotFound: Application key not found
RequiredFieldsMissing: Some required fields are missing
Grant:
AlreadyExists: Project grant already exists

View File

@ -86,6 +86,7 @@ Errors:
Machine:
Key:
NotFound: Clé de la machine non trouvée
AlreadyExisting: Clé de la machine déjà existante
PAT:
NotFound: Token d'accès personnel non trouvé
NotHuman: L'utilisateur doit être personnel
@ -264,6 +265,9 @@ Errors:
APIAuthMethodNoSecret: La méthode d'authentification API choisie ne nécessite pas de secret.
AuthMethodNoPrivateKeyJWT: La méthode d'authentification choisie ne nécessite pas de clé.
ClientSecretInvalid: Le secret du client n'est pas valide
Key:
AlreadyExisting: Clé d'application déjà existante
NotFound: Clé d'application non trouvée
RequiredFieldsMissing: Certains champs obligatoires sont manquants
Grant:
AlreadyExists: La subvention du projet existe déjà

View File

@ -85,7 +85,8 @@ Errors:
NotChanged: Indirizzo non cambiato
Machine:
Key:
NotFound: Machine Key non trovato
NotFound: Chiave macchina non trovato
AlreadyExisting: Chiave macchina già esistente
PAT:
NotFound: Personal Access Token non trovato
NotHuman: L'utente deve essere personale
@ -264,6 +265,9 @@ Errors:
APIAuthMethodNoSecret: Il metodo di autorizzazione API scelto non richiede un segreto
AuthMethodNoPrivateKeyJWT: Il metodo di autorizzazione scelto non richiede una chiave
ClientSecretInvalid: Il segreto del cliente non è valido
Key:
AlreadyExisting: Chiave di applicazione già esistente
NotFound: Chiave di applicazione non trovata
RequiredFieldsMissing: Mancano alcuni campi obbligatori
Grant:
AlreadyExists: Grant del progetto già esistente

View File

@ -86,6 +86,7 @@ Errors:
Machine:
Key:
NotFound: 未找到机器密钥
AlreadyExisting: 已有的机器钥匙
PAT:
NotFound: 未找到个人访问令牌
NotHuman: 用户必须是个人
@ -259,6 +260,9 @@ Errors:
APIAuthMethodNoSecret: 选择的 API 身份验证方法不需要秘钥
AuthMethodNoPrivateKeyJWT: 选择的身份验证方法不需要 Key
ClientSecretInvalid: Client Secret 无效
Key:
AlreadyExisting: 已经存在的应用钥匙
NotFound: 未找到应用钥匙
RequiredFieldsMissing: 缺少一些必填字段
Grant:
AlreadyExists: 项目授权已存在

View File

@ -4763,6 +4763,9 @@ message DataOrg {
repeated zitadel.idp.v1.IDPUserLink user_links = 33;
repeated zitadel.org.v1.Domain domains = 34;
repeated zitadel.v1.v1.DataAppKey app_keys = 35;
repeated zitadel.v1.v1.DataMachineKey machine_keys = 36;
}
message ImportDataResponse{
@ -4801,6 +4804,8 @@ message ImportDataSuccessOrg{
repeated ImportDataSuccessUserLinks user_links = 18;
repeated ImportDataSuccessUserMetadata user_metadata = 19;
repeated string domains = 20;
repeated string app_keys = 21;
repeated string machine_keys = 22;
}
message ImportDataSuccessProjectGrant{

View File

@ -4,9 +4,12 @@ import "zitadel/user.proto";
import "zitadel/idp.proto";
import "zitadel/org.proto";
import "zitadel/management.proto";
import "zitadel/auth_n_key.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "google/protobuf/timestamp.proto";
import "validate/validate.proto";
package zitadel.v1.v1;
@ -84,7 +87,11 @@ message DataOrg {
repeated zitadel.idp.v1.IDPUserLink user_links = 36;
repeated zitadel.org.v1.Domain domains = 37;
repeated DataAppKey app_keys = 38;
repeated DataMachineKey machine_keys = 39;
}
message DataOIDCIDP{
string idp_id = 1;
zitadel.management.v1.AddOrgOIDCIDPRequest idp = 2;
@ -130,6 +137,23 @@ message ExportHumanUser {
string otp_code = 9;
}
message DataAppKey {
string id = 1;
string project_id = 2;
string app_id = 3;
string client_id = 4;
zitadel.authn.v1.KeyType type = 5;
google.protobuf.Timestamp expiration_date = 6;
bytes public_key = 7;
}
message DataMachineKey {
string key_id = 1;
string user_id = 2;
zitadel.authn.v1.KeyType type = 3;
google.protobuf.Timestamp expiration_date = 4;
bytes public_key = 5;
}
message DataProject {
string project_id = 1;