mirror of
https://github.com/zitadel/zitadel.git
synced 2025-07-01 10:28:38 +00:00
feat: add azure provider templates (#5441)
Adds possibility to manage and use Microsoft Azure template based providers
This commit is contained in:
parent
93e1fe0056
commit
5a307afe62
@ -241,6 +241,27 @@ func (s *Server) UpdateJWTProvider(ctx context.Context, req *admin_pb.UpdateJWTP
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) AddAzureADProvider(ctx context.Context, req *admin_pb.AddAzureADProviderRequest) (*admin_pb.AddAzureADProviderResponse, error) {
|
||||||
|
id, details, err := s.command.AddInstanceAzureADProvider(ctx, addAzureADProviderToCommand(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.AddAzureADProviderResponse{
|
||||||
|
Id: id,
|
||||||
|
Details: object_pb.DomainToAddDetailsPb(details),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) UpdateAzureADProvider(ctx context.Context, req *admin_pb.UpdateAzureADProviderRequest) (*admin_pb.UpdateAzureADProviderResponse, error) {
|
||||||
|
details, err := s.command.UpdateInstanceAzureADProvider(ctx, req.Id, updateAzureADProviderToCommand(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &admin_pb.UpdateAzureADProviderResponse{
|
||||||
|
Details: object_pb.DomainToChangeDetailsPb(details),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) AddGitHubProvider(ctx context.Context, req *admin_pb.AddGitHubProviderRequest) (*admin_pb.AddGitHubProviderResponse, error) {
|
func (s *Server) AddGitHubProvider(ctx context.Context, req *admin_pb.AddGitHubProviderRequest) (*admin_pb.AddGitHubProviderResponse, error) {
|
||||||
id, details, err := s.command.AddInstanceGitHubProvider(ctx, addGitHubProviderToCommand(req))
|
id, details, err := s.command.AddInstanceGitHubProvider(ctx, addGitHubProviderToCommand(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -273,6 +273,30 @@ func updateJWTProviderToCommand(req *admin_pb.UpdateJWTProviderRequest) command.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addAzureADProviderToCommand(req *admin_pb.AddAzureADProviderRequest) command.AzureADProvider {
|
||||||
|
return command.AzureADProvider{
|
||||||
|
Name: req.Name,
|
||||||
|
ClientID: req.ClientId,
|
||||||
|
ClientSecret: req.ClientSecret,
|
||||||
|
Scopes: req.Scopes,
|
||||||
|
Tenant: idp_grpc.AzureADTenantToCommand(req.Tenant),
|
||||||
|
EmailVerified: req.EmailVerified,
|
||||||
|
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateAzureADProviderToCommand(req *admin_pb.UpdateAzureADProviderRequest) command.AzureADProvider {
|
||||||
|
return command.AzureADProvider{
|
||||||
|
Name: req.Name,
|
||||||
|
ClientID: req.ClientId,
|
||||||
|
ClientSecret: req.ClientSecret,
|
||||||
|
Scopes: req.Scopes,
|
||||||
|
Tenant: idp_grpc.AzureADTenantToCommand(req.Tenant),
|
||||||
|
EmailVerified: req.EmailVerified,
|
||||||
|
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func addGitHubProviderToCommand(req *admin_pb.AddGitHubProviderRequest) command.GitHubProvider {
|
func addGitHubProviderToCommand(req *admin_pb.AddGitHubProviderRequest) command.GitHubProvider {
|
||||||
return command.GitHubProvider{
|
return command.GitHubProvider{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
obj_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
|
obj_grpc "github.com/zitadel/zitadel/internal/api/grpc/object"
|
||||||
"github.com/zitadel/zitadel/internal/domain"
|
"github.com/zitadel/zitadel/internal/domain"
|
||||||
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
iam_model "github.com/zitadel/zitadel/internal/iam/model"
|
||||||
|
"github.com/zitadel/zitadel/internal/idp/providers/azuread"
|
||||||
"github.com/zitadel/zitadel/internal/query"
|
"github.com/zitadel/zitadel/internal/query"
|
||||||
"github.com/zitadel/zitadel/internal/repository/idp"
|
"github.com/zitadel/zitadel/internal/repository/idp"
|
||||||
idp_pb "github.com/zitadel/zitadel/pkg/grpc/idp"
|
idp_pb "github.com/zitadel/zitadel/pkg/grpc/idp"
|
||||||
@ -329,6 +330,33 @@ func LDAPAttributesToCommand(attributes *idp_pb.LDAPAttributes) idp.LDAPAttribut
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AzureADTenantToCommand(tenant *idp_pb.AzureADTenant) string {
|
||||||
|
if tenant == nil {
|
||||||
|
return string(azuread.CommonTenant)
|
||||||
|
}
|
||||||
|
switch t := tenant.Type.(type) {
|
||||||
|
case *idp_pb.AzureADTenant_TenantType:
|
||||||
|
return string(azureADTenantTypeToCommand(t.TenantType))
|
||||||
|
case *idp_pb.AzureADTenant_TenantId:
|
||||||
|
return t.TenantId
|
||||||
|
default:
|
||||||
|
return string(azuread.CommonTenant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func azureADTenantTypeToCommand(tenantType idp_pb.AzureADTenantType) azuread.TenantType {
|
||||||
|
switch tenantType {
|
||||||
|
case idp_pb.AzureADTenantType_AZURE_AD_TENANT_TYPE_COMMON:
|
||||||
|
return azuread.CommonTenant
|
||||||
|
case idp_pb.AzureADTenantType_AZURE_AD_TENANT_TYPE_ORGANISATIONS:
|
||||||
|
return azuread.OrganizationsTenant
|
||||||
|
case idp_pb.AzureADTenantType_AZURE_AD_TENANT_TYPE_CONSUMERS:
|
||||||
|
return azuread.ConsumersTenant
|
||||||
|
default:
|
||||||
|
return azuread.CommonTenant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ProvidersToPb(providers []*query.IDPTemplate) []*idp_pb.Provider {
|
func ProvidersToPb(providers []*query.IDPTemplate) []*idp_pb.Provider {
|
||||||
list := make([]*idp_pb.Provider, len(providers))
|
list := make([]*idp_pb.Provider, len(providers))
|
||||||
for i, provider := range providers {
|
for i, provider := range providers {
|
||||||
@ -412,6 +440,10 @@ func configToPb(config *query.IDPTemplate) *idp_pb.ProviderConfig {
|
|||||||
jwtConfigToPb(providerConfig, config.JWTIDPTemplate)
|
jwtConfigToPb(providerConfig, config.JWTIDPTemplate)
|
||||||
return providerConfig
|
return providerConfig
|
||||||
}
|
}
|
||||||
|
if config.AzureADIDPTemplate != nil {
|
||||||
|
azureConfigToPb(providerConfig, config.AzureADIDPTemplate)
|
||||||
|
return providerConfig
|
||||||
|
}
|
||||||
if config.GitHubIDPTemplate != nil {
|
if config.GitHubIDPTemplate != nil {
|
||||||
githubConfigToPb(providerConfig, config.GitHubIDPTemplate)
|
githubConfigToPb(providerConfig, config.GitHubIDPTemplate)
|
||||||
return providerConfig
|
return providerConfig
|
||||||
@ -473,6 +505,32 @@ func jwtConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.JWTIDP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func azureConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.AzureADIDPTemplate) {
|
||||||
|
providerConfig.Config = &idp_pb.ProviderConfig_AzureAd{
|
||||||
|
AzureAd: &idp_pb.AzureADConfig{
|
||||||
|
ClientId: template.ClientID,
|
||||||
|
Tenant: azureTenantToPb(template.Tenant),
|
||||||
|
EmailVerified: template.IsEmailVerified,
|
||||||
|
Scopes: template.Scopes,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func azureTenantToPb(tenant string) *idp_pb.AzureADTenant {
|
||||||
|
var tenantType idp_pb.IsAzureADTenantType
|
||||||
|
switch azuread.TenantType(tenant) {
|
||||||
|
case azuread.CommonTenant:
|
||||||
|
tenantType = &idp_pb.AzureADTenant_TenantType{TenantType: idp_pb.AzureADTenantType_AZURE_AD_TENANT_TYPE_COMMON}
|
||||||
|
case azuread.OrganizationsTenant:
|
||||||
|
tenantType = &idp_pb.AzureADTenant_TenantType{TenantType: idp_pb.AzureADTenantType_AZURE_AD_TENANT_TYPE_ORGANISATIONS}
|
||||||
|
case azuread.ConsumersTenant:
|
||||||
|
tenantType = &idp_pb.AzureADTenant_TenantType{TenantType: idp_pb.AzureADTenantType_AZURE_AD_TENANT_TYPE_CONSUMERS}
|
||||||
|
default:
|
||||||
|
tenantType = &idp_pb.AzureADTenant_TenantId{TenantId: tenant}
|
||||||
|
}
|
||||||
|
return &idp_pb.AzureADTenant{Type: tenantType}
|
||||||
|
}
|
||||||
|
|
||||||
func githubConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.GitHubIDPTemplate) {
|
func githubConfigToPb(providerConfig *idp_pb.ProviderConfig, template *query.GitHubIDPTemplate) {
|
||||||
providerConfig.Config = &idp_pb.ProviderConfig_Github{
|
providerConfig.Config = &idp_pb.ProviderConfig_Github{
|
||||||
Github: &idp_pb.GitHubConfig{
|
Github: &idp_pb.GitHubConfig{
|
||||||
|
@ -233,6 +233,27 @@ func (s *Server) UpdateJWTProvider(ctx context.Context, req *mgmt_pb.UpdateJWTPr
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) AddAzureADProvider(ctx context.Context, req *mgmt_pb.AddAzureADProviderRequest) (*mgmt_pb.AddAzureADProviderResponse, error) {
|
||||||
|
id, details, err := s.command.AddOrgAzureADProvider(ctx, authz.GetCtxData(ctx).OrgID, addAzureADProviderToCommand(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.AddAzureADProviderResponse{
|
||||||
|
Id: id,
|
||||||
|
Details: object_pb.DomainToAddDetailsPb(details),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) UpdateAzureADProvider(ctx context.Context, req *mgmt_pb.UpdateAzureADProviderRequest) (*mgmt_pb.UpdateAzureADProviderResponse, error) {
|
||||||
|
details, err := s.command.UpdateOrgAzureADProvider(ctx, authz.GetCtxData(ctx).OrgID, req.Id, updateAzureADProviderToCommand(req))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mgmt_pb.UpdateAzureADProviderResponse{
|
||||||
|
Details: object_pb.DomainToChangeDetailsPb(details),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) AddGitHubProvider(ctx context.Context, req *mgmt_pb.AddGitHubProviderRequest) (*mgmt_pb.AddGitHubProviderResponse, error) {
|
func (s *Server) AddGitHubProvider(ctx context.Context, req *mgmt_pb.AddGitHubProviderRequest) (*mgmt_pb.AddGitHubProviderResponse, error) {
|
||||||
id, details, err := s.command.AddOrgGitHubProvider(ctx, authz.GetCtxData(ctx).OrgID, addGitHubProviderToCommand(req))
|
id, details, err := s.command.AddOrgGitHubProvider(ctx, authz.GetCtxData(ctx).OrgID, addGitHubProviderToCommand(req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -290,6 +290,28 @@ func updateJWTProviderToCommand(req *mgmt_pb.UpdateJWTProviderRequest) command.J
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addAzureADProviderToCommand(req *mgmt_pb.AddAzureADProviderRequest) command.AzureADProvider {
|
||||||
|
return command.AzureADProvider{
|
||||||
|
Name: req.Name,
|
||||||
|
ClientID: req.ClientId,
|
||||||
|
ClientSecret: req.ClientSecret,
|
||||||
|
Tenant: idp_grpc.AzureADTenantToCommand(req.Tenant),
|
||||||
|
EmailVerified: req.EmailVerified,
|
||||||
|
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateAzureADProviderToCommand(req *mgmt_pb.UpdateAzureADProviderRequest) command.AzureADProvider {
|
||||||
|
return command.AzureADProvider{
|
||||||
|
Name: req.Name,
|
||||||
|
ClientID: req.ClientId,
|
||||||
|
ClientSecret: req.ClientSecret,
|
||||||
|
Tenant: idp_grpc.AzureADTenantToCommand(req.Tenant),
|
||||||
|
EmailVerified: req.EmailVerified,
|
||||||
|
IDPOptions: idp_grpc.OptionsToCommand(req.ProviderOptions),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func addGitHubProviderToCommand(req *mgmt_pb.AddGitHubProviderRequest) command.GitHubProvider {
|
func addGitHubProviderToCommand(req *mgmt_pb.AddGitHubProviderRequest) command.GitHubProvider {
|
||||||
return command.GitHubProvider{
|
return command.GitHubProvider{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/zitadel/zitadel/internal/errors"
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
"github.com/zitadel/zitadel/internal/eventstore/v1/models"
|
||||||
"github.com/zitadel/zitadel/internal/idp"
|
"github.com/zitadel/zitadel/internal/idp"
|
||||||
|
"github.com/zitadel/zitadel/internal/idp/providers/azuread"
|
||||||
"github.com/zitadel/zitadel/internal/idp/providers/github"
|
"github.com/zitadel/zitadel/internal/idp/providers/github"
|
||||||
"github.com/zitadel/zitadel/internal/idp/providers/gitlab"
|
"github.com/zitadel/zitadel/internal/idp/providers/gitlab"
|
||||||
"github.com/zitadel/zitadel/internal/idp/providers/google"
|
"github.com/zitadel/zitadel/internal/idp/providers/google"
|
||||||
@ -144,6 +145,8 @@ func (l *Login) handleIDP(w http.ResponseWriter, r *http.Request, authReq *domai
|
|||||||
provider, err = l.oidcProvider(r.Context(), identityProvider)
|
provider, err = l.oidcProvider(r.Context(), identityProvider)
|
||||||
case domain.IDPTypeJWT:
|
case domain.IDPTypeJWT:
|
||||||
provider, err = l.jwtProvider(identityProvider)
|
provider, err = l.jwtProvider(identityProvider)
|
||||||
|
case domain.IDPTypeAzureAD:
|
||||||
|
provider, err = l.azureProvider(r.Context(), identityProvider)
|
||||||
case domain.IDPTypeGitHub:
|
case domain.IDPTypeGitHub:
|
||||||
provider, err = l.githubProvider(r.Context(), identityProvider)
|
provider, err = l.githubProvider(r.Context(), identityProvider)
|
||||||
case domain.IDPTypeGitHubEnterprise:
|
case domain.IDPTypeGitHubEnterprise:
|
||||||
@ -155,7 +158,6 @@ func (l *Login) handleIDP(w http.ResponseWriter, r *http.Request, authReq *domai
|
|||||||
case domain.IDPTypeGoogle:
|
case domain.IDPTypeGoogle:
|
||||||
provider, err = l.googleProvider(r.Context(), identityProvider)
|
provider, err = l.googleProvider(r.Context(), identityProvider)
|
||||||
case domain.IDPTypeLDAP,
|
case domain.IDPTypeLDAP,
|
||||||
domain.IDPTypeAzureAD,
|
|
||||||
domain.IDPTypeUnspecified:
|
domain.IDPTypeUnspecified:
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
@ -212,6 +214,13 @@ func (l *Login) handleExternalLoginCallback(w http.ResponseWriter, r *http.Reque
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
session = &openid.Session{Provider: provider.(*openid.Provider), Code: data.Code}
|
session = &openid.Session{Provider: provider.(*openid.Provider), Code: data.Code}
|
||||||
|
case domain.IDPTypeAzureAD:
|
||||||
|
provider, err = l.azureProvider(r.Context(), identityProvider)
|
||||||
|
if err != nil {
|
||||||
|
l.externalAuthFailed(w, r, authReq, nil, nil, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
session = &oauth.Session{Provider: provider.(*azuread.Provider).Provider, Code: data.Code}
|
||||||
case domain.IDPTypeGitHub:
|
case domain.IDPTypeGitHub:
|
||||||
provider, err = l.githubProvider(r.Context(), identityProvider)
|
provider, err = l.githubProvider(r.Context(), identityProvider)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -249,7 +258,6 @@ func (l *Login) handleExternalLoginCallback(w http.ResponseWriter, r *http.Reque
|
|||||||
session = &openid.Session{Provider: provider.(*google.Provider).Provider, Code: data.Code}
|
session = &openid.Session{Provider: provider.(*google.Provider).Provider, Code: data.Code}
|
||||||
case domain.IDPTypeJWT,
|
case domain.IDPTypeJWT,
|
||||||
domain.IDPTypeLDAP,
|
domain.IDPTypeLDAP,
|
||||||
domain.IDPTypeAzureAD,
|
|
||||||
domain.IDPTypeUnspecified:
|
domain.IDPTypeUnspecified:
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
@ -666,6 +674,28 @@ func (l *Login) oauthProvider(ctx context.Context, identityProvider *query.IDPTe
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Login) azureProvider(ctx context.Context, identityProvider *query.IDPTemplate) (*azuread.Provider, error) {
|
||||||
|
secret, err := crypto.DecryptString(identityProvider.AzureADIDPTemplate.ClientSecret, l.idpConfigAlg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
opts := make([]azuread.ProviderOptions, 0, 2)
|
||||||
|
if identityProvider.AzureADIDPTemplate.IsEmailVerified {
|
||||||
|
opts = append(opts, azuread.WithEmailVerified())
|
||||||
|
}
|
||||||
|
if identityProvider.AzureADIDPTemplate.Tenant != "" {
|
||||||
|
opts = append(opts, azuread.WithTenant(azuread.TenantType(identityProvider.AzureADIDPTemplate.Tenant)))
|
||||||
|
}
|
||||||
|
return azuread.New(
|
||||||
|
identityProvider.Name,
|
||||||
|
identityProvider.AzureADIDPTemplate.ClientID,
|
||||||
|
secret,
|
||||||
|
l.baseURL(ctx)+EndpointExternalLoginCallback,
|
||||||
|
identityProvider.AzureADIDPTemplate.Scopes,
|
||||||
|
opts...,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func (l *Login) githubProvider(ctx context.Context, identityProvider *query.IDPTemplate) (*github.Provider, error) {
|
func (l *Login) githubProvider(ctx context.Context, identityProvider *query.IDPTemplate) (*github.Provider, error) {
|
||||||
secret, err := crypto.DecryptString(identityProvider.GitHubIDPTemplate.ClientSecret, l.idpConfigAlg)
|
secret, err := crypto.DecryptString(identityProvider.GitHubIDPTemplate.ClientSecret, l.idpConfigAlg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -38,6 +38,16 @@ type JWTProvider struct {
|
|||||||
IDPOptions idp.Options
|
IDPOptions idp.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AzureADProvider struct {
|
||||||
|
Name string
|
||||||
|
ClientID string
|
||||||
|
ClientSecret string
|
||||||
|
Scopes []string
|
||||||
|
Tenant string
|
||||||
|
EmailVerified bool
|
||||||
|
IDPOptions idp.Options
|
||||||
|
}
|
||||||
|
|
||||||
type GitHubProvider struct {
|
type GitHubProvider struct {
|
||||||
Name string
|
Name string
|
||||||
ClientID string
|
ClientID string
|
||||||
|
@ -413,6 +413,111 @@ func (wm *JWTIDPWriteModel) reduceJWTConfigChangedEvent(e *idpconfig.JWTConfigCh
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AzureADIDPWriteModel struct {
|
||||||
|
eventstore.WriteModel
|
||||||
|
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
ClientID string
|
||||||
|
ClientSecret *crypto.CryptoValue
|
||||||
|
Scopes []string
|
||||||
|
Tenant string
|
||||||
|
IsEmailVerified bool
|
||||||
|
idp.Options
|
||||||
|
|
||||||
|
State domain.IDPState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *AzureADIDPWriteModel) Reduce() error {
|
||||||
|
for _, event := range wm.Events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *idp.AzureADIDPAddedEvent:
|
||||||
|
wm.reduceAddedEvent(e)
|
||||||
|
case *idp.AzureADIDPChangedEvent:
|
||||||
|
wm.reduceChangedEvent(e)
|
||||||
|
case *idp.RemovedEvent:
|
||||||
|
wm.State = domain.IDPStateRemoved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wm.WriteModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *AzureADIDPWriteModel) reduceAddedEvent(e *idp.AzureADIDPAddedEvent) {
|
||||||
|
wm.Name = e.Name
|
||||||
|
wm.ClientID = e.ClientID
|
||||||
|
wm.ClientSecret = e.ClientSecret
|
||||||
|
wm.Scopes = e.Scopes
|
||||||
|
wm.Tenant = e.Tenant
|
||||||
|
wm.IsEmailVerified = e.IsEmailVerified
|
||||||
|
wm.Options = e.Options
|
||||||
|
wm.State = domain.IDPStateActive
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *AzureADIDPWriteModel) reduceChangedEvent(e *idp.AzureADIDPChangedEvent) {
|
||||||
|
if e.ClientID != nil {
|
||||||
|
wm.ClientID = *e.ClientID
|
||||||
|
}
|
||||||
|
if e.ClientSecret != nil {
|
||||||
|
wm.ClientSecret = e.ClientSecret
|
||||||
|
}
|
||||||
|
if e.Name != nil {
|
||||||
|
wm.Name = *e.Name
|
||||||
|
}
|
||||||
|
if e.Scopes != nil {
|
||||||
|
wm.Scopes = e.Scopes
|
||||||
|
}
|
||||||
|
if e.Tenant != nil {
|
||||||
|
wm.Tenant = *e.Tenant
|
||||||
|
}
|
||||||
|
if e.IsEmailVerified != nil {
|
||||||
|
wm.IsEmailVerified = *e.IsEmailVerified
|
||||||
|
}
|
||||||
|
wm.Options.ReduceChanges(e.OptionChanges)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *AzureADIDPWriteModel) NewChanges(
|
||||||
|
name string,
|
||||||
|
clientID string,
|
||||||
|
clientSecretString string,
|
||||||
|
secretCrypto crypto.Crypto,
|
||||||
|
scopes []string,
|
||||||
|
tenant string,
|
||||||
|
isEmailVerified bool,
|
||||||
|
options idp.Options,
|
||||||
|
) ([]idp.AzureADIDPChanges, error) {
|
||||||
|
changes := make([]idp.AzureADIDPChanges, 0)
|
||||||
|
var clientSecret *crypto.CryptoValue
|
||||||
|
var err error
|
||||||
|
if clientSecretString != "" {
|
||||||
|
clientSecret, err = crypto.Crypt([]byte(clientSecretString), secretCrypto)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
changes = append(changes, idp.ChangeAzureADClientSecret(clientSecret))
|
||||||
|
}
|
||||||
|
if wm.Name != name {
|
||||||
|
changes = append(changes, idp.ChangeAzureADName(name))
|
||||||
|
}
|
||||||
|
if wm.ClientID != clientID {
|
||||||
|
changes = append(changes, idp.ChangeAzureADClientID(clientID))
|
||||||
|
}
|
||||||
|
if wm.Tenant != tenant {
|
||||||
|
changes = append(changes, idp.ChangeAzureADTenant(tenant))
|
||||||
|
}
|
||||||
|
if wm.IsEmailVerified != isEmailVerified {
|
||||||
|
changes = append(changes, idp.ChangeAzureADIsEmailVerified(isEmailVerified))
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(wm.Scopes, scopes) {
|
||||||
|
changes = append(changes, idp.ChangeAzureADScopes(scopes))
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := wm.Options.Changes(options)
|
||||||
|
if !opts.IsZero() {
|
||||||
|
changes = append(changes, idp.ChangeAzureADOptions(opts))
|
||||||
|
}
|
||||||
|
return changes, nil
|
||||||
|
}
|
||||||
|
|
||||||
type GitHubIDPWriteModel struct {
|
type GitHubIDPWriteModel struct {
|
||||||
eventstore.WriteModel
|
eventstore.WriteModel
|
||||||
|
|
||||||
@ -1049,6 +1154,8 @@ func (wm *IDPRemoveWriteModel) Reduce() error {
|
|||||||
wm.reduceAdded(e.ID)
|
wm.reduceAdded(e.ID)
|
||||||
case *idp.JWTIDPAddedEvent:
|
case *idp.JWTIDPAddedEvent:
|
||||||
wm.reduceAdded(e.ID)
|
wm.reduceAdded(e.ID)
|
||||||
|
case *idp.AzureADIDPAddedEvent:
|
||||||
|
wm.reduceAdded(e.ID)
|
||||||
case *idp.GitHubIDPAddedEvent:
|
case *idp.GitHubIDPAddedEvent:
|
||||||
wm.reduceAdded(e.ID)
|
wm.reduceAdded(e.ID)
|
||||||
case *idp.GitHubEnterpriseIDPAddedEvent:
|
case *idp.GitHubEnterpriseIDPAddedEvent:
|
||||||
|
@ -139,6 +139,48 @@ func (c *Commands) UpdateInstanceJWTProvider(ctx context.Context, id string, pro
|
|||||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) AddInstanceAzureADProvider(ctx context.Context, provider AzureADProvider) (string, *domain.ObjectDetails, error) {
|
||||||
|
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||||
|
instanceAgg := instance.NewAggregate(instanceID)
|
||||||
|
id, err := c.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
writeModel := NewAzureADInstanceIDPWriteModel(instanceID, id)
|
||||||
|
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddInstanceAzureADProvider(instanceAgg, writeModel, provider))
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
return id, pushedEventsToObjectDetails(pushedEvents), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) UpdateInstanceAzureADProvider(ctx context.Context, id string, provider AzureADProvider) (*domain.ObjectDetails, error) {
|
||||||
|
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||||
|
instanceAgg := instance.NewAggregate(instanceID)
|
||||||
|
writeModel := NewAzureADInstanceIDPWriteModel(instanceID, id)
|
||||||
|
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateInstanceAzureADProvider(instanceAgg, writeModel, provider))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(cmds) == 0 {
|
||||||
|
// no change, so return directly
|
||||||
|
return &domain.ObjectDetails{
|
||||||
|
Sequence: writeModel.ProcessedSequence,
|
||||||
|
EventDate: writeModel.ChangeDate,
|
||||||
|
ResourceOwner: writeModel.ResourceOwner,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) AddInstanceGitHubProvider(ctx context.Context, provider GitHubProvider) (string, *domain.ObjectDetails, error) {
|
func (c *Commands) AddInstanceGitHubProvider(ctx context.Context, provider GitHubProvider) (string, *domain.ObjectDetails, error) {
|
||||||
instanceID := authz.GetInstance(ctx).InstanceID()
|
instanceID := authz.GetInstance(ctx).InstanceID()
|
||||||
instanceAgg := instance.NewAggregate(instanceID)
|
instanceAgg := instance.NewAggregate(instanceID)
|
||||||
@ -719,6 +761,92 @@ func (c *Commands) prepareUpdateInstanceJWTProvider(a *instance.Aggregate, write
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) prepareAddInstanceAzureADProvider(a *instance.Aggregate, writeModel *InstanceAzureADIDPWriteModel, provider AzureADProvider) preparation.Validation {
|
||||||
|
return func() (preparation.CreateCommands, error) {
|
||||||
|
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-sdf3g", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Fhbr2", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
if provider.ClientSecret = strings.TrimSpace(provider.ClientSecret); provider.ClientSecret == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-Dzh3g", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||||
|
events, err := filter(ctx, writeModel.Query())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
writeModel.AppendEvents(events...)
|
||||||
|
if err = writeModel.Reduce(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
secret, err := crypto.Encrypt([]byte(provider.ClientSecret), c.idpConfigEncryption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return []eventstore.Command{
|
||||||
|
instance.NewAzureADIDPAddedEvent(
|
||||||
|
ctx,
|
||||||
|
&a.Aggregate,
|
||||||
|
writeModel.ID,
|
||||||
|
provider.Name,
|
||||||
|
provider.ClientID,
|
||||||
|
secret,
|
||||||
|
provider.Scopes,
|
||||||
|
provider.Tenant,
|
||||||
|
provider.EmailVerified,
|
||||||
|
provider.IDPOptions,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) prepareUpdateInstanceAzureADProvider(a *instance.Aggregate, writeModel *InstanceAzureADIDPWriteModel, provider AzureADProvider) preparation.Validation {
|
||||||
|
return func() (preparation.CreateCommands, error) {
|
||||||
|
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-SAgh2", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-fh3h1", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "INST-dmitg", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||||
|
events, err := filter(ctx, writeModel.Query())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
writeModel.AppendEvents(events...)
|
||||||
|
if err = writeModel.Reduce(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !writeModel.State.Exists() {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "INST-BHz3q", "Errors.Instance.IDPConfig.NotExisting")
|
||||||
|
}
|
||||||
|
event, err := writeModel.NewChangedEvent(
|
||||||
|
ctx,
|
||||||
|
&a.Aggregate,
|
||||||
|
writeModel.ID,
|
||||||
|
provider.Name,
|
||||||
|
provider.ClientID,
|
||||||
|
provider.ClientSecret,
|
||||||
|
c.idpConfigEncryption,
|
||||||
|
provider.Scopes,
|
||||||
|
provider.Tenant,
|
||||||
|
provider.EmailVerified,
|
||||||
|
provider.IDPOptions,
|
||||||
|
)
|
||||||
|
if err != nil || event == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return []eventstore.Command{event}, nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) prepareAddInstanceGitHubProvider(a *instance.Aggregate, writeModel *InstanceGitHubIDPWriteModel, provider GitHubProvider) preparation.Validation {
|
func (c *Commands) prepareAddInstanceGitHubProvider(a *instance.Aggregate, writeModel *InstanceGitHubIDPWriteModel, provider GitHubProvider) preparation.Validation {
|
||||||
return func() (preparation.CreateCommands, error) {
|
return func() (preparation.CreateCommands, error) {
|
||||||
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||||
|
@ -279,6 +279,82 @@ func (wm *InstanceJWTIDPWriteModel) NewChangedEvent(
|
|||||||
return instance.NewJWTIDPChangedEvent(ctx, aggregate, id, changes)
|
return instance.NewJWTIDPChangedEvent(ctx, aggregate, id, changes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InstanceAzureADIDPWriteModel struct {
|
||||||
|
AzureADIDPWriteModel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAzureADInstanceIDPWriteModel(instanceID, id string) *InstanceAzureADIDPWriteModel {
|
||||||
|
return &InstanceAzureADIDPWriteModel{
|
||||||
|
AzureADIDPWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: instanceID,
|
||||||
|
ResourceOwner: instanceID,
|
||||||
|
},
|
||||||
|
ID: id,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *InstanceAzureADIDPWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *instance.AzureADIDPAddedEvent:
|
||||||
|
wm.AzureADIDPWriteModel.AppendEvents(&e.AzureADIDPAddedEvent)
|
||||||
|
case *instance.AzureADIDPChangedEvent:
|
||||||
|
wm.AzureADIDPWriteModel.AppendEvents(&e.AzureADIDPChangedEvent)
|
||||||
|
case *instance.IDPRemovedEvent:
|
||||||
|
wm.AzureADIDPWriteModel.AppendEvents(&e.RemovedEvent)
|
||||||
|
default:
|
||||||
|
wm.AzureADIDPWriteModel.AppendEvents(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *InstanceAzureADIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||||
|
ResourceOwner(wm.ResourceOwner).
|
||||||
|
AddQuery().
|
||||||
|
AggregateTypes(instance.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID).
|
||||||
|
EventTypes(
|
||||||
|
instance.AzureADIDPAddedEventType,
|
||||||
|
instance.AzureADIDPChangedEventType,
|
||||||
|
instance.IDPRemovedEventType,
|
||||||
|
).
|
||||||
|
EventData(map[string]interface{}{"id": wm.ID}).
|
||||||
|
Builder()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *InstanceAzureADIDPWriteModel) NewChangedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
clientID,
|
||||||
|
clientSecretString string,
|
||||||
|
secretCrypto crypto.Crypto,
|
||||||
|
scopes []string,
|
||||||
|
tenant string,
|
||||||
|
isEmailVerified bool,
|
||||||
|
options idp.Options,
|
||||||
|
) (*instance.AzureADIDPChangedEvent, error) {
|
||||||
|
|
||||||
|
changes, err := wm.AzureADIDPWriteModel.NewChanges(
|
||||||
|
name,
|
||||||
|
clientID,
|
||||||
|
clientSecretString,
|
||||||
|
secretCrypto,
|
||||||
|
scopes,
|
||||||
|
tenant,
|
||||||
|
isEmailVerified,
|
||||||
|
options,
|
||||||
|
)
|
||||||
|
if err != nil || len(changes) == 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return instance.NewAzureADIDPChangedEvent(ctx, aggregate, id, changes)
|
||||||
|
}
|
||||||
|
|
||||||
type InstanceGitHubIDPWriteModel struct {
|
type InstanceGitHubIDPWriteModel struct {
|
||||||
GitHubIDPWriteModel
|
GitHubIDPWriteModel
|
||||||
}
|
}
|
||||||
@ -726,6 +802,8 @@ func (wm *InstanceIDPRemoveWriteModel) AppendEvents(events ...eventstore.Event)
|
|||||||
wm.IDPRemoveWriteModel.AppendEvents(&e.OIDCIDPAddedEvent)
|
wm.IDPRemoveWriteModel.AppendEvents(&e.OIDCIDPAddedEvent)
|
||||||
case *instance.JWTIDPAddedEvent:
|
case *instance.JWTIDPAddedEvent:
|
||||||
wm.IDPRemoveWriteModel.AppendEvents(&e.JWTIDPAddedEvent)
|
wm.IDPRemoveWriteModel.AppendEvents(&e.JWTIDPAddedEvent)
|
||||||
|
case *instance.AzureADIDPAddedEvent:
|
||||||
|
wm.IDPRemoveWriteModel.AppendEvents(&e.AzureADIDPAddedEvent)
|
||||||
case *instance.GitHubIDPAddedEvent:
|
case *instance.GitHubIDPAddedEvent:
|
||||||
wm.IDPRemoveWriteModel.AppendEvents(&e.GitHubIDPAddedEvent)
|
wm.IDPRemoveWriteModel.AppendEvents(&e.GitHubIDPAddedEvent)
|
||||||
case *instance.GitHubEnterpriseIDPAddedEvent:
|
case *instance.GitHubEnterpriseIDPAddedEvent:
|
||||||
@ -760,6 +838,7 @@ func (wm *InstanceIDPRemoveWriteModel) Query() *eventstore.SearchQueryBuilder {
|
|||||||
instance.OAuthIDPAddedEventType,
|
instance.OAuthIDPAddedEventType,
|
||||||
instance.OIDCIDPAddedEventType,
|
instance.OIDCIDPAddedEventType,
|
||||||
instance.JWTIDPAddedEventType,
|
instance.JWTIDPAddedEventType,
|
||||||
|
instance.AzureADIDPAddedEventType,
|
||||||
instance.GitHubIDPAddedEventType,
|
instance.GitHubIDPAddedEventType,
|
||||||
instance.GitHubEnterpriseIDPAddedEventType,
|
instance.GitHubEnterpriseIDPAddedEventType,
|
||||||
instance.GitLabIDPAddedEventType,
|
instance.GitLabIDPAddedEventType,
|
||||||
|
@ -637,6 +637,428 @@ func TestCommandSide_UpdateInstanceGenericOAuthIDP(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommandSide_AddInstanceAzureADIDP(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
eventstore *eventstore.Eventstore
|
||||||
|
idGenerator id.Generator
|
||||||
|
secretCrypto crypto.EncryptionAlgorithm
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
provider AzureADProvider
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
id string
|
||||||
|
want *domain.ObjectDetails
|
||||||
|
err func(error) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid name",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
provider: AzureADProvider{},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-sdf3g", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid client id",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Fhbr2", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid client secret",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-Dzh3g", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusherWithInstanceID(
|
||||||
|
"instance1",
|
||||||
|
instance.NewAzureADIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
"name",
|
||||||
|
"clientID",
|
||||||
|
&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("clientSecret"),
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
idp.Options{},
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
ClientSecret: "clientSecret",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
id: "id1",
|
||||||
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok all set",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusherWithInstanceID(
|
||||||
|
"instance1",
|
||||||
|
instance.NewAzureADIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
"name",
|
||||||
|
"clientID",
|
||||||
|
&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("clientSecret"),
|
||||||
|
},
|
||||||
|
[]string{"openid"},
|
||||||
|
"tenant",
|
||||||
|
true,
|
||||||
|
idp.Options{
|
||||||
|
IsCreationAllowed: true,
|
||||||
|
IsLinkingAllowed: true,
|
||||||
|
IsAutoCreation: true,
|
||||||
|
IsAutoUpdate: true,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
ClientSecret: "clientSecret",
|
||||||
|
Scopes: []string{"openid"},
|
||||||
|
Tenant: "tenant",
|
||||||
|
EmailVerified: true,
|
||||||
|
IDPOptions: idp.Options{
|
||||||
|
IsCreationAllowed: true,
|
||||||
|
IsLinkingAllowed: true,
|
||||||
|
IsAutoCreation: true,
|
||||||
|
IsAutoUpdate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
id: "id1",
|
||||||
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
c := &Commands{
|
||||||
|
eventstore: tt.fields.eventstore,
|
||||||
|
idGenerator: tt.fields.idGenerator,
|
||||||
|
idpConfigEncryption: tt.fields.secretCrypto,
|
||||||
|
}
|
||||||
|
id, got, err := c.AddInstanceAzureADProvider(tt.args.ctx, tt.args.provider)
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
if tt.res.err != nil && !tt.res.err(err) {
|
||||||
|
t.Errorf("got wrong err: %v ", err)
|
||||||
|
}
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.Equal(t, tt.res.id, id)
|
||||||
|
assert.Equal(t, tt.res.want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCommandSide_UpdateInstanceAzureADIDP(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
eventstore *eventstore.Eventstore
|
||||||
|
secretCrypto crypto.EncryptionAlgorithm
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
id string
|
||||||
|
provider AzureADProvider
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
want *domain.ObjectDetails
|
||||||
|
err func(error) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid id",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
provider: AzureADProvider{},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-SAgh2", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid name",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-fh3h1", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid client id",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "INST-dmitg", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not found",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
err: caos_errors.IsNotFound,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no changes",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
instance.NewAzureADIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
"name",
|
||||||
|
"clientID",
|
||||||
|
&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("clientSecret"),
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
idp.Options{},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "change ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
instance.NewAzureADIDPAddedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
"name",
|
||||||
|
"clientID",
|
||||||
|
&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("clientSecret"),
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
idp.Options{},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
[]*repository.Event{
|
||||||
|
eventFromEventPusherWithInstanceID(
|
||||||
|
"instance1",
|
||||||
|
func() eventstore.Command {
|
||||||
|
t := true
|
||||||
|
event, _ := instance.NewAzureADIDPChangedEvent(context.Background(), &instance.NewAggregate("instance1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
[]idp.AzureADIDPChanges{
|
||||||
|
idp.ChangeAzureADName("new name"),
|
||||||
|
idp.ChangeAzureADClientID("new clientID"),
|
||||||
|
idp.ChangeAzureADClientSecret(&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("new clientSecret"),
|
||||||
|
}),
|
||||||
|
idp.ChangeAzureADScopes([]string{"openid", "profile"}),
|
||||||
|
idp.ChangeAzureADTenant("new tenant"),
|
||||||
|
idp.ChangeAzureADIsEmailVerified(true),
|
||||||
|
idp.ChangeAzureADOptions(idp.OptionChanges{
|
||||||
|
IsCreationAllowed: &t,
|
||||||
|
IsLinkingAllowed: &t,
|
||||||
|
IsAutoCreation: &t,
|
||||||
|
IsAutoUpdate: &t,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return event
|
||||||
|
}(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: authz.WithInstanceID(context.Background(), "instance1"),
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "new name",
|
||||||
|
ClientID: "new clientID",
|
||||||
|
ClientSecret: "new clientSecret",
|
||||||
|
Scopes: []string{"openid", "profile"},
|
||||||
|
Tenant: "new tenant",
|
||||||
|
EmailVerified: true,
|
||||||
|
IDPOptions: idp.Options{
|
||||||
|
IsCreationAllowed: true,
|
||||||
|
IsLinkingAllowed: true,
|
||||||
|
IsAutoCreation: true,
|
||||||
|
IsAutoUpdate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{ResourceOwner: "instance1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
c := &Commands{
|
||||||
|
eventstore: tt.fields.eventstore,
|
||||||
|
idpConfigEncryption: tt.fields.secretCrypto,
|
||||||
|
}
|
||||||
|
got, err := c.UpdateInstanceAzureADProvider(tt.args.ctx, tt.args.id, tt.args.provider)
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
if tt.res.err != nil && !tt.res.err(err) {
|
||||||
|
t.Errorf("got wrong err: %v ", err)
|
||||||
|
}
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.Equal(t, tt.res.want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCommandSide_AddInstanceGitHubIDP(t *testing.T) {
|
func TestCommandSide_AddInstanceGitHubIDP(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
eventstore *eventstore.Eventstore
|
eventstore *eventstore.Eventstore
|
||||||
|
@ -131,6 +131,45 @@ func (c *Commands) UpdateOrgJWTProvider(ctx context.Context, resourceOwner, id s
|
|||||||
}
|
}
|
||||||
return pushedEventsToObjectDetails(pushedEvents), nil
|
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||||
}
|
}
|
||||||
|
func (c *Commands) AddOrgAzureADProvider(ctx context.Context, resourceOwner string, provider AzureADProvider) (string, *domain.ObjectDetails, error) {
|
||||||
|
orgAgg := org.NewAggregate(resourceOwner)
|
||||||
|
id, err := c.idGenerator.Next()
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
writeModel := NewAzureADOrgIDPWriteModel(resourceOwner, id)
|
||||||
|
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareAddOrgAzureADProvider(orgAgg, writeModel, provider))
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
return id, pushedEventsToObjectDetails(pushedEvents), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) UpdateOrgAzureADProvider(ctx context.Context, resourceOwner, id string, provider AzureADProvider) (*domain.ObjectDetails, error) {
|
||||||
|
orgAgg := org.NewAggregate(resourceOwner)
|
||||||
|
writeModel := NewAzureADOrgIDPWriteModel(resourceOwner, id)
|
||||||
|
cmds, err := preparation.PrepareCommands(ctx, c.eventstore.Filter, c.prepareUpdateOrgAzureADProvider(orgAgg, writeModel, provider))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(cmds) == 0 {
|
||||||
|
// no change, so return directly
|
||||||
|
return &domain.ObjectDetails{
|
||||||
|
Sequence: writeModel.ProcessedSequence,
|
||||||
|
EventDate: writeModel.ChangeDate,
|
||||||
|
ResourceOwner: writeModel.ResourceOwner,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
pushedEvents, err := c.eventstore.Push(ctx, cmds...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return pushedEventsToObjectDetails(pushedEvents), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) AddOrgGitHubProvider(ctx context.Context, resourceOwner string, provider GitHubProvider) (string, *domain.ObjectDetails, error) {
|
func (c *Commands) AddOrgGitHubProvider(ctx context.Context, resourceOwner string, provider GitHubProvider) (string, *domain.ObjectDetails, error) {
|
||||||
orgAgg := org.NewAggregate(resourceOwner)
|
orgAgg := org.NewAggregate(resourceOwner)
|
||||||
@ -700,6 +739,92 @@ func (c *Commands) prepareUpdateOrgJWTProvider(a *org.Aggregate, writeModel *Org
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Commands) prepareAddOrgAzureADProvider(a *org.Aggregate, writeModel *OrgAzureADIDPWriteModel, provider AzureADProvider) preparation.Validation {
|
||||||
|
return func() (preparation.CreateCommands, error) {
|
||||||
|
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-sdf3g", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-Fhbr2", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
if provider.ClientSecret = strings.TrimSpace(provider.ClientSecret); provider.ClientSecret == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-Dzh3g", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||||
|
events, err := filter(ctx, writeModel.Query())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
writeModel.AppendEvents(events...)
|
||||||
|
if err = writeModel.Reduce(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
secret, err := crypto.Encrypt([]byte(provider.ClientSecret), c.idpConfigEncryption)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return []eventstore.Command{
|
||||||
|
org.NewAzureADIDPAddedEvent(
|
||||||
|
ctx,
|
||||||
|
&a.Aggregate,
|
||||||
|
writeModel.ID,
|
||||||
|
provider.Name,
|
||||||
|
provider.ClientID,
|
||||||
|
secret,
|
||||||
|
provider.Scopes,
|
||||||
|
provider.Tenant,
|
||||||
|
provider.EmailVerified,
|
||||||
|
provider.IDPOptions,
|
||||||
|
),
|
||||||
|
}, nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commands) prepareUpdateOrgAzureADProvider(a *org.Aggregate, writeModel *OrgAzureADIDPWriteModel, provider AzureADProvider) preparation.Validation {
|
||||||
|
return func() (preparation.CreateCommands, error) {
|
||||||
|
if writeModel.ID = strings.TrimSpace(writeModel.ID); writeModel.ID == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-SAgh2", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
if provider.Name = strings.TrimSpace(provider.Name); provider.Name == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-fh3h1", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||||
|
return nil, caos_errs.ThrowInvalidArgument(nil, "ORG-dmitg", "Errors.Invalid.Argument")
|
||||||
|
}
|
||||||
|
return func(ctx context.Context, filter preparation.FilterToQueryReducer) ([]eventstore.Command, error) {
|
||||||
|
events, err := filter(ctx, writeModel.Query())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
writeModel.AppendEvents(events...)
|
||||||
|
if err = writeModel.Reduce(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !writeModel.State.Exists() {
|
||||||
|
return nil, caos_errs.ThrowNotFound(nil, "ORG-BHz3q", "Errors.Org.IDPConfig.NotExisting")
|
||||||
|
}
|
||||||
|
event, err := writeModel.NewChangedEvent(
|
||||||
|
ctx,
|
||||||
|
&a.Aggregate,
|
||||||
|
writeModel.ID,
|
||||||
|
provider.Name,
|
||||||
|
provider.ClientID,
|
||||||
|
provider.ClientSecret,
|
||||||
|
c.idpConfigEncryption,
|
||||||
|
provider.Scopes,
|
||||||
|
provider.Tenant,
|
||||||
|
provider.EmailVerified,
|
||||||
|
provider.IDPOptions,
|
||||||
|
)
|
||||||
|
if err != nil || event == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return []eventstore.Command{event}, nil
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Commands) prepareAddOrgGitHubProvider(a *org.Aggregate, writeModel *OrgGitHubIDPWriteModel, provider GitHubProvider) preparation.Validation {
|
func (c *Commands) prepareAddOrgGitHubProvider(a *org.Aggregate, writeModel *OrgGitHubIDPWriteModel, provider GitHubProvider) preparation.Validation {
|
||||||
return func() (preparation.CreateCommands, error) {
|
return func() (preparation.CreateCommands, error) {
|
||||||
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
if provider.ClientID = strings.TrimSpace(provider.ClientID); provider.ClientID == "" {
|
||||||
|
@ -281,6 +281,86 @@ func (wm *OrgJWTIDPWriteModel) NewChangedEvent(
|
|||||||
return org.NewJWTIDPChangedEvent(ctx, aggregate, id, changes)
|
return org.NewJWTIDPChangedEvent(ctx, aggregate, id, changes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OrgAzureADIDPWriteModel struct {
|
||||||
|
AzureADIDPWriteModel
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAzureADOrgIDPWriteModel(orgID, id string) *OrgAzureADIDPWriteModel {
|
||||||
|
return &OrgAzureADIDPWriteModel{
|
||||||
|
AzureADIDPWriteModel{
|
||||||
|
WriteModel: eventstore.WriteModel{
|
||||||
|
AggregateID: orgID,
|
||||||
|
ResourceOwner: orgID,
|
||||||
|
},
|
||||||
|
ID: id,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgAzureADIDPWriteModel) Reduce() error {
|
||||||
|
return wm.AzureADIDPWriteModel.Reduce()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgAzureADIDPWriteModel) AppendEvents(events ...eventstore.Event) {
|
||||||
|
for _, event := range events {
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.AzureADIDPAddedEvent:
|
||||||
|
wm.AzureADIDPWriteModel.AppendEvents(&e.AzureADIDPAddedEvent)
|
||||||
|
case *org.AzureADIDPChangedEvent:
|
||||||
|
wm.AzureADIDPWriteModel.AppendEvents(&e.AzureADIDPChangedEvent)
|
||||||
|
case *org.IDPRemovedEvent:
|
||||||
|
wm.AzureADIDPWriteModel.AppendEvents(&e.RemovedEvent)
|
||||||
|
default:
|
||||||
|
wm.AzureADIDPWriteModel.AppendEvents(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgAzureADIDPWriteModel) Query() *eventstore.SearchQueryBuilder {
|
||||||
|
return eventstore.NewSearchQueryBuilder(eventstore.ColumnsEvent).
|
||||||
|
ResourceOwner(wm.ResourceOwner).
|
||||||
|
AddQuery().
|
||||||
|
AggregateTypes(org.AggregateType).
|
||||||
|
AggregateIDs(wm.AggregateID).
|
||||||
|
EventTypes(
|
||||||
|
org.AzureADIDPAddedEventType,
|
||||||
|
org.AzureADIDPChangedEventType,
|
||||||
|
org.IDPRemovedEventType,
|
||||||
|
).
|
||||||
|
EventData(map[string]interface{}{"id": wm.ID}).
|
||||||
|
Builder()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *OrgAzureADIDPWriteModel) NewChangedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
clientID,
|
||||||
|
clientSecretString string,
|
||||||
|
secretCrypto crypto.Crypto,
|
||||||
|
scopes []string,
|
||||||
|
tenant string,
|
||||||
|
isEmailVerified bool,
|
||||||
|
options idp.Options,
|
||||||
|
) (*org.AzureADIDPChangedEvent, error) {
|
||||||
|
|
||||||
|
changes, err := wm.AzureADIDPWriteModel.NewChanges(
|
||||||
|
name,
|
||||||
|
clientID,
|
||||||
|
clientSecretString,
|
||||||
|
secretCrypto,
|
||||||
|
scopes,
|
||||||
|
tenant,
|
||||||
|
isEmailVerified,
|
||||||
|
options,
|
||||||
|
)
|
||||||
|
if err != nil || len(changes) == 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return org.NewAzureADIDPChangedEvent(ctx, aggregate, id, changes)
|
||||||
|
}
|
||||||
|
|
||||||
type OrgGitHubIDPWriteModel struct {
|
type OrgGitHubIDPWriteModel struct {
|
||||||
GitHubIDPWriteModel
|
GitHubIDPWriteModel
|
||||||
}
|
}
|
||||||
@ -732,6 +812,8 @@ func (wm *OrgIDPRemoveWriteModel) AppendEvents(events ...eventstore.Event) {
|
|||||||
wm.IDPRemoveWriteModel.AppendEvents(&e.OIDCIDPAddedEvent)
|
wm.IDPRemoveWriteModel.AppendEvents(&e.OIDCIDPAddedEvent)
|
||||||
case *org.JWTIDPAddedEvent:
|
case *org.JWTIDPAddedEvent:
|
||||||
wm.IDPRemoveWriteModel.AppendEvents(&e.JWTIDPAddedEvent)
|
wm.IDPRemoveWriteModel.AppendEvents(&e.JWTIDPAddedEvent)
|
||||||
|
case *org.AzureADIDPAddedEvent:
|
||||||
|
wm.IDPRemoveWriteModel.AppendEvents(&e.AzureADIDPAddedEvent)
|
||||||
case *org.GitHubIDPAddedEvent:
|
case *org.GitHubIDPAddedEvent:
|
||||||
wm.IDPRemoveWriteModel.AppendEvents(&e.GitHubIDPAddedEvent)
|
wm.IDPRemoveWriteModel.AppendEvents(&e.GitHubIDPAddedEvent)
|
||||||
case *org.GitHubEnterpriseIDPAddedEvent:
|
case *org.GitHubEnterpriseIDPAddedEvent:
|
||||||
@ -766,6 +848,7 @@ func (wm *OrgIDPRemoveWriteModel) Query() *eventstore.SearchQueryBuilder {
|
|||||||
org.OAuthIDPAddedEventType,
|
org.OAuthIDPAddedEventType,
|
||||||
org.OIDCIDPAddedEventType,
|
org.OIDCIDPAddedEventType,
|
||||||
org.JWTIDPAddedEventType,
|
org.JWTIDPAddedEventType,
|
||||||
|
org.AzureADIDPAddedEventType,
|
||||||
org.GitHubIDPAddedEventType,
|
org.GitHubIDPAddedEventType,
|
||||||
org.GitHubEnterpriseIDPAddedEventType,
|
org.GitHubEnterpriseIDPAddedEventType,
|
||||||
org.GitLabIDPAddedEventType,
|
org.GitLabIDPAddedEventType,
|
||||||
|
@ -648,6 +648,432 @@ func TestCommandSide_UpdateOrgGenericOAuthIDP(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommandSide_AddOrgAzureADIDP(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
eventstore *eventstore.Eventstore
|
||||||
|
idGenerator id.Generator
|
||||||
|
secretCrypto crypto.EncryptionAlgorithm
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
resourceOwner string
|
||||||
|
provider AzureADProvider
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
id string
|
||||||
|
want *domain.ObjectDetails
|
||||||
|
err func(error) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid name",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
provider: AzureADProvider{},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-sdf3g", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid client id",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Fhbr2", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid client secret",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-Dzh3g", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(),
|
||||||
|
expectPush(
|
||||||
|
eventPusherToEvents(
|
||||||
|
org.NewAzureADIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
"name",
|
||||||
|
"clientID",
|
||||||
|
&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("clientSecret"),
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
idp.Options{},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
ClientSecret: "clientSecret",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
id: "id1",
|
||||||
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ok all set",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(),
|
||||||
|
expectPush(
|
||||||
|
eventPusherToEvents(
|
||||||
|
org.NewAzureADIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
"name",
|
||||||
|
"clientID",
|
||||||
|
&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("clientSecret"),
|
||||||
|
},
|
||||||
|
[]string{"openid"},
|
||||||
|
"tenant",
|
||||||
|
true,
|
||||||
|
idp.Options{
|
||||||
|
IsCreationAllowed: true,
|
||||||
|
IsLinkingAllowed: true,
|
||||||
|
IsAutoCreation: true,
|
||||||
|
IsAutoUpdate: true,
|
||||||
|
},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
idGenerator: id_mock.NewIDGeneratorExpectIDs(t, "id1"),
|
||||||
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
ClientSecret: "clientSecret",
|
||||||
|
Scopes: []string{"openid"},
|
||||||
|
Tenant: "tenant",
|
||||||
|
EmailVerified: true,
|
||||||
|
IDPOptions: idp.Options{
|
||||||
|
IsCreationAllowed: true,
|
||||||
|
IsLinkingAllowed: true,
|
||||||
|
IsAutoCreation: true,
|
||||||
|
IsAutoUpdate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
id: "id1",
|
||||||
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
c := &Commands{
|
||||||
|
eventstore: tt.fields.eventstore,
|
||||||
|
idGenerator: tt.fields.idGenerator,
|
||||||
|
idpConfigEncryption: tt.fields.secretCrypto,
|
||||||
|
}
|
||||||
|
id, got, err := c.AddOrgAzureADProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.provider)
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
if tt.res.err != nil && !tt.res.err(err) {
|
||||||
|
t.Errorf("got wrong err: %v ", err)
|
||||||
|
}
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.Equal(t, tt.res.id, id)
|
||||||
|
assert.Equal(t, tt.res.want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCommandSide_UpdateOrgAzureADIDP(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
eventstore *eventstore.Eventstore
|
||||||
|
secretCrypto crypto.EncryptionAlgorithm
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
resourceOwner string
|
||||||
|
id string
|
||||||
|
provider AzureADProvider
|
||||||
|
}
|
||||||
|
type res struct {
|
||||||
|
want *domain.ObjectDetails
|
||||||
|
err func(error) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
res res
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"invalid id",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
provider: AzureADProvider{},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-SAgh2", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid name",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-fh3h1", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invalid client id",
|
||||||
|
fields{
|
||||||
|
eventstore: eventstoreExpect(t),
|
||||||
|
},
|
||||||
|
args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res{
|
||||||
|
err: func(err error) bool {
|
||||||
|
return errors.Is(err, caos_errors.ThrowInvalidArgument(nil, "ORG-dmitg", ""))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not found",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
err: caos_errors.IsNotFound,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no changes",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewAzureADIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
"name",
|
||||||
|
"clientID",
|
||||||
|
&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("clientSecret"),
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
idp.Options{},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "name",
|
||||||
|
ClientID: "clientID",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "change ok",
|
||||||
|
fields: fields{
|
||||||
|
eventstore: eventstoreExpect(t,
|
||||||
|
expectFilter(
|
||||||
|
eventFromEventPusher(
|
||||||
|
org.NewAzureADIDPAddedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
"name",
|
||||||
|
"clientID",
|
||||||
|
&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("clientSecret"),
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
idp.Options{},
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
expectPush(
|
||||||
|
eventPusherToEvents(
|
||||||
|
func() eventstore.Command {
|
||||||
|
t := true
|
||||||
|
event, _ := org.NewAzureADIDPChangedEvent(context.Background(), &org.NewAggregate("org1").Aggregate,
|
||||||
|
"id1",
|
||||||
|
[]idp.AzureADIDPChanges{
|
||||||
|
idp.ChangeAzureADName("new name"),
|
||||||
|
idp.ChangeAzureADClientID("new clientID"),
|
||||||
|
idp.ChangeAzureADClientSecret(&crypto.CryptoValue{
|
||||||
|
CryptoType: crypto.TypeEncryption,
|
||||||
|
Algorithm: "enc",
|
||||||
|
KeyID: "id",
|
||||||
|
Crypted: []byte("new clientSecret"),
|
||||||
|
}),
|
||||||
|
idp.ChangeAzureADScopes([]string{"openid", "profile"}),
|
||||||
|
idp.ChangeAzureADTenant("new tenant"),
|
||||||
|
idp.ChangeAzureADIsEmailVerified(true),
|
||||||
|
idp.ChangeAzureADOptions(idp.OptionChanges{
|
||||||
|
IsCreationAllowed: &t,
|
||||||
|
IsLinkingAllowed: &t,
|
||||||
|
IsAutoCreation: &t,
|
||||||
|
IsAutoUpdate: &t,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return event
|
||||||
|
}(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
secretCrypto: crypto.CreateMockEncryptionAlg(gomock.NewController(t)),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
resourceOwner: "org1",
|
||||||
|
id: "id1",
|
||||||
|
provider: AzureADProvider{
|
||||||
|
Name: "new name",
|
||||||
|
ClientID: "new clientID",
|
||||||
|
ClientSecret: "new clientSecret",
|
||||||
|
Scopes: []string{"openid", "profile"},
|
||||||
|
Tenant: "new tenant",
|
||||||
|
EmailVerified: true,
|
||||||
|
IDPOptions: idp.Options{
|
||||||
|
IsCreationAllowed: true,
|
||||||
|
IsLinkingAllowed: true,
|
||||||
|
IsAutoCreation: true,
|
||||||
|
IsAutoUpdate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: res{
|
||||||
|
want: &domain.ObjectDetails{ResourceOwner: "org1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
c := &Commands{
|
||||||
|
eventstore: tt.fields.eventstore,
|
||||||
|
idpConfigEncryption: tt.fields.secretCrypto,
|
||||||
|
}
|
||||||
|
got, err := c.UpdateOrgAzureADProvider(tt.args.ctx, tt.args.resourceOwner, tt.args.id, tt.args.provider)
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
if tt.res.err != nil && !tt.res.err(err) {
|
||||||
|
t.Errorf("got wrong err: %v ", err)
|
||||||
|
}
|
||||||
|
if tt.res.err == nil {
|
||||||
|
assert.Equal(t, tt.res.want, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCommandSide_AddOrgGitHubIDP(t *testing.T) {
|
func TestCommandSide_AddOrgGitHubIDP(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
eventstore *eventstore.Eventstore
|
eventstore *eventstore.Eventstore
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
authURLTemplate string = "https://login.microsoftonline.com/%s/oauth2/v2.0/authorize"
|
authURLTemplate string = "https://login.microsoftonline.com/%s/oauth2/v2.0/authorize"
|
||||||
tokenURLTemplate string = "https://login.microsoftonline.com/%s/oauth2/v2.0/token"
|
tokenURLTemplate string = "https://login.microsoftonline.com/%s/oauth2/v2.0/token"
|
||||||
userinfoURL string = "https://graph.microsoft.com/oidc/userinfo"
|
userinfoURL string = "https://graph.microsoft.com/v1.0/me"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TenantType are the well known tenant types to scope the users that can authenticate. TenantType is not an
|
// TenantType are the well known tenant types to scope the users that can authenticate. TenantType is not an
|
||||||
@ -73,7 +73,7 @@ func WithOAuthOptions(opts ...oauth.ProviderOpts) ProviderOptions {
|
|||||||
|
|
||||||
// New creates an AzureAD provider using the [oauth.Provider] (OAuth 2.0 generic provider).
|
// New creates an AzureAD provider using the [oauth.Provider] (OAuth 2.0 generic provider).
|
||||||
// By default, it uses the [CommonTenant] and unverified emails.
|
// By default, it uses the [CommonTenant] and unverified emails.
|
||||||
func New(name, clientID, clientSecret, redirectURI string, opts ...ProviderOptions) (*Provider, error) {
|
func New(name, clientID, clientSecret, redirectURI string, scopes []string, opts ...ProviderOptions) (*Provider, error) {
|
||||||
provider := &Provider{
|
provider := &Provider{
|
||||||
tenant: CommonTenant,
|
tenant: CommonTenant,
|
||||||
options: make([]oauth.ProviderOpts, 0),
|
options: make([]oauth.ProviderOpts, 0),
|
||||||
@ -81,7 +81,7 @@ func New(name, clientID, clientSecret, redirectURI string, opts ...ProviderOptio
|
|||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(provider)
|
opt(provider)
|
||||||
}
|
}
|
||||||
config := newConfig(provider.tenant, clientID, clientSecret, redirectURI, []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail})
|
config := newConfig(provider.tenant, clientID, clientSecret, redirectURI, scopes)
|
||||||
rp, err := oauth.New(
|
rp, err := oauth.New(
|
||||||
config,
|
config,
|
||||||
name,
|
name,
|
||||||
@ -121,34 +121,38 @@ func newConfig(tenant TenantType, clientID, secret, callbackURL string, scopes [
|
|||||||
// AzureAD does not return an `email_verified` claim.
|
// AzureAD does not return an `email_verified` claim.
|
||||||
// The verification can be automatically activated on the provider ([WithEmailVerified])
|
// The verification can be automatically activated on the provider ([WithEmailVerified])
|
||||||
type User struct {
|
type User struct {
|
||||||
Sub string `json:"sub"`
|
ID string `json:"id"`
|
||||||
FamilyName string `json:"family_name"`
|
BusinessPhones []domain.PhoneNumber `json:"businessPhones"`
|
||||||
GivenName string `json:"given_name"`
|
DisplayName string `json:"displayName"`
|
||||||
Name string `json:"name"`
|
FirstName string `json:"givenName"`
|
||||||
PreferredUsername string `json:"preferred_username"`
|
JobTitle string `json:"jobTitle"`
|
||||||
Email domain.EmailAddress `json:"email"`
|
Email domain.EmailAddress `json:"mail"`
|
||||||
Picture string `json:"picture"`
|
MobilePhone domain.PhoneNumber `json:"mobilePhone"`
|
||||||
|
OfficeLocation string `json:"officeLocation"`
|
||||||
|
PreferredLanguage string `json:"preferredLanguage"`
|
||||||
|
LastName string `json:"surname"`
|
||||||
|
UserPrincipalName string `json:"userPrincipalName"`
|
||||||
isEmailVerified bool
|
isEmailVerified bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetID is an implementation of the [idp.User] interface.
|
// GetID is an implementation of the [idp.User] interface.
|
||||||
func (u *User) GetID() string {
|
func (u *User) GetID() string {
|
||||||
return u.Sub
|
return u.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFirstName is an implementation of the [idp.User] interface.
|
// GetFirstName is an implementation of the [idp.User] interface.
|
||||||
func (u *User) GetFirstName() string {
|
func (u *User) GetFirstName() string {
|
||||||
return u.GivenName
|
return u.FirstName
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLastName is an implementation of the [idp.User] interface.
|
// GetLastName is an implementation of the [idp.User] interface.
|
||||||
func (u *User) GetLastName() string {
|
func (u *User) GetLastName() string {
|
||||||
return u.FamilyName
|
return u.LastName
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDisplayName is an implementation of the [idp.User] interface.
|
// GetDisplayName is an implementation of the [idp.User] interface.
|
||||||
func (u *User) GetDisplayName() string {
|
func (u *User) GetDisplayName() string {
|
||||||
return u.Name
|
return u.DisplayName
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNickname is an implementation of the [idp.User] interface.
|
// GetNickname is an implementation of the [idp.User] interface.
|
||||||
@ -159,11 +163,16 @@ func (u *User) GetNickname() string {
|
|||||||
|
|
||||||
// GetPreferredUsername is an implementation of the [idp.User] interface.
|
// GetPreferredUsername is an implementation of the [idp.User] interface.
|
||||||
func (u *User) GetPreferredUsername() string {
|
func (u *User) GetPreferredUsername() string {
|
||||||
return u.PreferredUsername
|
return u.UserPrincipalName
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEmail is an implementation of the [idp.User] interface.
|
// GetEmail is an implementation of the [idp.User] interface.
|
||||||
func (u *User) GetEmail() domain.EmailAddress {
|
func (u *User) GetEmail() domain.EmailAddress {
|
||||||
|
if u.Email == "" {
|
||||||
|
// if the user used a social login on Azure as well, the email will be empty
|
||||||
|
// but is used as username
|
||||||
|
return domain.EmailAddress(u.UserPrincipalName)
|
||||||
|
}
|
||||||
return u.Email
|
return u.Email
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,10 +197,8 @@ func (u *User) IsPhoneVerified() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPreferredLanguage is an implementation of the [idp.User] interface.
|
// GetPreferredLanguage is an implementation of the [idp.User] interface.
|
||||||
// It returns [language.Und] because AzureAD does not provide the user's language
|
|
||||||
func (u *User) GetPreferredLanguage() language.Tag {
|
func (u *User) GetPreferredLanguage() language.Tag {
|
||||||
// AzureAD does not provide the user's language
|
return language.Make(u.PreferredLanguage)
|
||||||
return language.Und
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProfile is an implementation of the [idp.User] interface.
|
// GetProfile is an implementation of the [idp.User] interface.
|
||||||
@ -202,5 +209,5 @@ func (u *User) GetProfile() string {
|
|||||||
|
|
||||||
// GetAvatarURL is an implementation of the [idp.User] interface.
|
// GetAvatarURL is an implementation of the [idp.User] interface.
|
||||||
func (u *User) GetAvatarURL() string {
|
func (u *User) GetAvatarURL() string {
|
||||||
return u.Picture
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/zitadel/oidc/v2/pkg/client/rp"
|
"github.com/zitadel/oidc/v2/pkg/client/rp"
|
||||||
|
openid "github.com/zitadel/oidc/v2/pkg/oidc"
|
||||||
|
|
||||||
"github.com/zitadel/zitadel/internal/idp"
|
"github.com/zitadel/zitadel/internal/idp"
|
||||||
"github.com/zitadel/zitadel/internal/idp/providers/oauth"
|
"github.com/zitadel/zitadel/internal/idp/providers/oauth"
|
||||||
@ -19,6 +20,7 @@ func TestProvider_BeginAuth(t *testing.T) {
|
|||||||
clientID string
|
clientID string
|
||||||
clientSecret string
|
clientSecret string
|
||||||
redirectURI string
|
redirectURI string
|
||||||
|
scopes []string
|
||||||
options []ProviderOptions
|
options []ProviderOptions
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@ -34,7 +36,7 @@ func TestProvider_BeginAuth(t *testing.T) {
|
|||||||
redirectURI: "redirectURI",
|
redirectURI: "redirectURI",
|
||||||
},
|
},
|
||||||
want: &oidc.Session{
|
want: &oidc.Session{
|
||||||
AuthURL: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=clientID&prompt=select_account&redirect_uri=redirectURI&response_type=code&scope=openid+profile+email&state=testState",
|
AuthURL: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=clientID&prompt=select_account&redirect_uri=redirectURI&response_type=code&scope=openid&state=testState",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -48,7 +50,22 @@ func TestProvider_BeginAuth(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: &oidc.Session{
|
want: &oidc.Session{
|
||||||
AuthURL: "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=clientID&prompt=select_account&redirect_uri=redirectURI&response_type=code&scope=openid+profile+email&state=testState",
|
AuthURL: "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=clientID&prompt=select_account&redirect_uri=redirectURI&response_type=code&scope=openid&state=testState",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "custom scopes",
|
||||||
|
fields: fields{
|
||||||
|
clientID: "clientID",
|
||||||
|
clientSecret: "clientSecret",
|
||||||
|
redirectURI: "redirectURI",
|
||||||
|
scopes: []string{openid.ScopeOpenID, openid.ScopeProfile, "user"},
|
||||||
|
options: []ProviderOptions{
|
||||||
|
WithTenant(ConsumersTenant),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: &oidc.Session{
|
||||||
|
AuthURL: "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=clientID&prompt=select_account&redirect_uri=redirectURI&response_type=code&scope=openid+profile+user&state=testState",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -57,7 +74,7 @@ func TestProvider_BeginAuth(t *testing.T) {
|
|||||||
a := assert.New(t)
|
a := assert.New(t)
|
||||||
r := require.New(t)
|
r := require.New(t)
|
||||||
|
|
||||||
provider, err := New(tt.fields.name, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.options...)
|
provider, err := New(tt.fields.name, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.options...)
|
||||||
r.NoError(err)
|
r.NoError(err)
|
||||||
|
|
||||||
session, err := provider.BeginAuth(context.Background(), "testState")
|
session, err := provider.BeginAuth(context.Background(), "testState")
|
||||||
@ -74,6 +91,7 @@ func TestProvider_Options(t *testing.T) {
|
|||||||
clientID string
|
clientID string
|
||||||
clientSecret string
|
clientSecret string
|
||||||
redirectURI string
|
redirectURI string
|
||||||
|
scopes []string
|
||||||
options []ProviderOptions
|
options []ProviderOptions
|
||||||
}
|
}
|
||||||
type want struct {
|
type want struct {
|
||||||
@ -98,6 +116,7 @@ func TestProvider_Options(t *testing.T) {
|
|||||||
clientID: "clientID",
|
clientID: "clientID",
|
||||||
clientSecret: "clientSecret",
|
clientSecret: "clientSecret",
|
||||||
redirectURI: "redirectURI",
|
redirectURI: "redirectURI",
|
||||||
|
scopes: nil,
|
||||||
options: nil,
|
options: nil,
|
||||||
},
|
},
|
||||||
want: want{
|
want: want{
|
||||||
@ -146,7 +165,7 @@ func TestProvider_Options(t *testing.T) {
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
a := assert.New(t)
|
a := assert.New(t)
|
||||||
|
|
||||||
provider, err := New(tt.fields.name, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.options...)
|
provider, err := New(tt.fields.name, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.options...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
a.Equal(tt.want.name, provider.Name())
|
a.Equal(tt.want.name, provider.Name())
|
||||||
|
@ -25,6 +25,7 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
clientID string
|
clientID string
|
||||||
clientSecret string
|
clientSecret string
|
||||||
redirectURI string
|
redirectURI string
|
||||||
|
scopes []string
|
||||||
httpMock func()
|
httpMock func()
|
||||||
options []ProviderOptions
|
options []ProviderOptions
|
||||||
authURL string
|
authURL string
|
||||||
@ -61,7 +62,7 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
redirectURI: "redirectURI",
|
redirectURI: "redirectURI",
|
||||||
httpMock: func() {
|
httpMock: func() {
|
||||||
gock.New("https://graph.microsoft.com").
|
gock.New("https://graph.microsoft.com").
|
||||||
Get("/oidc/userinfo").
|
Get("/v1.0/me").
|
||||||
Reply(200).
|
Reply(200).
|
||||||
JSON(userinfo())
|
JSON(userinfo())
|
||||||
},
|
},
|
||||||
@ -82,7 +83,7 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
redirectURI: "redirectURI",
|
redirectURI: "redirectURI",
|
||||||
httpMock: func() {
|
httpMock: func() {
|
||||||
gock.New("https://graph.microsoft.com").
|
gock.New("https://graph.microsoft.com").
|
||||||
Get("/oidc/userinfo").
|
Get("/v1.0/me").
|
||||||
Reply(http.StatusInternalServerError)
|
Reply(http.StatusInternalServerError)
|
||||||
},
|
},
|
||||||
authURL: "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=clientID&redirect_uri=redirectURI&response_type=code&scope=openid+profile+email&state=testState",
|
authURL: "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=clientID&redirect_uri=redirectURI&response_type=code&scope=openid+profile+email&state=testState",
|
||||||
@ -119,7 +120,7 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
redirectURI: "redirectURI",
|
redirectURI: "redirectURI",
|
||||||
httpMock: func() {
|
httpMock: func() {
|
||||||
gock.New("https://graph.microsoft.com").
|
gock.New("https://graph.microsoft.com").
|
||||||
Get("/oidc/userinfo").
|
Get("/v1.0/me").
|
||||||
Reply(200).
|
Reply(200).
|
||||||
JSON(userinfo())
|
JSON(userinfo())
|
||||||
},
|
},
|
||||||
@ -145,16 +146,20 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: want{
|
want: want{
|
||||||
user: &User{
|
user: &User{
|
||||||
Sub: "sub",
|
ID: "id",
|
||||||
FamilyName: "lastname",
|
BusinessPhones: []domain.PhoneNumber{"phone1", "phone2"},
|
||||||
GivenName: "firstname",
|
DisplayName: "firstname lastname",
|
||||||
Name: "firstname lastname",
|
FirstName: "firstname",
|
||||||
PreferredUsername: "username",
|
JobTitle: "title",
|
||||||
Email: "email",
|
Email: "email",
|
||||||
Picture: "picture",
|
MobilePhone: "mobile",
|
||||||
|
OfficeLocation: "office",
|
||||||
|
PreferredLanguage: "en",
|
||||||
|
LastName: "lastname",
|
||||||
|
UserPrincipalName: "username",
|
||||||
isEmailVerified: false,
|
isEmailVerified: false,
|
||||||
},
|
},
|
||||||
id: "sub",
|
id: "id",
|
||||||
firstName: "firstname",
|
firstName: "firstname",
|
||||||
lastName: "lastname",
|
lastName: "lastname",
|
||||||
displayName: "firstname lastname",
|
displayName: "firstname lastname",
|
||||||
@ -164,8 +169,7 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
isEmailVerified: false,
|
isEmailVerified: false,
|
||||||
phone: "",
|
phone: "",
|
||||||
isPhoneVerified: false,
|
isPhoneVerified: false,
|
||||||
preferredLanguage: language.Und,
|
preferredLanguage: language.English,
|
||||||
avatarURL: "picture",
|
|
||||||
profile: "",
|
profile: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -180,7 +184,7 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
httpMock: func() {
|
httpMock: func() {
|
||||||
gock.New("https://graph.microsoft.com").
|
gock.New("https://graph.microsoft.com").
|
||||||
Get("/oidc/userinfo").
|
Get("/v1.0/me").
|
||||||
Reply(200).
|
Reply(200).
|
||||||
JSON(userinfo())
|
JSON(userinfo())
|
||||||
},
|
},
|
||||||
@ -206,16 +210,20 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
},
|
},
|
||||||
want: want{
|
want: want{
|
||||||
user: &User{
|
user: &User{
|
||||||
Sub: "sub",
|
ID: "id",
|
||||||
FamilyName: "lastname",
|
BusinessPhones: []domain.PhoneNumber{"phone1", "phone2"},
|
||||||
GivenName: "firstname",
|
DisplayName: "firstname lastname",
|
||||||
Name: "firstname lastname",
|
FirstName: "firstname",
|
||||||
PreferredUsername: "username",
|
JobTitle: "title",
|
||||||
Email: "email",
|
Email: "email",
|
||||||
Picture: "picture",
|
MobilePhone: "mobile",
|
||||||
|
OfficeLocation: "office",
|
||||||
|
PreferredLanguage: "en",
|
||||||
|
LastName: "lastname",
|
||||||
|
UserPrincipalName: "username",
|
||||||
isEmailVerified: true,
|
isEmailVerified: true,
|
||||||
},
|
},
|
||||||
id: "sub",
|
id: "id",
|
||||||
firstName: "firstname",
|
firstName: "firstname",
|
||||||
lastName: "lastname",
|
lastName: "lastname",
|
||||||
displayName: "firstname lastname",
|
displayName: "firstname lastname",
|
||||||
@ -225,8 +233,7 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
isEmailVerified: true,
|
isEmailVerified: true,
|
||||||
phone: "",
|
phone: "",
|
||||||
isPhoneVerified: false,
|
isPhoneVerified: false,
|
||||||
preferredLanguage: language.Und,
|
preferredLanguage: language.English,
|
||||||
avatarURL: "picture",
|
|
||||||
profile: "",
|
profile: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -237,7 +244,7 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
tt.fields.httpMock()
|
tt.fields.httpMock()
|
||||||
a := assert.New(t)
|
a := assert.New(t)
|
||||||
|
|
||||||
provider, err := New(tt.fields.name, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.options...)
|
provider, err := New(tt.fields.name, tt.fields.clientID, tt.fields.clientSecret, tt.fields.redirectURI, tt.fields.scopes, tt.fields.options...)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
session := &oauth.Session{
|
session := &oauth.Session{
|
||||||
@ -272,15 +279,18 @@ func TestSession_FetchUser(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func userinfo() oidc.UserInfoSetter {
|
func userinfo() *User {
|
||||||
userinfo := oidc.NewUserInfo()
|
return &User{
|
||||||
userinfo.SetSubject("sub")
|
ID: "id",
|
||||||
userinfo.SetName("firstname lastname")
|
BusinessPhones: []domain.PhoneNumber{"phone1", "phone2"},
|
||||||
userinfo.SetPreferredUsername("username")
|
DisplayName: "firstname lastname",
|
||||||
userinfo.SetNickname("nickname")
|
FirstName: "firstname",
|
||||||
userinfo.SetEmail("email", false) // azure add does not send the email_verified claim
|
JobTitle: "title",
|
||||||
userinfo.SetPicture("picture")
|
Email: "email",
|
||||||
userinfo.SetGivenName("firstname")
|
MobilePhone: "mobile",
|
||||||
userinfo.SetFamilyName("lastname")
|
OfficeLocation: "office",
|
||||||
return userinfo
|
PreferredLanguage: "en",
|
||||||
|
LastName: "lastname",
|
||||||
|
UserPrincipalName: "username",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,7 @@ type IDPTemplate struct {
|
|||||||
*OAuthIDPTemplate
|
*OAuthIDPTemplate
|
||||||
*OIDCIDPTemplate
|
*OIDCIDPTemplate
|
||||||
*JWTIDPTemplate
|
*JWTIDPTemplate
|
||||||
|
*AzureADIDPTemplate
|
||||||
*GitHubIDPTemplate
|
*GitHubIDPTemplate
|
||||||
*GitHubEnterpriseIDPTemplate
|
*GitHubEnterpriseIDPTemplate
|
||||||
*GitLabIDPTemplate
|
*GitLabIDPTemplate
|
||||||
@ -77,6 +78,15 @@ type JWTIDPTemplate struct {
|
|||||||
Endpoint string
|
Endpoint string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AzureADIDPTemplate struct {
|
||||||
|
IDPID string
|
||||||
|
ClientID string
|
||||||
|
ClientSecret *crypto.CryptoValue
|
||||||
|
Scopes database.StringArray
|
||||||
|
Tenant string
|
||||||
|
IsEmailVerified bool
|
||||||
|
}
|
||||||
|
|
||||||
type GitHubIDPTemplate struct {
|
type GitHubIDPTemplate struct {
|
||||||
IDPID string
|
IDPID string
|
||||||
ClientID string
|
ClientID string
|
||||||
@ -301,6 +311,41 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
azureadIdpTemplateTable = table{
|
||||||
|
name: projection.IDPTemplateAzureADTable,
|
||||||
|
instanceIDCol: projection.AzureADInstanceIDCol,
|
||||||
|
}
|
||||||
|
AzureADIDCol = Column{
|
||||||
|
name: projection.AzureADIDCol,
|
||||||
|
table: azureadIdpTemplateTable,
|
||||||
|
}
|
||||||
|
AzureADInstanceIDCol = Column{
|
||||||
|
name: projection.AzureADInstanceIDCol,
|
||||||
|
table: azureadIdpTemplateTable,
|
||||||
|
}
|
||||||
|
AzureADClientIDCol = Column{
|
||||||
|
name: projection.AzureADClientIDCol,
|
||||||
|
table: azureadIdpTemplateTable,
|
||||||
|
}
|
||||||
|
AzureADClientSecretCol = Column{
|
||||||
|
name: projection.AzureADClientSecretCol,
|
||||||
|
table: azureadIdpTemplateTable,
|
||||||
|
}
|
||||||
|
AzureADScopesCol = Column{
|
||||||
|
name: projection.AzureADScopesCol,
|
||||||
|
table: azureadIdpTemplateTable,
|
||||||
|
}
|
||||||
|
AzureADTenantCol = Column{
|
||||||
|
name: projection.AzureADTenantCol,
|
||||||
|
table: azureadIdpTemplateTable,
|
||||||
|
}
|
||||||
|
AzureADIsEmailVerified = Column{
|
||||||
|
name: projection.AzureADIsEmailVerified,
|
||||||
|
table: azureadIdpTemplateTable,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
githubIdpTemplateTable = table{
|
githubIdpTemplateTable = table{
|
||||||
name: projection.IDPTemplateGitHubTable,
|
name: projection.IDPTemplateGitHubTable,
|
||||||
@ -683,6 +728,13 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
|
|||||||
JWTEndpointCol.identifier(),
|
JWTEndpointCol.identifier(),
|
||||||
JWTKeysEndpointCol.identifier(),
|
JWTKeysEndpointCol.identifier(),
|
||||||
JWTHeaderNameCol.identifier(),
|
JWTHeaderNameCol.identifier(),
|
||||||
|
// azure
|
||||||
|
AzureADIDCol.identifier(),
|
||||||
|
AzureADClientIDCol.identifier(),
|
||||||
|
AzureADClientSecretCol.identifier(),
|
||||||
|
AzureADScopesCol.identifier(),
|
||||||
|
AzureADTenantCol.identifier(),
|
||||||
|
AzureADIsEmailVerified.identifier(),
|
||||||
// github
|
// github
|
||||||
GitHubIDCol.identifier(),
|
GitHubIDCol.identifier(),
|
||||||
GitHubClientIDCol.identifier(),
|
GitHubClientIDCol.identifier(),
|
||||||
@ -739,6 +791,7 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
|
|||||||
LeftJoin(join(OAuthIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(OAuthIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
|
||||||
|
LeftJoin(join(AzureADIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(GitHubIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(GitHubIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(GitHubEnterpriseIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(GitHubEnterpriseIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(GitLabIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(GitLabIDCol, IDPTemplateIDCol)).
|
||||||
@ -772,6 +825,13 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
|
|||||||
jwtKeysEndpoint := sql.NullString{}
|
jwtKeysEndpoint := sql.NullString{}
|
||||||
jwtHeaderName := sql.NullString{}
|
jwtHeaderName := sql.NullString{}
|
||||||
|
|
||||||
|
azureadID := sql.NullString{}
|
||||||
|
azureadClientID := sql.NullString{}
|
||||||
|
azureadClientSecret := new(crypto.CryptoValue)
|
||||||
|
azureadScopes := database.StringArray{}
|
||||||
|
azureadTenant := sql.NullString{}
|
||||||
|
azureadIsEmailVerified := sql.NullBool{}
|
||||||
|
|
||||||
githubID := sql.NullString{}
|
githubID := sql.NullString{}
|
||||||
githubClientID := sql.NullString{}
|
githubClientID := sql.NullString{}
|
||||||
githubClientSecret := new(crypto.CryptoValue)
|
githubClientSecret := new(crypto.CryptoValue)
|
||||||
@ -859,6 +919,13 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
|
|||||||
&jwtEndpoint,
|
&jwtEndpoint,
|
||||||
&jwtKeysEndpoint,
|
&jwtKeysEndpoint,
|
||||||
&jwtHeaderName,
|
&jwtHeaderName,
|
||||||
|
// azure
|
||||||
|
&azureadID,
|
||||||
|
&azureadClientID,
|
||||||
|
&azureadClientSecret,
|
||||||
|
&azureadScopes,
|
||||||
|
&azureadTenant,
|
||||||
|
&azureadIsEmailVerified,
|
||||||
// github
|
// github
|
||||||
&githubID,
|
&githubID,
|
||||||
&githubClientID,
|
&githubClientID,
|
||||||
@ -951,6 +1018,16 @@ func prepareIDPTemplateByIDQuery(ctx context.Context, db prepareDatabase) (sq.Se
|
|||||||
Endpoint: jwtEndpoint.String,
|
Endpoint: jwtEndpoint.String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if azureadID.Valid {
|
||||||
|
idpTemplate.AzureADIDPTemplate = &AzureADIDPTemplate{
|
||||||
|
IDPID: azureadID.String,
|
||||||
|
ClientID: azureadClientID.String,
|
||||||
|
ClientSecret: azureadClientSecret,
|
||||||
|
Scopes: azureadScopes,
|
||||||
|
Tenant: azureadTenant.String,
|
||||||
|
IsEmailVerified: azureadIsEmailVerified.Bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
if githubID.Valid {
|
if githubID.Valid {
|
||||||
idpTemplate.GitHubIDPTemplate = &GitHubIDPTemplate{
|
idpTemplate.GitHubIDPTemplate = &GitHubIDPTemplate{
|
||||||
IDPID: githubID.String,
|
IDPID: githubID.String,
|
||||||
@ -1064,6 +1141,13 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
|
|||||||
JWTEndpointCol.identifier(),
|
JWTEndpointCol.identifier(),
|
||||||
JWTKeysEndpointCol.identifier(),
|
JWTKeysEndpointCol.identifier(),
|
||||||
JWTHeaderNameCol.identifier(),
|
JWTHeaderNameCol.identifier(),
|
||||||
|
// azure
|
||||||
|
AzureADIDCol.identifier(),
|
||||||
|
AzureADClientIDCol.identifier(),
|
||||||
|
AzureADClientSecretCol.identifier(),
|
||||||
|
AzureADScopesCol.identifier(),
|
||||||
|
AzureADTenantCol.identifier(),
|
||||||
|
AzureADIsEmailVerified.identifier(),
|
||||||
// github
|
// github
|
||||||
GitHubIDCol.identifier(),
|
GitHubIDCol.identifier(),
|
||||||
GitHubClientIDCol.identifier(),
|
GitHubClientIDCol.identifier(),
|
||||||
@ -1121,6 +1205,7 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
|
|||||||
LeftJoin(join(OAuthIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(OAuthIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(OIDCIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(JWTIDCol, IDPTemplateIDCol)).
|
||||||
|
LeftJoin(join(AzureADIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(GitHubIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(GitHubIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(GitHubEnterpriseIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(GitHubEnterpriseIDCol, IDPTemplateIDCol)).
|
||||||
LeftJoin(join(GitLabIDCol, IDPTemplateIDCol)).
|
LeftJoin(join(GitLabIDCol, IDPTemplateIDCol)).
|
||||||
@ -1157,6 +1242,13 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
|
|||||||
jwtKeysEndpoint := sql.NullString{}
|
jwtKeysEndpoint := sql.NullString{}
|
||||||
jwtHeaderName := sql.NullString{}
|
jwtHeaderName := sql.NullString{}
|
||||||
|
|
||||||
|
azureadID := sql.NullString{}
|
||||||
|
azureadClientID := sql.NullString{}
|
||||||
|
azureadClientSecret := new(crypto.CryptoValue)
|
||||||
|
azureadScopes := database.StringArray{}
|
||||||
|
azureadTenant := sql.NullString{}
|
||||||
|
azureadIsEmailVerified := sql.NullBool{}
|
||||||
|
|
||||||
githubID := sql.NullString{}
|
githubID := sql.NullString{}
|
||||||
githubClientID := sql.NullString{}
|
githubClientID := sql.NullString{}
|
||||||
githubClientSecret := new(crypto.CryptoValue)
|
githubClientSecret := new(crypto.CryptoValue)
|
||||||
@ -1244,6 +1336,13 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
|
|||||||
&jwtEndpoint,
|
&jwtEndpoint,
|
||||||
&jwtKeysEndpoint,
|
&jwtKeysEndpoint,
|
||||||
&jwtHeaderName,
|
&jwtHeaderName,
|
||||||
|
// azure
|
||||||
|
&azureadID,
|
||||||
|
&azureadClientID,
|
||||||
|
&azureadClientSecret,
|
||||||
|
&azureadScopes,
|
||||||
|
&azureadTenant,
|
||||||
|
&azureadIsEmailVerified,
|
||||||
// github
|
// github
|
||||||
&githubID,
|
&githubID,
|
||||||
&githubClientID,
|
&githubClientID,
|
||||||
@ -1335,6 +1434,16 @@ func prepareIDPTemplatesQuery(ctx context.Context, db prepareDatabase) (sq.Selec
|
|||||||
Endpoint: jwtEndpoint.String,
|
Endpoint: jwtEndpoint.String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if azureadID.Valid {
|
||||||
|
idpTemplate.AzureADIDPTemplate = &AzureADIDPTemplate{
|
||||||
|
IDPID: azureadID.String,
|
||||||
|
ClientID: azureadClientID.String,
|
||||||
|
ClientSecret: azureadClientSecret,
|
||||||
|
Scopes: azureadScopes,
|
||||||
|
Tenant: azureadTenant.String,
|
||||||
|
IsEmailVerified: azureadIsEmailVerified.Bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
if githubID.Valid {
|
if githubID.Valid {
|
||||||
idpTemplate.GitHubIDPTemplate = &GitHubIDPTemplate{
|
idpTemplate.GitHubIDPTemplate = &GitHubIDPTemplate{
|
||||||
IDPID: githubID.String,
|
IDPID: githubID.String,
|
||||||
|
@ -49,6 +49,13 @@ var (
|
|||||||
` projections.idp_templates3_jwt.jwt_endpoint,` +
|
` projections.idp_templates3_jwt.jwt_endpoint,` +
|
||||||
` projections.idp_templates3_jwt.keys_endpoint,` +
|
` projections.idp_templates3_jwt.keys_endpoint,` +
|
||||||
` projections.idp_templates3_jwt.header_name,` +
|
` projections.idp_templates3_jwt.header_name,` +
|
||||||
|
// azure
|
||||||
|
` projections.idp_templates3_azure.idp_id,` +
|
||||||
|
` projections.idp_templates3_azure.client_id,` +
|
||||||
|
` projections.idp_templates3_azure.client_secret,` +
|
||||||
|
` projections.idp_templates3_azure.scopes,` +
|
||||||
|
` projections.idp_templates3_azure.tenant,` +
|
||||||
|
` projections.idp_templates3_azure.is_email_verified,` +
|
||||||
// github
|
// github
|
||||||
` projections.idp_templates3_github.idp_id,` +
|
` projections.idp_templates3_github.idp_id,` +
|
||||||
` projections.idp_templates3_github.client_id,` +
|
` projections.idp_templates3_github.client_id,` +
|
||||||
@ -105,6 +112,7 @@ var (
|
|||||||
` LEFT JOIN projections.idp_templates3_oauth2 ON projections.idp_templates3.id = projections.idp_templates3_oauth2.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_oauth2.instance_id` +
|
` LEFT JOIN projections.idp_templates3_oauth2 ON projections.idp_templates3.id = projections.idp_templates3_oauth2.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_oauth2.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_oidc ON projections.idp_templates3.id = projections.idp_templates3_oidc.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_oidc.instance_id` +
|
` LEFT JOIN projections.idp_templates3_oidc ON projections.idp_templates3.id = projections.idp_templates3_oidc.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_oidc.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_jwt ON projections.idp_templates3.id = projections.idp_templates3_jwt.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_jwt.instance_id` +
|
` LEFT JOIN projections.idp_templates3_jwt ON projections.idp_templates3.id = projections.idp_templates3_jwt.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_jwt.instance_id` +
|
||||||
|
` LEFT JOIN projections.idp_templates3_azure ON projections.idp_templates3.id = projections.idp_templates3_azure.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_azure.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_github ON projections.idp_templates3.id = projections.idp_templates3_github.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github.instance_id` +
|
` LEFT JOIN projections.idp_templates3_github ON projections.idp_templates3.id = projections.idp_templates3_github.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_github_enterprise ON projections.idp_templates3.id = projections.idp_templates3_github_enterprise.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github_enterprise.instance_id` +
|
` LEFT JOIN projections.idp_templates3_github_enterprise ON projections.idp_templates3.id = projections.idp_templates3_github_enterprise.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github_enterprise.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_gitlab ON projections.idp_templates3.id = projections.idp_templates3_gitlab.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_gitlab.instance_id` +
|
` LEFT JOIN projections.idp_templates3_gitlab ON projections.idp_templates3.id = projections.idp_templates3_gitlab.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_gitlab.instance_id` +
|
||||||
@ -147,6 +155,13 @@ var (
|
|||||||
"jwt_endpoint",
|
"jwt_endpoint",
|
||||||
"keys_endpoint",
|
"keys_endpoint",
|
||||||
"header_name",
|
"header_name",
|
||||||
|
// azure
|
||||||
|
"idp_id",
|
||||||
|
"client_id",
|
||||||
|
"client_secret",
|
||||||
|
"scopes",
|
||||||
|
"tenant",
|
||||||
|
"is_email_verified",
|
||||||
// github config
|
// github config
|
||||||
"idp_id",
|
"idp_id",
|
||||||
"client_id",
|
"client_id",
|
||||||
@ -234,6 +249,13 @@ var (
|
|||||||
` projections.idp_templates3_jwt.jwt_endpoint,` +
|
` projections.idp_templates3_jwt.jwt_endpoint,` +
|
||||||
` projections.idp_templates3_jwt.keys_endpoint,` +
|
` projections.idp_templates3_jwt.keys_endpoint,` +
|
||||||
` projections.idp_templates3_jwt.header_name,` +
|
` projections.idp_templates3_jwt.header_name,` +
|
||||||
|
// azure
|
||||||
|
` projections.idp_templates3_azure.idp_id,` +
|
||||||
|
` projections.idp_templates3_azure.client_id,` +
|
||||||
|
` projections.idp_templates3_azure.client_secret,` +
|
||||||
|
` projections.idp_templates3_azure.scopes,` +
|
||||||
|
` projections.idp_templates3_azure.tenant,` +
|
||||||
|
` projections.idp_templates3_azure.is_email_verified,` +
|
||||||
// github
|
// github
|
||||||
` projections.idp_templates3_github.idp_id,` +
|
` projections.idp_templates3_github.idp_id,` +
|
||||||
` projections.idp_templates3_github.client_id,` +
|
` projections.idp_templates3_github.client_id,` +
|
||||||
@ -291,6 +313,7 @@ var (
|
|||||||
` LEFT JOIN projections.idp_templates3_oauth2 ON projections.idp_templates3.id = projections.idp_templates3_oauth2.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_oauth2.instance_id` +
|
` LEFT JOIN projections.idp_templates3_oauth2 ON projections.idp_templates3.id = projections.idp_templates3_oauth2.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_oauth2.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_oidc ON projections.idp_templates3.id = projections.idp_templates3_oidc.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_oidc.instance_id` +
|
` LEFT JOIN projections.idp_templates3_oidc ON projections.idp_templates3.id = projections.idp_templates3_oidc.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_oidc.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_jwt ON projections.idp_templates3.id = projections.idp_templates3_jwt.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_jwt.instance_id` +
|
` LEFT JOIN projections.idp_templates3_jwt ON projections.idp_templates3.id = projections.idp_templates3_jwt.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_jwt.instance_id` +
|
||||||
|
` LEFT JOIN projections.idp_templates3_azure ON projections.idp_templates3.id = projections.idp_templates3_azure.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_azure.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_github ON projections.idp_templates3.id = projections.idp_templates3_github.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github.instance_id` +
|
` LEFT JOIN projections.idp_templates3_github ON projections.idp_templates3.id = projections.idp_templates3_github.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_github_enterprise ON projections.idp_templates3.id = projections.idp_templates3_github_enterprise.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github_enterprise.instance_id` +
|
` LEFT JOIN projections.idp_templates3_github_enterprise ON projections.idp_templates3.id = projections.idp_templates3_github_enterprise.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_github_enterprise.instance_id` +
|
||||||
` LEFT JOIN projections.idp_templates3_gitlab ON projections.idp_templates3.id = projections.idp_templates3_gitlab.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_gitlab.instance_id` +
|
` LEFT JOIN projections.idp_templates3_gitlab ON projections.idp_templates3.id = projections.idp_templates3_gitlab.idp_id AND projections.idp_templates3.instance_id = projections.idp_templates3_gitlab.instance_id` +
|
||||||
@ -333,6 +356,13 @@ var (
|
|||||||
"jwt_endpoint",
|
"jwt_endpoint",
|
||||||
"keys_endpoint",
|
"keys_endpoint",
|
||||||
"header_name",
|
"header_name",
|
||||||
|
// azure
|
||||||
|
"idp_id",
|
||||||
|
"client_id",
|
||||||
|
"client_secret",
|
||||||
|
"scopes",
|
||||||
|
"tenant",
|
||||||
|
"is_email_verified",
|
||||||
// github config
|
// github config
|
||||||
"idp_id",
|
"idp_id",
|
||||||
"client_id",
|
"client_id",
|
||||||
@ -460,6 +490,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -583,6 +620,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -703,6 +747,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
"jwt",
|
"jwt",
|
||||||
"keys",
|
"keys",
|
||||||
"header",
|
"header",
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -823,6 +874,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
"idp-id",
|
"idp-id",
|
||||||
"client_id",
|
"client_id",
|
||||||
@ -942,6 +1000,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1061,6 +1126,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1181,6 +1253,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1300,6 +1379,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1438,6 +1524,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1587,6 +1680,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1734,6 +1834,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1856,6 +1963,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -1944,6 +2058,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -2032,6 +2153,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -2120,6 +2248,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -2208,6 +2343,13 @@ func Test_IDPTemplateTemplatesPrepares(t *testing.T) {
|
|||||||
"jwt",
|
"jwt",
|
||||||
"keys",
|
"keys",
|
||||||
"header",
|
"header",
|
||||||
|
// azure
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
// github
|
// github
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
@ -21,6 +21,7 @@ const (
|
|||||||
IDPTemplateOAuthTable = IDPTemplateTable + "_" + IDPTemplateOAuthSuffix
|
IDPTemplateOAuthTable = IDPTemplateTable + "_" + IDPTemplateOAuthSuffix
|
||||||
IDPTemplateOIDCTable = IDPTemplateTable + "_" + IDPTemplateOIDCSuffix
|
IDPTemplateOIDCTable = IDPTemplateTable + "_" + IDPTemplateOIDCSuffix
|
||||||
IDPTemplateJWTTable = IDPTemplateTable + "_" + IDPTemplateJWTSuffix
|
IDPTemplateJWTTable = IDPTemplateTable + "_" + IDPTemplateJWTSuffix
|
||||||
|
IDPTemplateAzureADTable = IDPTemplateTable + "_" + IDPTemplateAzureADSuffix
|
||||||
IDPTemplateGitHubTable = IDPTemplateTable + "_" + IDPTemplateGitHubSuffix
|
IDPTemplateGitHubTable = IDPTemplateTable + "_" + IDPTemplateGitHubSuffix
|
||||||
IDPTemplateGitHubEnterpriseTable = IDPTemplateTable + "_" + IDPTemplateGitHubEnterpriseSuffix
|
IDPTemplateGitHubEnterpriseTable = IDPTemplateTable + "_" + IDPTemplateGitHubEnterpriseSuffix
|
||||||
IDPTemplateGitLabTable = IDPTemplateTable + "_" + IDPTemplateGitLabSuffix
|
IDPTemplateGitLabTable = IDPTemplateTable + "_" + IDPTemplateGitLabSuffix
|
||||||
@ -31,6 +32,7 @@ const (
|
|||||||
IDPTemplateOAuthSuffix = "oauth2"
|
IDPTemplateOAuthSuffix = "oauth2"
|
||||||
IDPTemplateOIDCSuffix = "oidc"
|
IDPTemplateOIDCSuffix = "oidc"
|
||||||
IDPTemplateJWTSuffix = "jwt"
|
IDPTemplateJWTSuffix = "jwt"
|
||||||
|
IDPTemplateAzureADSuffix = "azure"
|
||||||
IDPTemplateGitHubSuffix = "github"
|
IDPTemplateGitHubSuffix = "github"
|
||||||
IDPTemplateGitHubEnterpriseSuffix = "github_enterprise"
|
IDPTemplateGitHubEnterpriseSuffix = "github_enterprise"
|
||||||
IDPTemplateGitLabSuffix = "gitlab"
|
IDPTemplateGitLabSuffix = "gitlab"
|
||||||
@ -78,6 +80,14 @@ const (
|
|||||||
JWTKeysEndpointCol = "keys_endpoint"
|
JWTKeysEndpointCol = "keys_endpoint"
|
||||||
JWTHeaderNameCol = "header_name"
|
JWTHeaderNameCol = "header_name"
|
||||||
|
|
||||||
|
AzureADIDCol = "idp_id"
|
||||||
|
AzureADInstanceIDCol = "instance_id"
|
||||||
|
AzureADClientIDCol = "client_id"
|
||||||
|
AzureADClientSecretCol = "client_secret"
|
||||||
|
AzureADScopesCol = "scopes"
|
||||||
|
AzureADTenantCol = "tenant"
|
||||||
|
AzureADIsEmailVerified = "is_email_verified"
|
||||||
|
|
||||||
GitHubIDCol = "idp_id"
|
GitHubIDCol = "idp_id"
|
||||||
GitHubInstanceIDCol = "instance_id"
|
GitHubInstanceIDCol = "instance_id"
|
||||||
GitHubClientIDCol = "client_id"
|
GitHubClientIDCol = "client_id"
|
||||||
@ -206,6 +216,19 @@ func newIDPTemplateProjection(ctx context.Context, config crdb.StatementHandlerC
|
|||||||
IDPTemplateJWTSuffix,
|
IDPTemplateJWTSuffix,
|
||||||
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys()),
|
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys()),
|
||||||
),
|
),
|
||||||
|
crdb.NewSuffixedTable([]*crdb.Column{
|
||||||
|
crdb.NewColumn(AzureADIDCol, crdb.ColumnTypeText),
|
||||||
|
crdb.NewColumn(AzureADInstanceIDCol, crdb.ColumnTypeText),
|
||||||
|
crdb.NewColumn(AzureADClientIDCol, crdb.ColumnTypeText),
|
||||||
|
crdb.NewColumn(AzureADClientSecretCol, crdb.ColumnTypeJSONB),
|
||||||
|
crdb.NewColumn(AzureADScopesCol, crdb.ColumnTypeText, crdb.Nullable()),
|
||||||
|
crdb.NewColumn(AzureADTenantCol, crdb.ColumnTypeText, crdb.Nullable()),
|
||||||
|
crdb.NewColumn(AzureADIsEmailVerified, crdb.ColumnTypeBool, crdb.Default(false)),
|
||||||
|
},
|
||||||
|
crdb.NewPrimaryKey(AzureADInstanceIDCol, AzureADIDCol),
|
||||||
|
IDPTemplateAzureADSuffix,
|
||||||
|
crdb.WithForeignKey(crdb.NewForeignKeyOfPublicKeys()),
|
||||||
|
),
|
||||||
crdb.NewSuffixedTable([]*crdb.Column{
|
crdb.NewSuffixedTable([]*crdb.Column{
|
||||||
crdb.NewColumn(GitHubIDCol, crdb.ColumnTypeText),
|
crdb.NewColumn(GitHubIDCol, crdb.ColumnTypeText),
|
||||||
crdb.NewColumn(GitHubInstanceIDCol, crdb.ColumnTypeText),
|
crdb.NewColumn(GitHubInstanceIDCol, crdb.ColumnTypeText),
|
||||||
@ -352,6 +375,14 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
|
|||||||
Event: instance.IDPJWTConfigChangedEventType,
|
Event: instance.IDPJWTConfigChangedEventType,
|
||||||
Reduce: p.reduceOldJWTConfigChanged,
|
Reduce: p.reduceOldJWTConfigChanged,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Event: instance.AzureADIDPAddedEventType,
|
||||||
|
Reduce: p.reduceAzureADIDPAdded,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: instance.AzureADIDPChangedEventType,
|
||||||
|
Reduce: p.reduceAzureADIDPChanged,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Event: instance.GitHubIDPAddedEventType,
|
Event: instance.GitHubIDPAddedEventType,
|
||||||
Reduce: p.reduceGitHubIDPAdded,
|
Reduce: p.reduceGitHubIDPAdded,
|
||||||
@ -429,7 +460,6 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
|
|||||||
Event: org.OIDCIDPChangedEventType,
|
Event: org.OIDCIDPChangedEventType,
|
||||||
Reduce: p.reduceOIDCIDPChanged,
|
Reduce: p.reduceOIDCIDPChanged,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
Event: org.JWTIDPAddedEventType,
|
Event: org.JWTIDPAddedEventType,
|
||||||
Reduce: p.reduceJWTIDPAdded,
|
Reduce: p.reduceJWTIDPAdded,
|
||||||
@ -462,6 +492,14 @@ func (p *idpTemplateProjection) reducers() []handler.AggregateReducer {
|
|||||||
Event: org.IDPJWTConfigChangedEventType,
|
Event: org.IDPJWTConfigChangedEventType,
|
||||||
Reduce: p.reduceOldJWTConfigChanged,
|
Reduce: p.reduceOldJWTConfigChanged,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Event: org.AzureADIDPAddedEventType,
|
||||||
|
Reduce: p.reduceAzureADIDPAdded,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Event: org.AzureADIDPChangedEventType,
|
||||||
|
Reduce: p.reduceAzureADIDPChanged,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Event: org.GitHubIDPAddedEventType,
|
Event: org.GitHubIDPAddedEventType,
|
||||||
Reduce: p.reduceGitHubIDPAdded,
|
Reduce: p.reduceGitHubIDPAdded,
|
||||||
@ -1049,6 +1087,96 @@ func (p *idpTemplateProjection) reduceOldJWTConfigChanged(event eventstore.Event
|
|||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *idpTemplateProjection) reduceAzureADIDPAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||||
|
var idpEvent idp.AzureADIDPAddedEvent
|
||||||
|
var idpOwnerType domain.IdentityProviderType
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.AzureADIDPAddedEvent:
|
||||||
|
idpEvent = e.AzureADIDPAddedEvent
|
||||||
|
idpOwnerType = domain.IdentityProviderTypeOrg
|
||||||
|
case *instance.AzureADIDPAddedEvent:
|
||||||
|
idpEvent = e.AzureADIDPAddedEvent
|
||||||
|
idpOwnerType = domain.IdentityProviderTypeSystem
|
||||||
|
default:
|
||||||
|
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-x9a022b", "reduce.wrong.event.type %v", []eventstore.EventType{org.AzureADIDPAddedEventType, instance.AzureADIDPAddedEventType})
|
||||||
|
}
|
||||||
|
|
||||||
|
return crdb.NewMultiStatement(
|
||||||
|
&idpEvent,
|
||||||
|
crdb.AddCreateStatement(
|
||||||
|
[]handler.Column{
|
||||||
|
handler.NewCol(IDPTemplateIDCol, idpEvent.ID),
|
||||||
|
handler.NewCol(IDPTemplateCreationDateCol, idpEvent.CreationDate()),
|
||||||
|
handler.NewCol(IDPTemplateChangeDateCol, idpEvent.CreationDate()),
|
||||||
|
handler.NewCol(IDPTemplateSequenceCol, idpEvent.Sequence()),
|
||||||
|
handler.NewCol(IDPTemplateResourceOwnerCol, idpEvent.Aggregate().ResourceOwner),
|
||||||
|
handler.NewCol(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
|
||||||
|
handler.NewCol(IDPTemplateStateCol, domain.IDPStateActive),
|
||||||
|
handler.NewCol(IDPTemplateNameCol, idpEvent.Name),
|
||||||
|
handler.NewCol(IDPTemplateOwnerTypeCol, idpOwnerType),
|
||||||
|
handler.NewCol(IDPTemplateTypeCol, domain.IDPTypeAzureAD),
|
||||||
|
handler.NewCol(IDPTemplateIsCreationAllowedCol, idpEvent.IsCreationAllowed),
|
||||||
|
handler.NewCol(IDPTemplateIsLinkingAllowedCol, idpEvent.IsLinkingAllowed),
|
||||||
|
handler.NewCol(IDPTemplateIsAutoCreationCol, idpEvent.IsAutoCreation),
|
||||||
|
handler.NewCol(IDPTemplateIsAutoUpdateCol, idpEvent.IsAutoUpdate),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
crdb.AddCreateStatement(
|
||||||
|
[]handler.Column{
|
||||||
|
handler.NewCol(AzureADIDCol, idpEvent.ID),
|
||||||
|
handler.NewCol(AzureADInstanceIDCol, idpEvent.Aggregate().InstanceID),
|
||||||
|
handler.NewCol(AzureADClientIDCol, idpEvent.ClientID),
|
||||||
|
handler.NewCol(AzureADClientSecretCol, idpEvent.ClientSecret),
|
||||||
|
handler.NewCol(AzureADScopesCol, database.StringArray(idpEvent.Scopes)),
|
||||||
|
handler.NewCol(AzureADTenantCol, idpEvent.Tenant),
|
||||||
|
handler.NewCol(AzureADIsEmailVerified, idpEvent.IsEmailVerified),
|
||||||
|
},
|
||||||
|
crdb.WithTableSuffix(IDPTemplateAzureADSuffix),
|
||||||
|
),
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *idpTemplateProjection) reduceAzureADIDPChanged(event eventstore.Event) (*handler.Statement, error) {
|
||||||
|
var idpEvent idp.AzureADIDPChangedEvent
|
||||||
|
switch e := event.(type) {
|
||||||
|
case *org.AzureADIDPChangedEvent:
|
||||||
|
idpEvent = e.AzureADIDPChangedEvent
|
||||||
|
case *instance.AzureADIDPChangedEvent:
|
||||||
|
idpEvent = e.AzureADIDPChangedEvent
|
||||||
|
default:
|
||||||
|
return nil, errors.ThrowInvalidArgumentf(nil, "HANDL-p1582ks", "reduce.wrong.event.type %v", []eventstore.EventType{org.AzureADIDPChangedEventType, instance.AzureADIDPChangedEventType})
|
||||||
|
}
|
||||||
|
|
||||||
|
ops := make([]func(eventstore.Event) crdb.Exec, 0, 2)
|
||||||
|
ops = append(ops,
|
||||||
|
crdb.AddUpdateStatement(
|
||||||
|
reduceIDPChangedTemplateColumns(idpEvent.Name, idpEvent.CreationDate(), idpEvent.Sequence(), idpEvent.OptionChanges),
|
||||||
|
[]handler.Condition{
|
||||||
|
handler.NewCond(IDPTemplateIDCol, idpEvent.ID),
|
||||||
|
handler.NewCond(IDPTemplateInstanceIDCol, idpEvent.Aggregate().InstanceID),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
githubCols := reduceAzureADIDPChangedColumns(idpEvent)
|
||||||
|
if len(githubCols) > 0 {
|
||||||
|
ops = append(ops,
|
||||||
|
crdb.AddUpdateStatement(
|
||||||
|
githubCols,
|
||||||
|
[]handler.Condition{
|
||||||
|
handler.NewCond(AzureADIDCol, idpEvent.ID),
|
||||||
|
handler.NewCond(AzureADInstanceIDCol, idpEvent.Aggregate().InstanceID),
|
||||||
|
},
|
||||||
|
crdb.WithTableSuffix(IDPTemplateAzureADSuffix),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return crdb.NewMultiStatement(
|
||||||
|
&idpEvent,
|
||||||
|
ops...,
|
||||||
|
), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *idpTemplateProjection) reduceGitHubIDPAdded(event eventstore.Event) (*handler.Statement, error) {
|
func (p *idpTemplateProjection) reduceGitHubIDPAdded(event eventstore.Event) (*handler.Statement, error) {
|
||||||
var idpEvent idp.GitHubIDPAddedEvent
|
var idpEvent idp.GitHubIDPAddedEvent
|
||||||
var idpOwnerType domain.IdentityProviderType
|
var idpOwnerType domain.IdentityProviderType
|
||||||
@ -1723,6 +1851,26 @@ func reduceJWTIDPChangedColumns(idpEvent idp.JWTIDPChangedEvent) []handler.Colum
|
|||||||
return jwtCols
|
return jwtCols
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func reduceAzureADIDPChangedColumns(idpEvent idp.AzureADIDPChangedEvent) []handler.Column {
|
||||||
|
azureADCols := make([]handler.Column, 0, 5)
|
||||||
|
if idpEvent.ClientID != nil {
|
||||||
|
azureADCols = append(azureADCols, handler.NewCol(AzureADClientIDCol, *idpEvent.ClientID))
|
||||||
|
}
|
||||||
|
if idpEvent.ClientSecret != nil {
|
||||||
|
azureADCols = append(azureADCols, handler.NewCol(AzureADClientSecretCol, *idpEvent.ClientSecret))
|
||||||
|
}
|
||||||
|
if idpEvent.Scopes != nil {
|
||||||
|
azureADCols = append(azureADCols, handler.NewCol(AzureADScopesCol, database.StringArray(idpEvent.Scopes)))
|
||||||
|
}
|
||||||
|
if idpEvent.Tenant != nil {
|
||||||
|
azureADCols = append(azureADCols, handler.NewCol(AzureADTenantCol, *idpEvent.Tenant))
|
||||||
|
}
|
||||||
|
if idpEvent.IsEmailVerified != nil {
|
||||||
|
azureADCols = append(azureADCols, handler.NewCol(AzureADIsEmailVerified, *idpEvent.IsEmailVerified))
|
||||||
|
}
|
||||||
|
return azureADCols
|
||||||
|
}
|
||||||
|
|
||||||
func reduceGitHubIDPChangedColumns(idpEvent idp.GitHubIDPChangedEvent) []handler.Column {
|
func reduceGitHubIDPChangedColumns(idpEvent idp.GitHubIDPChangedEvent) []handler.Column {
|
||||||
oauthCols := make([]handler.Column, 0, 3)
|
oauthCols := make([]handler.Column, 0, 3)
|
||||||
if idpEvent.ClientID != nil {
|
if idpEvent.ClientID != nil {
|
||||||
|
@ -410,6 +410,330 @@ func TestIDPTemplateProjection_reducesOAuth(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIDPTemplateProjection_reducesAzureAD(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
event func(t *testing.T) eventstore.Event
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
reduce func(event eventstore.Event) (*handler.Statement, error)
|
||||||
|
want wantReduce
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "instance reduceAzureADIDPAdded minimal",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(instance.AzureADIDPAddedEventType),
|
||||||
|
instance.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"id": "idp-id",
|
||||||
|
"name": "name",
|
||||||
|
"client_id": "client_id",
|
||||||
|
"client_secret": {
|
||||||
|
"cryptoType": 0,
|
||||||
|
"algorithm": "RSA-265",
|
||||||
|
"keyId": "key-id"
|
||||||
|
}
|
||||||
|
}`),
|
||||||
|
), instance.AzureADIDPAddedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&idpTemplateProjection{}).reduceAzureADIDPAdded,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("instance"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: idpTemplateInsertStmt,
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-id",
|
||||||
|
anyArg{},
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
"ro-id",
|
||||||
|
"instance-id",
|
||||||
|
domain.IDPStateActive,
|
||||||
|
"name",
|
||||||
|
domain.IdentityProviderTypeSystem,
|
||||||
|
domain.IDPTypeAzureAD,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expectedStmt: "INSERT INTO projections.idp_templates3_azure (idp_id, instance_id, client_id, client_secret, scopes, tenant, is_email_verified) VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-id",
|
||||||
|
"instance-id",
|
||||||
|
"client_id",
|
||||||
|
anyArg{},
|
||||||
|
database.StringArray(nil),
|
||||||
|
"",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "instance reduceAzureADIDPAdded",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(instance.AzureADIDPAddedEventType),
|
||||||
|
instance.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"id": "idp-id",
|
||||||
|
"name": "name",
|
||||||
|
"client_id": "client_id",
|
||||||
|
"client_secret": {
|
||||||
|
"cryptoType": 0,
|
||||||
|
"algorithm": "RSA-265",
|
||||||
|
"keyId": "key-id"
|
||||||
|
},
|
||||||
|
"tenant": "tenant",
|
||||||
|
"isEmailVerified": true,
|
||||||
|
"scopes": ["profile"],
|
||||||
|
"isCreationAllowed": true,
|
||||||
|
"isLinkingAllowed": true,
|
||||||
|
"isAutoCreation": true,
|
||||||
|
"isAutoUpdate": true
|
||||||
|
}`),
|
||||||
|
), instance.AzureADIDPAddedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&idpTemplateProjection{}).reduceAzureADIDPAdded,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("instance"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: idpTemplateInsertStmt,
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-id",
|
||||||
|
anyArg{},
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
"ro-id",
|
||||||
|
"instance-id",
|
||||||
|
domain.IDPStateActive,
|
||||||
|
"name",
|
||||||
|
domain.IdentityProviderTypeSystem,
|
||||||
|
domain.IDPTypeAzureAD,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expectedStmt: "INSERT INTO projections.idp_templates3_azure (idp_id, instance_id, client_id, client_secret, scopes, tenant, is_email_verified) VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-id",
|
||||||
|
"instance-id",
|
||||||
|
"client_id",
|
||||||
|
anyArg{},
|
||||||
|
database.StringArray{"profile"},
|
||||||
|
"tenant",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "org reduceAzureADIDPAdded",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(org.AzureADIDPAddedEventType),
|
||||||
|
org.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"id": "idp-id",
|
||||||
|
"name": "name",
|
||||||
|
"client_id": "client_id",
|
||||||
|
"client_secret": {
|
||||||
|
"cryptoType": 0,
|
||||||
|
"algorithm": "RSA-265",
|
||||||
|
"keyId": "key-id"
|
||||||
|
},
|
||||||
|
"tenant": "tenant",
|
||||||
|
"isEmailVerified": true,
|
||||||
|
"scopes": ["profile"],
|
||||||
|
"isCreationAllowed": true,
|
||||||
|
"isLinkingAllowed": true,
|
||||||
|
"isAutoCreation": true,
|
||||||
|
"isAutoUpdate": true
|
||||||
|
}`),
|
||||||
|
), org.AzureADIDPAddedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&idpTemplateProjection{}).reduceAzureADIDPAdded,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("org"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: idpTemplateInsertStmt,
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-id",
|
||||||
|
anyArg{},
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
"ro-id",
|
||||||
|
"instance-id",
|
||||||
|
domain.IDPStateActive,
|
||||||
|
"name",
|
||||||
|
domain.IdentityProviderTypeOrg,
|
||||||
|
domain.IDPTypeAzureAD,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expectedStmt: "INSERT INTO projections.idp_templates3_azure (idp_id, instance_id, client_id, client_secret, scopes, tenant, is_email_verified) VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"idp-id",
|
||||||
|
"instance-id",
|
||||||
|
"client_id",
|
||||||
|
anyArg{},
|
||||||
|
database.StringArray{"profile"},
|
||||||
|
"tenant",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "instance reduceAzureADIDPChanged minimal",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(instance.AzureADIDPChangedEventType),
|
||||||
|
instance.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"id": "idp-id",
|
||||||
|
"isCreationAllowed": true,
|
||||||
|
"client_id": "id"
|
||||||
|
}`),
|
||||||
|
), instance.AzureADIDPChangedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&idpTemplateProjection{}).reduceAzureADIDPChanged,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("instance"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: idpTemplateUpdateMinimalStmt,
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
true,
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
"idp-id",
|
||||||
|
"instance-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expectedStmt: "UPDATE projections.idp_templates3_azure SET client_id = $1 WHERE (idp_id = $2) AND (instance_id = $3)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"id",
|
||||||
|
"idp-id",
|
||||||
|
"instance-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "instance reduceAzureADIDPChanged",
|
||||||
|
args: args{
|
||||||
|
event: getEvent(testEvent(
|
||||||
|
repository.EventType(instance.AzureADIDPChangedEventType),
|
||||||
|
instance.AggregateType,
|
||||||
|
[]byte(`{
|
||||||
|
"id": "idp-id",
|
||||||
|
"name": "name",
|
||||||
|
"client_id": "client_id",
|
||||||
|
"client_secret": {
|
||||||
|
"cryptoType": 0,
|
||||||
|
"algorithm": "RSA-265",
|
||||||
|
"keyId": "key-id"
|
||||||
|
},
|
||||||
|
"tenant": "tenant",
|
||||||
|
"isEmailVerified": true,
|
||||||
|
"scopes": ["profile"],
|
||||||
|
"isCreationAllowed": true,
|
||||||
|
"isLinkingAllowed": true,
|
||||||
|
"isAutoCreation": true,
|
||||||
|
"isAutoUpdate": true
|
||||||
|
}`),
|
||||||
|
), instance.AzureADIDPChangedEventMapper),
|
||||||
|
},
|
||||||
|
reduce: (&idpTemplateProjection{}).reduceAzureADIDPChanged,
|
||||||
|
want: wantReduce{
|
||||||
|
aggregateType: eventstore.AggregateType("instance"),
|
||||||
|
sequence: 15,
|
||||||
|
previousSequence: 10,
|
||||||
|
executer: &testExecuter{
|
||||||
|
executions: []execution{
|
||||||
|
{
|
||||||
|
expectedStmt: idpTemplateUpdateStmt,
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"name",
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
anyArg{},
|
||||||
|
uint64(15),
|
||||||
|
"idp-id",
|
||||||
|
"instance-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expectedStmt: "UPDATE projections.idp_templates3_azure SET (client_id, client_secret, scopes, tenant, is_email_verified) = ($1, $2, $3, $4, $5) WHERE (idp_id = $6) AND (instance_id = $7)",
|
||||||
|
expectedArgs: []interface{}{
|
||||||
|
"client_id",
|
||||||
|
anyArg{},
|
||||||
|
database.StringArray{"profile"},
|
||||||
|
"tenant",
|
||||||
|
true,
|
||||||
|
"idp-id",
|
||||||
|
"instance-id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
event := baseEvent(t)
|
||||||
|
got, err := tt.reduce(event)
|
||||||
|
if !errors.IsErrorInvalidArgument(err) {
|
||||||
|
t.Errorf("no wrong event mapping: %v, got: %v", err, got)
|
||||||
|
}
|
||||||
|
|
||||||
|
event = tt.args.event(t)
|
||||||
|
got, err = tt.reduce(event)
|
||||||
|
assertReduce(t, got, err, IDPTemplateTable, tt.want)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestIDPTemplateProjection_reducesGitHub(t *testing.T) {
|
func TestIDPTemplateProjection_reducesGitHub(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
event func(t *testing.T) eventstore.Event
|
event func(t *testing.T) eventstore.Event
|
||||||
|
164
internal/repository/idp/azuread.go
Normal file
164
internal/repository/idp/azuread.go
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
package idp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/zitadel/zitadel/internal/crypto"
|
||||||
|
"github.com/zitadel/zitadel/internal/errors"
|
||||||
|
"github.com/zitadel/zitadel/internal/eventstore"
|
||||||
|
"github.com/zitadel/zitadel/internal/eventstore/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AzureADIDPAddedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
ClientID string `json:"client_id,omitempty"`
|
||||||
|
ClientSecret *crypto.CryptoValue `json:"client_secret,omitempty"`
|
||||||
|
Scopes []string `json:"scopes,omitempty"`
|
||||||
|
Tenant string `json:"tenant,omitempty"`
|
||||||
|
IsEmailVerified bool `json:"isEmailVerified,omitempty"`
|
||||||
|
Options
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAzureADIDPAddedEvent(
|
||||||
|
base *eventstore.BaseEvent,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
clientID string,
|
||||||
|
clientSecret *crypto.CryptoValue,
|
||||||
|
scopes []string,
|
||||||
|
tenant string,
|
||||||
|
isEmailVerified bool,
|
||||||
|
options Options,
|
||||||
|
) *AzureADIDPAddedEvent {
|
||||||
|
return &AzureADIDPAddedEvent{
|
||||||
|
BaseEvent: *base,
|
||||||
|
ID: id,
|
||||||
|
Name: name,
|
||||||
|
ClientID: clientID,
|
||||||
|
ClientSecret: clientSecret,
|
||||||
|
Scopes: scopes,
|
||||||
|
Tenant: tenant,
|
||||||
|
IsEmailVerified: isEmailVerified,
|
||||||
|
Options: options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *AzureADIDPAddedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *AzureADIDPAddedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AzureADIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e := &AzureADIDPAddedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal(event.Data, e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "IDP-Grh2g", "unable to unmarshal event")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type AzureADIDPChangedEvent struct {
|
||||||
|
eventstore.BaseEvent `json:"-"`
|
||||||
|
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
ClientID *string `json:"client_id,omitempty"`
|
||||||
|
ClientSecret *crypto.CryptoValue `json:"client_secret,omitempty"`
|
||||||
|
Scopes []string `json:"scopes,omitempty"`
|
||||||
|
Tenant *string `json:"tenant,omitempty"`
|
||||||
|
IsEmailVerified *bool `json:"isEmailVerified,omitempty"`
|
||||||
|
OptionChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAzureADIDPChangedEvent(
|
||||||
|
base *eventstore.BaseEvent,
|
||||||
|
id string,
|
||||||
|
changes []AzureADIDPChanges,
|
||||||
|
) (*AzureADIDPChangedEvent, error) {
|
||||||
|
if len(changes) == 0 {
|
||||||
|
return nil, errors.ThrowPreconditionFailed(nil, "IDP-BH3dl", "Errors.NoChangesFound")
|
||||||
|
}
|
||||||
|
changedEvent := &AzureADIDPChangedEvent{
|
||||||
|
BaseEvent: *base,
|
||||||
|
ID: id,
|
||||||
|
}
|
||||||
|
for _, change := range changes {
|
||||||
|
change(changedEvent)
|
||||||
|
}
|
||||||
|
return changedEvent, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type AzureADIDPChanges func(*AzureADIDPChangedEvent)
|
||||||
|
|
||||||
|
func ChangeAzureADName(name string) func(*AzureADIDPChangedEvent) {
|
||||||
|
return func(e *AzureADIDPChangedEvent) {
|
||||||
|
e.Name = &name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangeAzureADClientID(clientID string) func(*AzureADIDPChangedEvent) {
|
||||||
|
return func(e *AzureADIDPChangedEvent) {
|
||||||
|
e.ClientID = &clientID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangeAzureADClientSecret(clientSecret *crypto.CryptoValue) func(*AzureADIDPChangedEvent) {
|
||||||
|
return func(e *AzureADIDPChangedEvent) {
|
||||||
|
e.ClientSecret = clientSecret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangeAzureADOptions(options OptionChanges) func(*AzureADIDPChangedEvent) {
|
||||||
|
return func(e *AzureADIDPChangedEvent) {
|
||||||
|
e.OptionChanges = options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangeAzureADScopes(scopes []string) func(*AzureADIDPChangedEvent) {
|
||||||
|
return func(e *AzureADIDPChangedEvent) {
|
||||||
|
e.Scopes = scopes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangeAzureADTenant(tenant string) func(*AzureADIDPChangedEvent) {
|
||||||
|
return func(e *AzureADIDPChangedEvent) {
|
||||||
|
e.Tenant = &tenant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangeAzureADIsEmailVerified(isEmailVerified bool) func(*AzureADIDPChangedEvent) {
|
||||||
|
return func(e *AzureADIDPChangedEvent) {
|
||||||
|
e.IsEmailVerified = &isEmailVerified
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *AzureADIDPChangedEvent) Data() interface{} {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *AzureADIDPChangedEvent) UniqueConstraints() []*eventstore.EventUniqueConstraint {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AzureADIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e := &AzureADIDPChangedEvent{
|
||||||
|
BaseEvent: *eventstore.BaseEventFromRepo(event),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := json.Unmarshal(event.Data, e)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.ThrowInternal(err, "IDP-D3gjzh", "unable to unmarshal event")
|
||||||
|
}
|
||||||
|
|
||||||
|
return e, nil
|
||||||
|
}
|
@ -76,6 +76,8 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
|||||||
RegisterFilterEventMapper(AggregateType, OIDCIDPChangedEventType, OIDCIDPChangedEventMapper).
|
RegisterFilterEventMapper(AggregateType, OIDCIDPChangedEventType, OIDCIDPChangedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, JWTIDPAddedEventType, JWTIDPAddedEventMapper).
|
RegisterFilterEventMapper(AggregateType, JWTIDPAddedEventType, JWTIDPAddedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, JWTIDPChangedEventType, JWTIDPChangedEventMapper).
|
RegisterFilterEventMapper(AggregateType, JWTIDPChangedEventType, JWTIDPChangedEventMapper).
|
||||||
|
RegisterFilterEventMapper(AggregateType, AzureADIDPAddedEventType, AzureADIDPAddedEventMapper).
|
||||||
|
RegisterFilterEventMapper(AggregateType, AzureADIDPChangedEventType, AzureADIDPChangedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, GitHubIDPAddedEventType, GitHubIDPAddedEventMapper).
|
RegisterFilterEventMapper(AggregateType, GitHubIDPAddedEventType, GitHubIDPAddedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, GitHubIDPChangedEventType, GitHubIDPChangedEventMapper).
|
RegisterFilterEventMapper(AggregateType, GitHubIDPChangedEventType, GitHubIDPChangedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, GitHubEnterpriseIDPAddedEventType, GitHubEnterpriseIDPAddedEventMapper).
|
RegisterFilterEventMapper(AggregateType, GitHubEnterpriseIDPAddedEventType, GitHubEnterpriseIDPAddedEventMapper).
|
||||||
|
@ -16,6 +16,8 @@ const (
|
|||||||
OIDCIDPChangedEventType eventstore.EventType = "instance.idp.oidc.changed"
|
OIDCIDPChangedEventType eventstore.EventType = "instance.idp.oidc.changed"
|
||||||
JWTIDPAddedEventType eventstore.EventType = "instance.idp.jwt.added"
|
JWTIDPAddedEventType eventstore.EventType = "instance.idp.jwt.added"
|
||||||
JWTIDPChangedEventType eventstore.EventType = "instance.idp.jwt.changed"
|
JWTIDPChangedEventType eventstore.EventType = "instance.idp.jwt.changed"
|
||||||
|
AzureADIDPAddedEventType eventstore.EventType = "instance.idp.azure.added"
|
||||||
|
AzureADIDPChangedEventType eventstore.EventType = "instance.idp.azure.changed"
|
||||||
GitHubIDPAddedEventType eventstore.EventType = "instance.idp.github.added"
|
GitHubIDPAddedEventType eventstore.EventType = "instance.idp.github.added"
|
||||||
GitHubIDPChangedEventType eventstore.EventType = "instance.idp.github.changed"
|
GitHubIDPChangedEventType eventstore.EventType = "instance.idp.github.changed"
|
||||||
GitHubEnterpriseIDPAddedEventType eventstore.EventType = "instance.idp.github_enterprise.added"
|
GitHubEnterpriseIDPAddedEventType eventstore.EventType = "instance.idp.github_enterprise.added"
|
||||||
@ -271,6 +273,86 @@ func JWTIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error)
|
|||||||
return &JWTIDPChangedEvent{JWTIDPChangedEvent: *e.(*idp.JWTIDPChangedEvent)}, nil
|
return &JWTIDPChangedEvent{JWTIDPChangedEvent: *e.(*idp.JWTIDPChangedEvent)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AzureADIDPAddedEvent struct {
|
||||||
|
idp.AzureADIDPAddedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAzureADIDPAddedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
clientID string,
|
||||||
|
clientSecret *crypto.CryptoValue,
|
||||||
|
scopes []string,
|
||||||
|
tenant string,
|
||||||
|
isEmailVerified bool,
|
||||||
|
options idp.Options,
|
||||||
|
) *AzureADIDPAddedEvent {
|
||||||
|
|
||||||
|
return &AzureADIDPAddedEvent{
|
||||||
|
AzureADIDPAddedEvent: *idp.NewAzureADIDPAddedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
AzureADIDPAddedEventType,
|
||||||
|
),
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
clientID,
|
||||||
|
clientSecret,
|
||||||
|
scopes,
|
||||||
|
tenant,
|
||||||
|
isEmailVerified,
|
||||||
|
options,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AzureADIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := idp.AzureADIDPAddedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &AzureADIDPAddedEvent{AzureADIDPAddedEvent: *e.(*idp.AzureADIDPAddedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type AzureADIDPChangedEvent struct {
|
||||||
|
idp.AzureADIDPChangedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAzureADIDPChangedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
id string,
|
||||||
|
changes []idp.AzureADIDPChanges,
|
||||||
|
) (*AzureADIDPChangedEvent, error) {
|
||||||
|
|
||||||
|
changedEvent, err := idp.NewAzureADIDPChangedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
AzureADIDPChangedEventType,
|
||||||
|
),
|
||||||
|
id,
|
||||||
|
changes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &AzureADIDPChangedEvent{AzureADIDPChangedEvent: *changedEvent}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AzureADIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := idp.AzureADIDPChangedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &AzureADIDPChangedEvent{AzureADIDPChangedEvent: *e.(*idp.AzureADIDPChangedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type GitHubIDPAddedEvent struct {
|
type GitHubIDPAddedEvent struct {
|
||||||
idp.GitHubIDPAddedEvent
|
idp.GitHubIDPAddedEvent
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,8 @@ func RegisterEventMappers(es *eventstore.Eventstore) {
|
|||||||
RegisterFilterEventMapper(AggregateType, OIDCIDPChangedEventType, OIDCIDPChangedEventMapper).
|
RegisterFilterEventMapper(AggregateType, OIDCIDPChangedEventType, OIDCIDPChangedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, JWTIDPAddedEventType, JWTIDPAddedEventMapper).
|
RegisterFilterEventMapper(AggregateType, JWTIDPAddedEventType, JWTIDPAddedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, JWTIDPChangedEventType, JWTIDPChangedEventMapper).
|
RegisterFilterEventMapper(AggregateType, JWTIDPChangedEventType, JWTIDPChangedEventMapper).
|
||||||
|
RegisterFilterEventMapper(AggregateType, AzureADIDPAddedEventType, AzureADIDPAddedEventMapper).
|
||||||
|
RegisterFilterEventMapper(AggregateType, AzureADIDPChangedEventType, AzureADIDPChangedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, GitHubIDPAddedEventType, GitHubIDPAddedEventMapper).
|
RegisterFilterEventMapper(AggregateType, GitHubIDPAddedEventType, GitHubIDPAddedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, GitHubIDPChangedEventType, GitHubIDPChangedEventMapper).
|
RegisterFilterEventMapper(AggregateType, GitHubIDPChangedEventType, GitHubIDPChangedEventMapper).
|
||||||
RegisterFilterEventMapper(AggregateType, GitHubEnterpriseIDPAddedEventType, GitHubEnterpriseIDPAddedEventMapper).
|
RegisterFilterEventMapper(AggregateType, GitHubEnterpriseIDPAddedEventType, GitHubEnterpriseIDPAddedEventMapper).
|
||||||
|
@ -16,6 +16,8 @@ const (
|
|||||||
OIDCIDPChangedEventType eventstore.EventType = "org.idp.oidc.changed"
|
OIDCIDPChangedEventType eventstore.EventType = "org.idp.oidc.changed"
|
||||||
JWTIDPAddedEventType eventstore.EventType = "org.idp.jwt.added"
|
JWTIDPAddedEventType eventstore.EventType = "org.idp.jwt.added"
|
||||||
JWTIDPChangedEventType eventstore.EventType = "org.idp.jwt.changed"
|
JWTIDPChangedEventType eventstore.EventType = "org.idp.jwt.changed"
|
||||||
|
AzureADIDPAddedEventType eventstore.EventType = "org.idp.azure.added"
|
||||||
|
AzureADIDPChangedEventType eventstore.EventType = "org.idp.azure.changed"
|
||||||
GitHubIDPAddedEventType eventstore.EventType = "org.idp.github.added"
|
GitHubIDPAddedEventType eventstore.EventType = "org.idp.github.added"
|
||||||
GitHubIDPChangedEventType eventstore.EventType = "org.idp.github.changed"
|
GitHubIDPChangedEventType eventstore.EventType = "org.idp.github.changed"
|
||||||
GitHubEnterpriseIDPAddedEventType eventstore.EventType = "org.idp.github_enterprise.added"
|
GitHubEnterpriseIDPAddedEventType eventstore.EventType = "org.idp.github_enterprise.added"
|
||||||
@ -271,6 +273,86 @@ func JWTIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error)
|
|||||||
return &JWTIDPChangedEvent{JWTIDPChangedEvent: *e.(*idp.JWTIDPChangedEvent)}, nil
|
return &JWTIDPChangedEvent{JWTIDPChangedEvent: *e.(*idp.JWTIDPChangedEvent)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AzureADIDPAddedEvent struct {
|
||||||
|
idp.AzureADIDPAddedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAzureADIDPAddedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
clientID string,
|
||||||
|
clientSecret *crypto.CryptoValue,
|
||||||
|
scopes []string,
|
||||||
|
tenant string,
|
||||||
|
isEmailVerified bool,
|
||||||
|
options idp.Options,
|
||||||
|
) *AzureADIDPAddedEvent {
|
||||||
|
|
||||||
|
return &AzureADIDPAddedEvent{
|
||||||
|
AzureADIDPAddedEvent: *idp.NewAzureADIDPAddedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
AzureADIDPAddedEventType,
|
||||||
|
),
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
clientID,
|
||||||
|
clientSecret,
|
||||||
|
scopes,
|
||||||
|
tenant,
|
||||||
|
isEmailVerified,
|
||||||
|
options,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AzureADIDPAddedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := idp.AzureADIDPAddedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &AzureADIDPAddedEvent{AzureADIDPAddedEvent: *e.(*idp.AzureADIDPAddedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type AzureADIDPChangedEvent struct {
|
||||||
|
idp.AzureADIDPChangedEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAzureADIDPChangedEvent(
|
||||||
|
ctx context.Context,
|
||||||
|
aggregate *eventstore.Aggregate,
|
||||||
|
id string,
|
||||||
|
changes []idp.AzureADIDPChanges,
|
||||||
|
) (*AzureADIDPChangedEvent, error) {
|
||||||
|
|
||||||
|
changedEvent, err := idp.NewAzureADIDPChangedEvent(
|
||||||
|
eventstore.NewBaseEventForPush(
|
||||||
|
ctx,
|
||||||
|
aggregate,
|
||||||
|
AzureADIDPChangedEventType,
|
||||||
|
),
|
||||||
|
id,
|
||||||
|
changes,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &AzureADIDPChangedEvent{AzureADIDPChangedEvent: *changedEvent}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AzureADIDPChangedEventMapper(event *repository.Event) (eventstore.Event, error) {
|
||||||
|
e, err := idp.AzureADIDPChangedEventMapper(event)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &AzureADIDPChangedEvent{AzureADIDPChangedEvent: *e.(*idp.AzureADIDPChangedEvent)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
type GitHubIDPAddedEvent struct {
|
type GitHubIDPAddedEvent struct {
|
||||||
idp.GitHubIDPAddedEvent
|
idp.GitHubIDPAddedEvent
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
package idp
|
package idp
|
||||||
|
|
||||||
type IDPConfig = isIDP_Config
|
type IDPConfig = isIDP_Config
|
||||||
|
type IsAzureADTenantType = isAzureADTenant_Type
|
||||||
|
@ -1320,6 +1320,30 @@ service AdminService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a new Azure AD identity provider on the instance
|
||||||
|
rpc AddAzureADProvider(AddAzureADProviderRequest) returns (AddAzureADProviderResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/idps/azure"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "iam.idp.write"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change an existing Azure AD identity provider on the instance
|
||||||
|
rpc UpdateAzureADProvider(UpdateAzureADProviderRequest) returns (UpdateAzureADProviderResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
put: "/idps/azure/{id}"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "iam.idp.write"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Add a new GitHub identity provider on the instance
|
// Add a new GitHub identity provider on the instance
|
||||||
rpc AddGitHubProvider(AddGitHubProviderRequest) returns (AddGitHubProviderResponse) {
|
rpc AddGitHubProvider(AddGitHubProviderRequest) returns (AddGitHubProviderResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
@ -4525,6 +4549,39 @@ message UpdateJWTProviderResponse {
|
|||||||
zitadel.v1.ObjectDetails details = 1;
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AddAzureADProviderRequest {
|
||||||
|
string name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string client_id = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string client_secret = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
// if not provided the `common` tenant will be used
|
||||||
|
zitadel.idp.v1.AzureADTenant tenant = 4;
|
||||||
|
bool email_verified = 5;
|
||||||
|
repeated string scopes = 6 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
|
||||||
|
zitadel.idp.v1.Options provider_options = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddAzureADProviderResponse {
|
||||||
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
|
string id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateAzureADProviderRequest {
|
||||||
|
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string client_id = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
// client_secret will only be updated if provided
|
||||||
|
string client_secret = 4 [(validate.rules).string = {max_len: 200}];
|
||||||
|
// if not provided the `common` tenant will be used
|
||||||
|
zitadel.idp.v1.AzureADTenant tenant = 5;
|
||||||
|
bool email_verified = 6;
|
||||||
|
repeated string scopes = 7 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
|
||||||
|
zitadel.idp.v1.Options provider_options = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateAzureADProviderResponse {
|
||||||
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message AddGitHubProviderRequest {
|
message AddGitHubProviderRequest {
|
||||||
// GitHub will be used as default, if no name is provided
|
// GitHub will be used as default, if no name is provided
|
||||||
string name = 1 [(validate.rules).string = {max_len: 200}];
|
string name = 1 [(validate.rules).string = {max_len: 200}];
|
||||||
|
@ -271,8 +271,10 @@ message ProviderConfig {
|
|||||||
GitHubEnterpriseServerConfig github_es = 8;
|
GitHubEnterpriseServerConfig github_es = 8;
|
||||||
GitLabConfig gitlab = 9;
|
GitLabConfig gitlab = 9;
|
||||||
GitLabSelfHostedConfig gitlab_self_hosted = 10;
|
GitLabSelfHostedConfig gitlab_self_hosted = 10;
|
||||||
|
AzureADConfig azure_ad = 11;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message OAuthConfig {
|
message OAuthConfig {
|
||||||
string client_id = 1;
|
string client_id = 1;
|
||||||
string authorization_endpoint = 2;
|
string authorization_endpoint = 2;
|
||||||
@ -329,6 +331,13 @@ message LDAPConfig {
|
|||||||
Options provider_options = 9;
|
Options provider_options = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AzureADConfig {
|
||||||
|
string client_id = 1;
|
||||||
|
AzureADTenant tenant = 2;
|
||||||
|
bool email_verified = 3;
|
||||||
|
repeated string scopes = 4;
|
||||||
|
}
|
||||||
|
|
||||||
message Options {
|
message Options {
|
||||||
bool is_linking_allowed = 1;
|
bool is_linking_allowed = 1;
|
||||||
bool is_creation_allowed = 2;
|
bool is_creation_allowed = 2;
|
||||||
@ -352,3 +361,15 @@ message LDAPAttributes {
|
|||||||
string profile_attribute = 13 [(validate.rules).string = {max_len: 200}];
|
string profile_attribute = 13 [(validate.rules).string = {max_len: 200}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum AzureADTenantType {
|
||||||
|
AZURE_AD_TENANT_TYPE_COMMON = 0;
|
||||||
|
AZURE_AD_TENANT_TYPE_ORGANISATIONS = 1;
|
||||||
|
AZURE_AD_TENANT_TYPE_CONSUMERS = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AzureADTenant {
|
||||||
|
oneof type {
|
||||||
|
AzureADTenantType tenant_type = 1;
|
||||||
|
string tenant_id = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6536,6 +6536,30 @@ service ManagementService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a new Azure AD identity provider in the organisation
|
||||||
|
rpc AddAzureADProvider(AddAzureADProviderRequest) returns (AddAzureADProviderResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/idps/azure"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "org.idp.write"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change an existing Azure AD identity provider in the organisation
|
||||||
|
rpc UpdateAzureADProvider(UpdateAzureADProviderRequest) returns (UpdateAzureADProviderResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
put: "/idps/azure/{id}"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
|
||||||
|
option (zitadel.v1.auth_option) = {
|
||||||
|
permission: "org.idp.write"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Add a new GitHub identity provider in the organization
|
// Add a new GitHub identity provider in the organization
|
||||||
rpc AddGitHubProvider(AddGitHubProviderRequest) returns (AddGitHubProviderResponse) {
|
rpc AddGitHubProvider(AddGitHubProviderRequest) returns (AddGitHubProviderResponse) {
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
@ -11199,6 +11223,39 @@ message UpdateJWTProviderResponse {
|
|||||||
zitadel.v1.ObjectDetails details = 1;
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message AddAzureADProviderRequest {
|
||||||
|
string name = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string client_id = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string client_secret = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
// if not provided the `common` tenant will be used
|
||||||
|
zitadel.idp.v1.AzureADTenant tenant = 4;
|
||||||
|
bool email_verified = 5;
|
||||||
|
repeated string scopes = 6 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
|
||||||
|
zitadel.idp.v1.Options provider_options = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddAzureADProviderResponse {
|
||||||
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
|
string id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateAzureADProviderRequest {
|
||||||
|
string id = 1 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string name = 2 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
string client_id = 3 [(validate.rules).string = {min_len: 1, max_len: 200}];
|
||||||
|
// client_secret will only be updated if provided
|
||||||
|
string client_secret = 4 [(validate.rules).string = {max_len: 200}];
|
||||||
|
// if not provided the `common` tenant will be used
|
||||||
|
zitadel.idp.v1.AzureADTenant tenant = 5;
|
||||||
|
bool email_verified = 6;
|
||||||
|
repeated string scopes = 7 [(validate.rules).repeated = {max_items: 20, items: {string: {min_len: 1, max_len: 100}}}];
|
||||||
|
zitadel.idp.v1.Options provider_options = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateAzureADProviderResponse {
|
||||||
|
zitadel.v1.ObjectDetails details = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message AddGitHubProviderRequest {
|
message AddGitHubProviderRequest {
|
||||||
// GitHub will be used as default, if no name is provided
|
// GitHub will be used as default, if no name is provided
|
||||||
string name = 1 [(validate.rules).string = {max_len: 200}];
|
string name = 1 [(validate.rules).string = {max_len: 200}];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user