Authentication with OpenLDAP
The Stackable platform supports user authentication with LDAP in multiple products. This page guides you through setting up the configuration necessary to use an existing LDAP installation with Stackable supported products. You can learn more about authentication in the Stackable Platform on the concepts page.
Prerequisites:
Setup
Before configuring LDAP you need to set up some services to configure, as well as an LDAP server to use for
authentication. This tutorial is about learning how to configure LDAP, so there won’t be detailed instructions on how to
set up all of this, instead the tutorial uses the stackablectl stacks
command.
Superset and Trino Stack
This command will install the latest Stackable release for you, and set up the trino-superset-s3
Stack. It contains a
Superset instance connected to a Trino instance, and all their dependencies (Minio S3, PostgreSQL). Later in this guide,
a Superset and Trino instance will be configured to use LDAP.
If you do not have a Kubernetes cluster already, add the --cluster kind
(or -c kind
) flag to let stackablectl deploy
one for you.
stackablectl stack install trino-superset-s3
This command will take a few minutes to complete.
The stack installed here is used in the trino-taxi-data demo. Click the link to learn more.
|
Inspect
Before starting to add configuration to your Stackable cluster, inspect what the command above has set up in your Kubernetes cluster.
Use stackablectl stacklets list
to find the endpoints of Superset and Trino and open their web interfaces in the
browser.
You can log into Superset with user admin and password adminadmin, and into Trino with user admin and password adminadmin.
These are the current users defined in Superset’s and Trino’s internal user management. Later you will see that these users cannot be used for authentication anymore after LDAP authentication has been enabled.
OpenLDAP Stack
Install another Stack, the tutorial-openldap
.
stackablectl stack install tutorial-openldap
Inspect
Look at the Pod definition of the openldap-0
Pod, it contains the environment settings
LDAP_ADMIN_USERNAME: ldapadmin
LDAP_ADMIN_PASSWORD: ldapadminpassword
LDAP_USERS: alice,bob
LDAP_PASSWORDS: alice,bob
ldapadmin
is the admin or bind user, and ldapadminpassword
is the password that belongs to that user. alice
and bob
(and their respective passwords) are the only two users defined in the LDAP instance. You will use this information later to configure LDAP.
Steps
Now that you have a couple of data products installed as well as an LDAP server, you can start configuring the products to use LDAP. The following image shows the parts that are already there in blue and the parts you will add in green:
The tutorial has 3 steps:
-
Configure an AuthenticationClass (as well as SecretClass and Secret) with this LDAP installation
-
Update the SupersetCluster to use the AuthenticationClass to authenticate users
-
Update the TrinoCluster to use the AuthenticationClass to authenticate users
Configure LDAP
The AuthenticationClass is the main resource required to configure the products, but it depends on some other resources. Below you will create a Secret, SecretClass and the AuthenticationClass. Use kubectl apply
to deploy the manifests shown below.
If you’re having problems here, install the openldap stack instead of tutorial-openldap which comes with an already configured AuthenticationClass ready to use. You can then skip to configuring superset.
|
First, create a secret that contains the LDAP bind credentials which products can use to authenticate with LDAP:
---
apiVersion: v1
kind: Secret
metadata:
name: openldap-bind-credentials
labels:
secrets.stackable.tech/class: openldap-bind-credentials (1)
stringData:
user: cn=ldapadmin,dc=example,dc=org (2)
password: ldapadminpassword (3)
1 | The annotation which SecretClass this secret belongs to |
2 | The LDAP bind user that was provided by the tutorial-ldap Stack |
3 | The corresponding password |
Notice the SecretClass annotation. Create the SecretClass next:
---
apiVersion: secrets.stackable.tech/v1alpha1
kind: SecretClass
metadata:
name: openldap-bind-credentials (1)
spec:
backend:
k8sSearch:
searchNamespace:
pod: {} (2)
1 | The name of the SecretClass we are creating that is referred to by the Secret |
2 | This determines the namespace in which the referenced Secret will be looked for. In this case it searches for a Secret in the same namespace as the product runs in. See the documentation of SecretClass |
This level of indirection is necessary, because the AuthenticationClass is cluster-scoped but Secrets are not.
Now you can create the AuthenticationClass openldap
which references the SecretClass:
---
apiVersion: authentication.stackable.tech/v1alpha1
kind: AuthenticationClass
metadata:
name: openldap (1)
spec:
provider:
ldap:
hostname: openldap.default.svc.cluster.local (2)
searchBase: ou=users,dc=example,dc=org
bindCredentials:
secretClass: openldap-bind-credentials (3)
port: 1636
tls:
verification:
server:
caCert:
secretClass: openldap-tls
1 | The name of the AuthenticationClass, which needs to be referenced later |
2 | The hostname in this case is the Service at which the OpenLDAP is running, inside of Kubernetes. |
3 | Here the SecretClass name is referenced |
Remember the name of the AuthenticationClass (openldap
), you will use it in the next steps when configuring the products.
Add LDAP authentication to Superset
To make Superset use your new LDAP AuthenticationClass, you have to update the SupersetCluster definition. A SupersetCluster named superset
is already installed by the stack.
Fetch the existing SupersetCluster defintion from the Kubernetes API server and save it into a superset.yaml
file:
kubectl get superset superset -o yaml > superset.yaml
The superset.yaml
file should look similar to this
---
apiVersion: superset.stackable.tech/v1alpha1
kind: SupersetCluster
metadata:
name: superset
...
spec:
version: ...
statsdExporterVersion: ...
credentialsSecret: superset-credentials
nodes:
roleGroups:
default:
config:
...
You can now delete the SupersetCluster, you recreate it later with the new configuration:
kubectl delete superset superset
Modify your superset.yaml
to include this new authenticationConfig
property under the spec
:
spec:
authenticationConfig: (1)
authenticationClass: openldap (2)
userRegistrationRole: Admin (3)
1 | The new authenticationConfig section which configures how Superset is authenticating users |
2 | The authenticationClass property is referencing the AuthenticationClass openldap you created earlier |
3 | The default Superset role that users should be assigned to when they log in. Any user will be an Admin |
Your superset.yaml
should now look similar to this
---
apiVersion: superset.stackable.tech/v1alpha1
kind: SupersetCluster
metadata:
name: superset
...
spec:
version: ...
statsdExporterVersion: ...
credentialsSecret: superset-credentials
authenticationConfig:
authenticationClass: openldap
userRegistrationRole: Admin
nodes:
roleGroups:
default:
config:
...
Now deploy the updated superset cluster:
kubectl apply -f superset.yaml
Connect to superset as before, and try logging in again with username admin and password adminadmin, Superset will not accept these credentials anymore. You now have to use LDAP credentials to log in. The OpenLDAP you installed earlier comes with two users, alice (password alice) and bob (password bob). Log in with any of these users and Superset will accept.
Add LDAP configuration to Trino
Trino is configured very similarly to Superset.
Fetch the existing TrinoCluster defintion from the Kubernetes API server and save it into a trino.yaml
file:
kubectl get trino trino -o yaml > trino.yaml
The trino.yaml
file should look similar to this
---
apiVersion: trino.stackable.tech/v1alpha1
kind: TrinoCluster
metadata:
name: trino
...
spec:
version: 396-stackable0.1.0
authentication:
method:
multiUser:
...
opa:
configMapName: opa
package: trino
catalogLabelSelector:
...
workers:
...
coordinators:
...
...
You can now delete the TrinoCluster. you recreate it later with the new configuration:
kubectl delete trino trino
Replace the multiUser
authentication method in your trino.yaml
with an ldap
method that references the openldap
AuthenticationClass:
spec:
authentication:
method:
ldap: (1)
authenticationClass: openldap (2)
1 | The new ldap authentication method replaces the previous multiUser authentication method |
2 | The authenticationClass property is referencing the AuthenticationClass openldap you created earlier |
Your trino.yaml
should now look similar to this
---
apiVersion: trino.stackable.tech/v1alpha1
kind: TrinoCluster
metadata:
name: trino
...
spec:
version: 396-stackable0.1.0
authentication:
method:
ldap:
authenticationClass: openldap
opa:
configMapName: opa
package: trino
catalogLabelSelector:
...
workers:
...
coordinators:
...
...
Now deploy the updated Trino cluster:
kubectl apply -f trino.yaml
Again, like with Superset, connect to Trino now (make sure that the StatefulSets are running). You will notice that the admin user cannot be used anymore, but the LDAP users alice and bob work!
Bonus: Reconfigure OPA to use the new LDAP users
This is a bonus step, and if you want you can skip straight to the next section: Log in with the new LDAP credentials
This step is not required for authentication by itself. But the demo stack you installed comes with an authorization configuration for Trino as well. Authorization on the platform is done using the Stackable Operator for OPA (OpenPolicyAgent).
Fetch the snippet as before:
kubectl get cm trino-opa-bundle -o yaml > trino-opa-bundle.yaml
Apply this patch:
data:
trino.rego: |
package trino
default allow = false
allow {
input.context.identity.user == "alice"
}
allow {
input.context.identity.user == "bob"
}
And apply the new bundle:
kubectl apply -f trino-opa-bundle.yaml
The OPA Operator will automatically detect the change and update the Trino authorization bundle.
Log in with the new LDAP credentials
Congratulations! You have configured Superset and Trino to use LDAP for authentication.
Log in with the LDAP user credentials alice:alice
or bob:bob
into Superset and Trino. Note also that the previously used admin
credentials no longer work.
If you skipped the OPA step, you will be able to log into Trino, but running queries will not work, as the LDAP users are not authorized to do so. If you did do this step, running queries with the LDAP users will also work.
That concludes the tutorial!
Summary
To summarize, you have done the following:
-
Written an AuthenticationClass for an existing LDAP server. The credentials are stored in a Secret with a SecretClass that is referenced in the AuthenticationClass.
-
Adapted the SupersetCluster spec to include the reference to the LDAP AuthenticationClass.
-
Adapted the TrinoCluster spec to include the reference to the AuthenticationClass.
The LDAP connection details only need to be written down once, in the AuthenticationClass. Making a product use this AuthenticationClass is then done by referencing the AuthenticationClass, so the configuration for LDAP is all in a single resource.