feat(ldap): adding root ca option to ldap config (#9292)

# Which Problems Are Solved

Adding ability to add a root CA to LDAP configs

# Additional Context

- Closes https://github.com/zitadel/zitadel/issues/7888

---------

Co-authored-by: Iraq Jaber <IraqJaber@gmail.com>
This commit is contained in:
Iraq
2025-02-18 10:06:50 +00:00
committed by GitHub
parent d7332d1ac4
commit 5bbb953ffb
27 changed files with 418 additions and 243 deletions

View File

@@ -6834,6 +6834,8 @@ message AddLDAPProviderRequest {
google.protobuf.Duration timeout = 10;
zitadel.idp.v1.LDAPAttributes attributes = 11;
zitadel.idp.v1.Options provider_options = 12;
// Root_ca is for self signing certificates for TLS connections to LDAP servers it is intended to be filled with a .pem file.
bytes root_ca = 13 [(validate.rules).bytes.max_len = 12000];
}
message AddLDAPProviderResponse {
@@ -6855,6 +6857,8 @@ message UpdateLDAPProviderRequest {
google.protobuf.Duration timeout = 11;
zitadel.idp.v1.LDAPAttributes attributes = 12;
zitadel.idp.v1.Options provider_options = 13;
// Root_ca is for self signing certificates for TLS connections to LDAP servers it is intended to be filled with a .pem file.
bytes root_ca = 14 [(validate.rules).bytes.max_len = 12000];
}
message UpdateLDAPProviderResponse {

View File

@@ -456,6 +456,7 @@ message LDAPConfig {
repeated string user_filters = 7;
google.protobuf.Duration timeout = 8;
LDAPAttributes attributes = 9;
bytes root_ca = 10;
}
message SAMLConfig {

View File

@@ -10,24 +10,23 @@ import "protoc-gen-openapiv2/options/annotations.proto";
import "validate/validate.proto";
import "google/protobuf/duration.proto";
option go_package = "github.com/zitadel/zitadel/pkg/grpc/idp/v2;idp";
message IDP {
// Unique identifier for the identity provider.
string id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"69629023906488334\"";
}
];
string id = 1
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"69629023906488334\"";
} ];
zitadel.object.v2.Details details = 2;
// Current state of the identity provider.
IDPState state = 3;
string name = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"Google\"";
}
];
string name = 4
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"Google\"";
} ];
// Type of the identity provider, for example OIDC, JWT, LDAP and SAML.
IDPType type = 5;
// Configuration for the type of the identity provider.
@@ -93,177 +92,189 @@ message IDPConfig {
message JWTConfig {
// The endpoint where the JWT can be extracted.
string jwt_endpoint = 1 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
(validate.rules).string = {min_len : 1, max_len : 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) =
{
example:
"\"https://accounts.google.com\"";
}
];
// The issuer of the JWT (for validation).
string issuer = 2 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com\"";
(validate.rules).string = {min_len : 1, max_len : 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) =
{
example:
"\"https://accounts.google.com\"";
}
];
// The endpoint to the key (JWK) which is used to sign the JWT with.
string keys_endpoint = 3 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/keys\"";
(validate.rules).string = {min_len : 1, max_len : 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) =
{
example:
"\"https://accounts.google.com/keys\"";
}
];
// The name of the header where the JWT is sent in, default is authorization.
string header_name = 4 [
(validate.rules).string = {min_len: 1, max_len: 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"x-auth-token\"";
(validate.rules).string = {min_len : 1, max_len : 200},
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) =
{
example:
"\"x-auth-token\"";
}
];
}
message OAuthConfig {
// Client id generated by the identity provider.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
string client_id = 1
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"client-id\"";
} ];
// The endpoint where ZITADEL send the user to authenticate.
string authorization_endpoint = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/o/oauth2/v2/auth\"";
}
];
string authorization_endpoint = 2
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"https://accounts.google.com/o/oauth2/v2/auth\"";
} ];
// The endpoint where ZITADEL can get the token.
string token_endpoint = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://oauth2.googleapis.com/token\"";
}
];
string token_endpoint = 3
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"https://oauth2.googleapis.com/token\"";
} ];
// The endpoint where ZITADEL can get the user information.
string user_endpoint = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://openidconnect.googleapis.com/v1/userinfo\"";
}
];
// The scopes requested by ZITADEL during the request on the identity provider.
repeated string scopes = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
// Defines how the attribute is called where ZITADEL can get the id of the user.
string id_attribute = 6 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"user_id\"";
}
];
string user_endpoint = 4
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"https://openidconnect.googleapis.com/v1/userinfo\"";
} ];
// The scopes requested by ZITADEL during the request on the identity
// provider.
repeated string scopes = 5
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"[\"openid\", \"profile\", \"email\"]";
} ];
// Defines how the attribute is called where ZITADEL can get the id of the
// user.
string id_attribute = 6
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"user_id\"";
} ];
}
message GenericOIDCConfig {
// The OIDC issuer of the identity provider.
string issuer = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"https://accounts.google.com/\"";
}
];
string issuer = 1
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"https://accounts.google.com/\"";
} ];
// Client id generated by the identity provider.
string client_id = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
// The scopes requested by ZITADEL during the request on the identity provider.
repeated string scopes = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
// If true, provider information get mapped from the id token, not from the userinfo endpoint.
bool is_id_token_mapping = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "true";
}
];
string client_id = 2
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"client-id\"";
} ];
// The scopes requested by ZITADEL during the request on the identity
// provider.
repeated string scopes = 3
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"[\"openid\", \"profile\", \"email\"]";
} ];
// If true, provider information get mapped from the id token, not from the
// userinfo endpoint.
bool is_id_token_mapping = 4
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"true";
} ];
}
message GitHubConfig {
// The client ID of the GitHub App.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
string client_id = 1
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"client-id\"";
} ];
// The scopes requested by ZITADEL during the request to GitHub.
repeated string scopes = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
repeated string scopes = 2
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"[\"openid\", \"profile\", \"email\"]";
} ];
}
message GitHubEnterpriseServerConfig {
// The client ID of the GitHub App.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
string client_id = 1
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"client-id\"";
} ];
string authorization_endpoint = 2;
string token_endpoint = 3;
string user_endpoint = 4;
// The scopes requested by ZITADEL during the request to GitHub.
repeated string scopes = 5 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
repeated string scopes = 5
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"[\"openid\", \"profile\", \"email\"]";
} ];
}
message GoogleConfig {
// Client id of the Google application.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
string client_id = 1
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"client-id\"";
} ];
// The scopes requested by ZITADEL during the request to Google.
repeated string scopes = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
repeated string scopes = 2
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"[\"openid\", \"profile\", \"email\"]";
} ];
}
message GitLabConfig {
// Client id of the GitLab application.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
string client_id = 1
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"client-id\"";
} ];
// The scopes requested by ZITADEL during the request to GitLab.
repeated string scopes = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
repeated string scopes = 2
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"[\"openid\", \"profile\", \"email\"]";
} ];
}
message GitLabSelfHostedConfig {
string issuer = 1;
// Client id of the GitLab application.
string client_id = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
string client_id = 2
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"client-id\"";
} ];
// The scopes requested by ZITADEL during the request to GitLab.
repeated string scopes = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\"]";
}
];
repeated string scopes = 3
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"[\"openid\", \"profile\", \"email\"]";
} ];
}
message LDAPConfig {
@@ -276,6 +287,7 @@ message LDAPConfig {
repeated string user_filters = 7;
google.protobuf.Duration timeout = 8;
LDAPAttributes attributes = 9;
bytes root_ca = 10;
}
message SAMLConfig {
@@ -288,66 +300,84 @@ message SAMLConfig {
// `nameid-format` for the SAML Request.
SAMLNameIDFormat name_id_format = 4;
// Optional name of the attribute, which will be used to map the user
// in case the nameid-format returned is `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`.
// in case the nameid-format returned is
// `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`.
optional string transient_mapping_attribute_name = 5;
}
message AzureADConfig {
// Client id of the Azure AD application
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"client-id\"";
}
];
// Defines what user accounts should be able to login (Personal, Organizational, All).
string client_id = 1
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"client-id\"";
} ];
// Defines what user accounts should be able to login (Personal,
// Organizational, All).
AzureADTenant tenant = 2;
// Azure AD doesn't send if the email has been verified. Enable this if the user email should always be added verified in ZITADEL (no verification emails will be sent).
// Azure AD doesn't send if the email has been verified. Enable this if the
// user email should always be added verified in ZITADEL (no verification
// emails will be sent).
bool email_verified = 3;
// The scopes requested by ZITADEL during the request to Azure AD.
repeated string scopes = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"openid\", \"profile\", \"email\", \"User.Read\"]";
}
];
repeated string scopes = 4
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"[\"openid\", \"profile\", \"email\", \"User.Read\"]";
} ];
}
message Options {
// Enable if users should be able to link an existing ZITADEL user with an external account.
// Enable if users should be able to link an existing ZITADEL user with an
// external account.
bool is_linking_allowed = 1;
// Enable if users should be able to create a new account in ZITADEL when using an external account.
// Enable if users should be able to create a new account in ZITADEL when
// using an external account.
bool is_creation_allowed = 2;
// Enable if a new account in ZITADEL should be created automatically when login with an external account.
// Enable if a new account in ZITADEL should be created automatically when
// login with an external account.
bool is_auto_creation = 3;
// Enable if a the ZITADEL account fields should be updated automatically on each login.
// Enable if a the ZITADEL account fields should be updated automatically on
// each login.
bool is_auto_update = 4;
// Enable if users should get prompted to link an existing ZITADEL user to an external account if the selected attribute matches.
AutoLinkingOption auto_linking = 5 ;
// Enable if users should get prompted to link an existing ZITADEL user to an
// external account if the selected attribute matches.
AutoLinkingOption auto_linking = 5;
}
enum AutoLinkingOption {
// AUTO_LINKING_OPTION_UNSPECIFIED disables the auto linking prompt.
AUTO_LINKING_OPTION_UNSPECIFIED = 0;
// AUTO_LINKING_OPTION_USERNAME will use the username of the external user to check for a corresponding ZITADEL user.
// AUTO_LINKING_OPTION_USERNAME will use the username of the external user to
// check for a corresponding ZITADEL user.
AUTO_LINKING_OPTION_USERNAME = 1;
// AUTO_LINKING_OPTION_EMAIL will use the email of the external user to check for a corresponding ZITADEL user with the same verified email
// Note that in case multiple users match, no prompt will be shown.
// AUTO_LINKING_OPTION_EMAIL will use the email of the external user to check
// for a corresponding ZITADEL user with the same verified email Note that in
// case multiple users match, no prompt will be shown.
AUTO_LINKING_OPTION_EMAIL = 2;
}
message LDAPAttributes {
string id_attribute = 1 [(validate.rules).string = {max_len: 200}];
string first_name_attribute = 2 [(validate.rules).string = {max_len: 200}];
string last_name_attribute = 3 [(validate.rules).string = {max_len: 200}];
string display_name_attribute = 4 [(validate.rules).string = {max_len: 200}];
string nick_name_attribute = 5 [(validate.rules).string = {max_len: 200}];
string preferred_username_attribute = 6 [(validate.rules).string = {max_len: 200}];
string email_attribute = 7 [(validate.rules).string = {max_len: 200}];
string email_verified_attribute = 8 [(validate.rules).string = {max_len: 200}];
string phone_attribute = 9 [(validate.rules).string = {max_len: 200}];
string phone_verified_attribute = 10 [(validate.rules).string = {max_len: 200}];
string preferred_language_attribute = 11 [(validate.rules).string = {max_len: 200}];
string avatar_url_attribute = 12 [(validate.rules).string = {max_len: 200}];
string profile_attribute = 13 [(validate.rules).string = {max_len: 200}];
string id_attribute = 1 [ (validate.rules).string = {max_len : 200} ];
string first_name_attribute = 2 [ (validate.rules).string = {max_len : 200} ];
string last_name_attribute = 3 [ (validate.rules).string = {max_len : 200} ];
string display_name_attribute = 4
[ (validate.rules).string = {max_len : 200} ];
string nick_name_attribute = 5 [ (validate.rules).string = {max_len : 200} ];
string preferred_username_attribute = 6
[ (validate.rules).string = {max_len : 200} ];
string email_attribute = 7 [ (validate.rules).string = {max_len : 200} ];
string email_verified_attribute = 8
[ (validate.rules).string = {max_len : 200} ];
string phone_attribute = 9 [ (validate.rules).string = {max_len : 200} ];
string phone_verified_attribute = 10
[ (validate.rules).string = {max_len : 200} ];
string preferred_language_attribute = 11
[ (validate.rules).string = {max_len : 200} ];
string avatar_url_attribute = 12
[ (validate.rules).string = {max_len : 200} ];
string profile_attribute = 13 [ (validate.rules).string = {max_len : 200} ];
string root_ca= 14;
}
enum AzureADTenantType {
@@ -365,27 +395,27 @@ message AzureADTenant {
message AppleConfig {
// Client id (App ID or Service ID) provided by Apple.
string client_id = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"com.client.id\"";
}
];
string client_id = 1
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"com.client.id\"";
} ];
// Team ID provided by Apple.
string team_id = 2 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"ALT03JV3OS\"";
}
];
string team_id = 2
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"ALT03JV3OS\"";
} ];
// ID of the private key generated by Apple.
string key_id = 3 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "\"OGKDK25KD\"";
}
];
string key_id = 3
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"\"OGKDK25KD\"";
} ];
// The scopes requested by ZITADEL during the request to Apple.
repeated string scopes = 4 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example: "[\"name\", \"email\"]";
}
];
}
repeated string scopes = 4
[ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
example:
"[\"name\", \"email\"]";
} ];
}

View File

@@ -13255,6 +13255,8 @@ message AddLDAPProviderRequest {
google.protobuf.Duration timeout = 10;
zitadel.idp.v1.LDAPAttributes attributes = 11;
zitadel.idp.v1.Options provider_options = 12;
// Root_ca is for self signing certificates for TLS connections to LDAP servers it is intended to be filled with a .pem file.
bytes root_ca = 13 [(validate.rules).bytes.max_len = 12000];
}
message AddLDAPProviderResponse {
@@ -13276,6 +13278,8 @@ message UpdateLDAPProviderRequest {
google.protobuf.Duration timeout = 11;
zitadel.idp.v1.LDAPAttributes attributes = 12;
zitadel.idp.v1.Options provider_options = 13;
// Root_ca is for self signing certificates for TLS connections to LDAP servers it is intended to be filled with a .pem file.
bytes root_ca = 14 [(validate.rules).bytes.max_len = 12000];
}
message UpdateLDAPProviderResponse {