mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-15 20:38:00 +00:00
370 lines
12 KiB
Go
370 lines
12 KiB
Go
|
package idp
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
|
||
|
"github.com/crewjam/saml"
|
||
|
"github.com/muhlemmer/gu"
|
||
|
"google.golang.org/protobuf/types/known/durationpb"
|
||
|
|
||
|
"github.com/zitadel/zitadel/internal/api/grpc/object/v2"
|
||
|
"github.com/zitadel/zitadel/internal/domain"
|
||
|
"github.com/zitadel/zitadel/internal/idp/providers/azuread"
|
||
|
"github.com/zitadel/zitadel/internal/query"
|
||
|
idp_rp "github.com/zitadel/zitadel/internal/repository/idp"
|
||
|
idp_pb "github.com/zitadel/zitadel/pkg/grpc/idp/v2"
|
||
|
)
|
||
|
|
||
|
func (s *Server) GetIDPByID(ctx context.Context, req *idp_pb.GetIDPByIDRequest) (*idp_pb.GetIDPByIDResponse, error) {
|
||
|
idp, err := s.query.IDPTemplateByID(ctx, true, req.Id, false, s.checkPermission)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return &idp_pb.GetIDPByIDResponse{Idp: idpToPb(idp)}, nil
|
||
|
}
|
||
|
|
||
|
func idpToPb(idp *query.IDPTemplate) *idp_pb.IDP {
|
||
|
return &idp_pb.IDP{
|
||
|
Id: idp.ID,
|
||
|
Details: object.DomainToDetailsPb(
|
||
|
&domain.ObjectDetails{
|
||
|
Sequence: idp.Sequence,
|
||
|
EventDate: idp.ChangeDate,
|
||
|
ResourceOwner: idp.ResourceOwner,
|
||
|
}),
|
||
|
State: idpStateToPb(idp.State),
|
||
|
Name: idp.Name,
|
||
|
Type: idpTypeToPb(idp.Type),
|
||
|
Config: configToPb(idp),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func idpStateToPb(state domain.IDPState) idp_pb.IDPState {
|
||
|
switch state {
|
||
|
case domain.IDPStateActive:
|
||
|
return idp_pb.IDPState_IDP_STATE_ACTIVE
|
||
|
case domain.IDPStateInactive:
|
||
|
return idp_pb.IDPState_IDP_STATE_INACTIVE
|
||
|
case domain.IDPStateUnspecified:
|
||
|
return idp_pb.IDPState_IDP_STATE_UNSPECIFIED
|
||
|
case domain.IDPStateMigrated:
|
||
|
return idp_pb.IDPState_IDP_STATE_MIGRATED
|
||
|
case domain.IDPStateRemoved:
|
||
|
return idp_pb.IDPState_IDP_STATE_REMOVED
|
||
|
default:
|
||
|
return idp_pb.IDPState_IDP_STATE_UNSPECIFIED
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func idpTypeToPb(idpType domain.IDPType) idp_pb.IDPType {
|
||
|
switch idpType {
|
||
|
case domain.IDPTypeOIDC:
|
||
|
return idp_pb.IDPType_IDP_TYPE_OIDC
|
||
|
case domain.IDPTypeJWT:
|
||
|
return idp_pb.IDPType_IDP_TYPE_JWT
|
||
|
case domain.IDPTypeOAuth:
|
||
|
return idp_pb.IDPType_IDP_TYPE_OAUTH
|
||
|
case domain.IDPTypeLDAP:
|
||
|
return idp_pb.IDPType_IDP_TYPE_LDAP
|
||
|
case domain.IDPTypeAzureAD:
|
||
|
return idp_pb.IDPType_IDP_TYPE_AZURE_AD
|
||
|
case domain.IDPTypeGitHub:
|
||
|
return idp_pb.IDPType_IDP_TYPE_GITHUB
|
||
|
case domain.IDPTypeGitHubEnterprise:
|
||
|
return idp_pb.IDPType_IDP_TYPE_GITHUB_ES
|
||
|
case domain.IDPTypeGitLab:
|
||
|
return idp_pb.IDPType_IDP_TYPE_GITLAB
|
||
|
case domain.IDPTypeGitLabSelfHosted:
|
||
|
return idp_pb.IDPType_IDP_TYPE_GITLAB_SELF_HOSTED
|
||
|
case domain.IDPTypeGoogle:
|
||
|
return idp_pb.IDPType_IDP_TYPE_GOOGLE
|
||
|
case domain.IDPTypeApple:
|
||
|
return idp_pb.IDPType_IDP_TYPE_APPLE
|
||
|
case domain.IDPTypeSAML:
|
||
|
return idp_pb.IDPType_IDP_TYPE_SAML
|
||
|
case domain.IDPTypeUnspecified:
|
||
|
return idp_pb.IDPType_IDP_TYPE_UNSPECIFIED
|
||
|
default:
|
||
|
return idp_pb.IDPType_IDP_TYPE_UNSPECIFIED
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func configToPb(config *query.IDPTemplate) *idp_pb.IDPConfig {
|
||
|
idpConfig := &idp_pb.IDPConfig{
|
||
|
Options: &idp_pb.Options{
|
||
|
IsLinkingAllowed: config.IsLinkingAllowed,
|
||
|
IsCreationAllowed: config.IsCreationAllowed,
|
||
|
IsAutoCreation: config.IsAutoCreation,
|
||
|
IsAutoUpdate: config.IsAutoUpdate,
|
||
|
AutoLinking: autoLinkingOptionToPb(config.AutoLinking),
|
||
|
},
|
||
|
}
|
||
|
if config.OAuthIDPTemplate != nil {
|
||
|
oauthConfigToPb(idpConfig, config.OAuthIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.OIDCIDPTemplate != nil {
|
||
|
oidcConfigToPb(idpConfig, config.OIDCIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.JWTIDPTemplate != nil {
|
||
|
jwtConfigToPb(idpConfig, config.JWTIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.AzureADIDPTemplate != nil {
|
||
|
azureConfigToPb(idpConfig, config.AzureADIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.GitHubIDPTemplate != nil {
|
||
|
githubConfigToPb(idpConfig, config.GitHubIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.GitHubEnterpriseIDPTemplate != nil {
|
||
|
githubEnterpriseConfigToPb(idpConfig, config.GitHubEnterpriseIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.GitLabIDPTemplate != nil {
|
||
|
gitlabConfigToPb(idpConfig, config.GitLabIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.GitLabSelfHostedIDPTemplate != nil {
|
||
|
gitlabSelfHostedConfigToPb(idpConfig, config.GitLabSelfHostedIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.GoogleIDPTemplate != nil {
|
||
|
googleConfigToPb(idpConfig, config.GoogleIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.LDAPIDPTemplate != nil {
|
||
|
ldapConfigToPb(idpConfig, config.LDAPIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.AppleIDPTemplate != nil {
|
||
|
appleConfigToPb(idpConfig, config.AppleIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
if config.SAMLIDPTemplate != nil {
|
||
|
samlConfigToPb(idpConfig, config.SAMLIDPTemplate)
|
||
|
return idpConfig
|
||
|
}
|
||
|
return idpConfig
|
||
|
}
|
||
|
|
||
|
func autoLinkingOptionToPb(linking domain.AutoLinkingOption) idp_pb.AutoLinkingOption {
|
||
|
switch linking {
|
||
|
case domain.AutoLinkingOptionUnspecified:
|
||
|
return idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_UNSPECIFIED
|
||
|
case domain.AutoLinkingOptionUsername:
|
||
|
return idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_USERNAME
|
||
|
case domain.AutoLinkingOptionEmail:
|
||
|
return idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_EMAIL
|
||
|
default:
|
||
|
return idp_pb.AutoLinkingOption_AUTO_LINKING_OPTION_UNSPECIFIED
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func oauthConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.OAuthIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_Oauth{
|
||
|
Oauth: &idp_pb.OAuthConfig{
|
||
|
ClientId: template.ClientID,
|
||
|
AuthorizationEndpoint: template.AuthorizationEndpoint,
|
||
|
TokenEndpoint: template.TokenEndpoint,
|
||
|
UserEndpoint: template.UserEndpoint,
|
||
|
Scopes: template.Scopes,
|
||
|
IdAttribute: template.IDAttribute,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func oidcConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.OIDCIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_Oidc{
|
||
|
Oidc: &idp_pb.GenericOIDCConfig{
|
||
|
ClientId: template.ClientID,
|
||
|
Issuer: template.Issuer,
|
||
|
Scopes: template.Scopes,
|
||
|
IsIdTokenMapping: template.IsIDTokenMapping,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func jwtConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.JWTIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_Jwt{
|
||
|
Jwt: &idp_pb.JWTConfig{
|
||
|
JwtEndpoint: template.Endpoint,
|
||
|
Issuer: template.Issuer,
|
||
|
KeysEndpoint: template.KeysEndpoint,
|
||
|
HeaderName: template.HeaderName,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func azureConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.AzureADIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_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(idpConfig *idp_pb.IDPConfig, template *query.GitHubIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_Github{
|
||
|
Github: &idp_pb.GitHubConfig{
|
||
|
ClientId: template.ClientID,
|
||
|
Scopes: template.Scopes,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func githubEnterpriseConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.GitHubEnterpriseIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_GithubEs{
|
||
|
GithubEs: &idp_pb.GitHubEnterpriseServerConfig{
|
||
|
ClientId: template.ClientID,
|
||
|
AuthorizationEndpoint: template.AuthorizationEndpoint,
|
||
|
TokenEndpoint: template.TokenEndpoint,
|
||
|
UserEndpoint: template.UserEndpoint,
|
||
|
Scopes: template.Scopes,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func gitlabConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.GitLabIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_Gitlab{
|
||
|
Gitlab: &idp_pb.GitLabConfig{
|
||
|
ClientId: template.ClientID,
|
||
|
Scopes: template.Scopes,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func gitlabSelfHostedConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.GitLabSelfHostedIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_GitlabSelfHosted{
|
||
|
GitlabSelfHosted: &idp_pb.GitLabSelfHostedConfig{
|
||
|
ClientId: template.ClientID,
|
||
|
Issuer: template.Issuer,
|
||
|
Scopes: template.Scopes,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func googleConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.GoogleIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_Google{
|
||
|
Google: &idp_pb.GoogleConfig{
|
||
|
ClientId: template.ClientID,
|
||
|
Scopes: template.Scopes,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func ldapConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.LDAPIDPTemplate) {
|
||
|
var timeout *durationpb.Duration
|
||
|
if template.Timeout != 0 {
|
||
|
timeout = durationpb.New(template.Timeout)
|
||
|
}
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_Ldap{
|
||
|
Ldap: &idp_pb.LDAPConfig{
|
||
|
Servers: template.Servers,
|
||
|
StartTls: template.StartTLS,
|
||
|
BaseDn: template.BaseDN,
|
||
|
BindDn: template.BindDN,
|
||
|
UserBase: template.UserBase,
|
||
|
UserObjectClasses: template.UserObjectClasses,
|
||
|
UserFilters: template.UserFilters,
|
||
|
Timeout: timeout,
|
||
|
Attributes: ldapAttributesToPb(template.LDAPAttributes),
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func ldapAttributesToPb(attributes idp_rp.LDAPAttributes) *idp_pb.LDAPAttributes {
|
||
|
return &idp_pb.LDAPAttributes{
|
||
|
IdAttribute: attributes.IDAttribute,
|
||
|
FirstNameAttribute: attributes.FirstNameAttribute,
|
||
|
LastNameAttribute: attributes.LastNameAttribute,
|
||
|
DisplayNameAttribute: attributes.DisplayNameAttribute,
|
||
|
NickNameAttribute: attributes.NickNameAttribute,
|
||
|
PreferredUsernameAttribute: attributes.PreferredUsernameAttribute,
|
||
|
EmailAttribute: attributes.EmailAttribute,
|
||
|
EmailVerifiedAttribute: attributes.EmailVerifiedAttribute,
|
||
|
PhoneAttribute: attributes.PhoneAttribute,
|
||
|
PhoneVerifiedAttribute: attributes.PhoneVerifiedAttribute,
|
||
|
PreferredLanguageAttribute: attributes.PreferredLanguageAttribute,
|
||
|
AvatarUrlAttribute: attributes.AvatarURLAttribute,
|
||
|
ProfileAttribute: attributes.ProfileAttribute,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func appleConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.AppleIDPTemplate) {
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_Apple{
|
||
|
Apple: &idp_pb.AppleConfig{
|
||
|
ClientId: template.ClientID,
|
||
|
TeamId: template.TeamID,
|
||
|
KeyId: template.KeyID,
|
||
|
Scopes: template.Scopes,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func samlConfigToPb(idpConfig *idp_pb.IDPConfig, template *query.SAMLIDPTemplate) {
|
||
|
nameIDFormat := idp_pb.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_PERSISTENT
|
||
|
if template.NameIDFormat.Valid {
|
||
|
nameIDFormat = nameIDToPb(template.NameIDFormat.V)
|
||
|
}
|
||
|
idpConfig.Config = &idp_pb.IDPConfig_Saml{
|
||
|
Saml: &idp_pb.SAMLConfig{
|
||
|
MetadataXml: template.Metadata,
|
||
|
Binding: bindingToPb(template.Binding),
|
||
|
WithSignedRequest: template.WithSignedRequest,
|
||
|
NameIdFormat: nameIDFormat,
|
||
|
TransientMappingAttributeName: gu.Ptr(template.TransientMappingAttributeName),
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func bindingToPb(binding string) idp_pb.SAMLBinding {
|
||
|
switch binding {
|
||
|
case "":
|
||
|
return idp_pb.SAMLBinding_SAML_BINDING_UNSPECIFIED
|
||
|
case saml.HTTPPostBinding:
|
||
|
return idp_pb.SAMLBinding_SAML_BINDING_POST
|
||
|
case saml.HTTPRedirectBinding:
|
||
|
return idp_pb.SAMLBinding_SAML_BINDING_REDIRECT
|
||
|
case saml.HTTPArtifactBinding:
|
||
|
return idp_pb.SAMLBinding_SAML_BINDING_ARTIFACT
|
||
|
default:
|
||
|
return idp_pb.SAMLBinding_SAML_BINDING_UNSPECIFIED
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func nameIDToPb(format domain.SAMLNameIDFormat) idp_pb.SAMLNameIDFormat {
|
||
|
switch format {
|
||
|
case domain.SAMLNameIDFormatUnspecified:
|
||
|
return idp_pb.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_UNSPECIFIED
|
||
|
case domain.SAMLNameIDFormatEmailAddress:
|
||
|
return idp_pb.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_EMAIL_ADDRESS
|
||
|
case domain.SAMLNameIDFormatPersistent:
|
||
|
return idp_pb.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_PERSISTENT
|
||
|
case domain.SAMLNameIDFormatTransient:
|
||
|
return idp_pb.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_TRANSIENT
|
||
|
default:
|
||
|
return idp_pb.SAMLNameIDFormat_SAML_NAME_ID_FORMAT_UNSPECIFIED
|
||
|
}
|
||
|
}
|