Managing authentication for multiple stacks using Elastic Stack configuration policy
editManaging authentication for multiple stacks using Elastic Stack configuration policy
editWe have identified an issue with Elasticsearch 8.15.1 and 8.15.2 that prevents security role mappings configured via Stack configuration policies to work correctly. Avoid these versions and upgrade to 8.16.0 to remedy this issue if you are affected.
This requires a valid Enterprise license or Enterprise trial license. Check the license documentation for more details about managing licenses.
ECK 2.11.0
extends the functionality of Elastic Stack configuration policies so that it becomes possible to configure Elasticsearch security realms for more than one Elastic stack at once.
The authentication will apply to all Elasticsearch clusters and Kibana instances managed by the Elastic Stack configuration policy.
Examples for configuring some of the authentication methods can be found below:
LDAP using Elastic stack configuration policy
editWe have identified an issue with Elasticsearch 8.15.1 and 8.15.2 that prevents security role mappings configured via Stack configuration policies to work correctly. Avoid these versions and upgrade to 8.16.0 to remedy this issue if you are affected.
This requires a valid Enterprise license or Enterprise trial license. Check the license documentation for more details about managing licenses.
Make sure you check the complete guide to setting up LDAP with Elasticsearch.
To configure LDAP using Elastic Stack configuration policy with user search:
edit-
Add a realm configuration to the
config
field underelasticsearch
in thexpack.security.authc.realms.ldap
namespace. At a minimum, you must specify the URL of the LDAP server and the order of the LDAP realm compared to other configured security realms. You also have to setuser_search.base_dn
to the container DN where the users are searched for. Refer to LDAP realm settings for all of the options you can set for an LDAP realm. For example, the following snippet shows an LDAP realm configured with a user search:elasticsearch: config: xpack.security.authc.realms: ldap: ldap1: order: 0 url: "ldap://openldap.default.svc.cluster.local:1389" bind_dn: "cn=admin,dc=example,dc=org" user_search: base_dn: "dc=example,dc=org" filter: "(cn={0})" group_search: base_dn: "dc=example,dc=org" unmapped_groups_as_roles: false
-
The password for the
bind_dn
user should be configured by adding the appropriatesecure_bind_password
setting to the Elasticsearch keystore. This can be done using the Elastic Stack configuration policy by following the below steps:-
Create a secret that has the
secure_bind_password
in the same namespace as the operatorkubectl create secret generic ldap-secret --from-literal=xpack.security.authc.realms.ldap.ldap1.secure_bind_password=<password>
-
Add the secret name to the
secureSettings
field underelasticsearch
in the Elastic Stack configuration policyspec: resourceSelector: matchLabels: env: my-label elasticsearch: secureSettings: - secretName: ldap-secret
-
-
Map LDAP groups to roles. In the below example, LDAP users get the Elasticsearch
superuser
role.dn: "cn=users,dc=example,dc=org"
is the LDAP distinguished name (DN) of the users group.securityRoleMappings: ldap_role: roles: [ "superuser" ] rules: all: - field: { realm.name: "ldap1" } - field: { dn: "cn=users,dc=example,dc=org" } enabled: true
Simple full example Elastic Stack config policy to configure LDAP realm with user search
apiVersion: stackconfigpolicy.k8s.elastic.co/v1alpha1 kind: StackConfigPolicy metadata: name: test-stack-config-policy spec: resourceSelector: matchLabels: env: my-label elasticsearch: secureSettings: - secretName: ldap-secret securityRoleMappings: ldap_role: roles: [ "superuser" ] rules: all: - field: { realm.name: "ldap1" } - field: { dn: "cn=users,dc=example,dc=org" } enabled: true config: xpack.security.authc.realms: ldap: ldap1: order: 0 url: "ldap://openldap.default.svc.cluster.local:1389" bind_dn: "cn=admin,dc=example,dc=org" user_search: base_dn: "dc=example,dc=org" filter: "(cn={0})" group_search: base_dn: "dc=example,dc=org" unmapped_groups_as_roles: false
To configure an LDAP realm with user DN templates:
editAdd a realm configuration to elasticsearch.yml
in the xpack.security.authc.realms.ldap namespace. At a minimum, you must specify the url and order of the LDAP server, and specify at least one template with the user_dn_templates option. Check LDAP realm settings for all of the options you can set for an ldap realm.
For example, the following snippet shows an LDAP realm configured with user DN templates:
xpack: security: authc: realms: ldap: ldap1: order: 0 url: "ldaps://ldap.example.com:636" user_dn_templates: - "cn={0}, ou=users, dc=example, dc=org" group_search: base_dn: "dc=example,dc=org" unmapped_groups_as_roles: false
Example Elastic Stack config policy to configure LDAP realm with user DN templates:
apiVersion: stackconfigpolicy.k8s.elastic.co/v1alpha1 kind: StackConfigPolicy metadata: name: test-stack-config-policy spec: resourceSelector: matchLabels: env: my-label elasticsearch: securityRoleMappings: ldap_role: roles: [ "superuser" ] rules: all: - field: { realm.name: "ldap1" } - field: { dn: "*,ou=users,dc=example,dc=org" } enabled: true config: xpack.security.authc.realms: ldap: ldap1: order: 0 url: "ldaps://ldap.example.com:636" user_dn_templates: - "cn={0}, ou=users, dc=example, dc=org" group_search: base_dn: "dc=example,dc=org" unmapped_groups_as_roles: false
The bind_dn
setting is not used in template mode. All LDAP operations run as the authenticating user. So there is no need of setting up any additional secrets to be stored in the keystore.
OIDC using Elastic stack configuration policy
editWe have identified an issue with Elasticsearch 8.15.1 and 8.15.2 that prevents security role mappings configured via Stack configuration policies to work correctly. Avoid these versions and upgrade to 8.16.0 to remedy this issue if you are affected.
This requires a valid Enterprise license or Enterprise trial license. Check the license documentation for more details about managing licenses.
Make sure you check the complete guide to setting up OpenID Connect with Elasticsearch.
Configuring OpenID Connect using Elastic Stack configuration policy
-
Add OIDC realm to the
elasticsearch.yml
file using theconfig
field underelasticsearch
in the Elastic Stack configuration policy, also enable token service.Below snippet is an example of using Google as OpenID provider, the values will change depending on the provider being used.
elasticsearch: config: xpack: security: authc: token.enabled: true realms: oidc: oidc1: order: 2 rp.client_id: "<client id>" rp.response_type: "code" rp.requested_scopes: ["openid", "email"] rp.redirect_uri: "${KIBANA_URL}/api/security/oidc/callback" op.issuer: "https://accounts.google.com" op.authorization_endpoint: "https://accounts.google.com/o/oauth2/v2/auth" op.token_endpoint: "https://oauth2.googleapis.com/token" op.userinfo_endpoint: "https://openidconnect.googleapis.com/v1/userinfo" op.jwkset_path: "https://www.googleapis.com/oauth2/v3/certs" claims.principal: email claim_patterns.principal: "^([^@]+)@elastic\\.co$"
-
Another piece of configuration of the OpenID Connect realm is to set the Client Secret that was assigned to the Relying Parties (RP) during registration in the OpenID Connect Provider (OP). This is a secure setting and as such is not defined in the realm configuration in
elasticsearch.yml
but added to the Elasticsearch keystore. To set this up using Elastic Stack configuration policy, use the following steps.-
Create a secret in the operator namespace that has the Client Secret
kubectl create secret generic oidc-client-secret --from-literal=xpack.security.authc.realms.oidc.oidc1.rp.client_secret=<client_secret>
-
Add the secret name to the
secureSettings
field underelasticsearch
elasticsearch: secureSettings: - secretName: oidc-client-secret
-
-
When a user authenticates using OpenID Connect, they are identified to the Elastic Stack, but this does not automatically grant them access to perform any actions or access any data. Your OpenID Connect users cannot do anything until they are assigned roles. Roles can be assigned by adding role mappings to the Elastic Stack configuration policy. The below example is giving a specific user access as a superuser to Elasticsearch, if you want to assign roles to all users authenticating with OIDC, you can remove the username field.
elasticsearch: secureSettings: - secretName: oidc-client-secret securityRoleMappings: oidc_kibana: roles: [ "superuser" ] rules: all: - field: { realm.name: "oidc1" } - field: { username: "<username>" } enabled: true
-
Update Kibana to use OpenID Connect as the authentication provider:
kibana: config: xpack.security.authc.providers: oidc.oidc1: order: 0 realm: oidc1 description: "Log in with GCP"
Example full Elastic Stack configuration policy to configure oidc
apiVersion: stackconfigpolicy.k8s.elastic.co/v1alpha1 kind: StackConfigPolicy metadata: name: test-stack-config-policy spec: resourceSelector: matchLabels: env: my-label elasticsearch: secureSettings: - secretName: oidc-client-secret securityRoleMappings: oidc_kibana: roles: [ "superuser" ] rules: all: - field: { realm.name: "oidc1" } - field: { username: "<username>" } enabled: true config: logger.org.elasticsearch.discovery: DEBUG xpack: security: authc: token.enabled: true realms: oidc: oidc1: order: 2 rp.client_id: "<client id>" rp.response_type: "code" rp.requested_scopes: ["openid", "email"] rp.redirect_uri: "${KIBANA_URL}/api/security/oidc/callback" op.issuer: "https://accounts.google.com" op.authorization_endpoint: "https://accounts.google.com/o/oauth2/v2/auth" op.token_endpoint: "https://oauth2.googleapis.com/token" op.userinfo_endpoint: "https://openidconnect.googleapis.com/v1/userinfo" op.jwkset_path: "https://www.googleapis.com/oauth2/v3/certs" claims.principal: email claim_patterns.principal: "^([^@]+)@elastic\\.co$" kibana: config: xpack.security.authc.providers: oidc.oidc1: order: 0 realm: oidc1 description: "Log in with GCP" basic.basic1: order: 1
The Kibana URL should be an environment variable that should be configured on the Elasticsearch Clusters managed by the Elastic Stack Configuration policy. This can be done by adding an environment variable to the pod template in the Elasticsearch CR. apiVersion: elasticsearch.k8s.elastic.co/v1 kind: Elasticsearch metadata: name: quickstart namespace: kvalliy labels: env: my-label spec: version: 8.10.3 nodeSets: - name: default count: 1 config: node.store.allow_mmap: false podTemplate: spec: containers: - name: elasticsearch env: - name: KIBANA_URL value: "https://kibana.eck-ocp.elastic.dev" |
The OpenID Connect Provider (OP) should have support to configure multiple Redirect URLs, so that the same rp.client_id
and client_secret
can be used for all the Elasticsearch clusters managed by the Elastic Stack configuration policy.
JWT using Elastic Stack configuration policy
editWe have identified an issue with Elasticsearch 8.15.1 and 8.15.2 that prevents security role mappings configured via Stack configuration policies to work correctly. Avoid these versions and upgrade to 8.16.0 to remedy this issue if you are affected.
This requires a valid Enterprise license or Enterprise trial license. Check the license documentation for more details about managing licenses.
Make sure you check the complete guide to setting up JWT with Elasticsearch.
Configuring JWT with Elastic Stack configuration policy
-
Add your JWT realm to the
elasticsearch.yml
file using theconfig
field underelasticsearch
in the Elastic Stack configuration policyelasticsearch: config: xpack.security.authc.realms.jwt.jwt1: order: -98 token_type: id_token client_authentication.type: shared_secret allowed_issuer: "https://es.k8s.elastic.co" allowed_audiences: [ "elasticsearch" ] allowed_subjects: ["elastic-user"] allowed_signature_algorithms: [RS512] pkc_jwkset_path: jwks/jwkset.json claims.principal: sub
-
Add the
shared_secret
setting that will be used for client authentication to the Elasticsearch keystore.-
Create a secret in the operator namespace containing the shared secret
kubectl create secret generic shared-secret --from-literal=xpack.security.authc.realms.jwt.jwt1.client_authentication.shared_secret=<sharedsecret>
-
Add the secret name to the
secureSettings
field underelasticsearch
in the Elastic Stack configuration policyelasticsearch: secureSettings: : - secretName: shared-secret
-
-
Add an additional volume to the Elasticsearch pods that contain the JSON Web Keys, it should be mounted to the path that is configured for the
xpack.security.authc.realms.jwt.jwt1.pkc_jwkset_path
config. The file path is resolved relative to the Elasticsearch configuration directory.-
Create a secret in the operator namespace that has the jwk set
kubectl create secret generic jwks-secret --from-file=jwkset.json
-
Add the secret name and mountpath to the
secretMounts
field underelasticsearch
in the Elastic Stack configuration policysecretMounts: - secretName: jwks-secret mountPath: "/usr/share/elasticsearch/config/jwks"
-
-
You can use the
securityRoleMappings
field underelasticsearch
in the Elastic Stack configuration policy to define role mappings that determine which roles should be assigned to each user based on their username, groups, or other metadata.securityRoleMappings: jwt1-user-role: roles: [ "superuser" ] rules: all: - field: { realm.name: "jwt1" } - field: { username: "jwt-user" } enabled: true
The following example demonstrates how an Elastic Stack configuration policy can be used to configure a JWT realm:
apiVersion: stackconfigpolicy.k8s.elastic.co/v1alpha1 kind: StackConfigPolicy metadata: name: test-stack-config-policy spec: resourceSelector: matchLabels: env: my-label elasticsearch: secureSettings: - secretName: shared-secret securityRoleMappings: jwt1-user-role: roles: [ "superuser" ] rules: all: - field: { realm.name: "jwt1" } - field: { username: "jwt-user" } enabled: true config: xpack.security.authc.realms.jwt.jwt1: order: -98 token_type: id_token client_authentication.type: shared_secret allowed_issuer: "https://es.k8s.elastic.co" allowed_audiences: [ "elasticsearch" ] allowed_subjects: ["elastic-user"] allowed_signature_algorithms: [RS512] pkc_jwkset_path: jwks/jwkset.json claims.principal: sub secretMounts: - secretName: jwks-secret mountPath: "/usr/share/elasticsearch/config/jwks"