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 exising LDAP installation with Stackable supported products. You can learn more about authentication in the Stackable Platform on the concepts page.
Prerequisites:
- 
a k8s cluster available, or kind installed 
- 
stackablectl installed 
- 
basic knowledge of how to create resources in Kubernetes (i.e. kubectl apply -f <filename>.yaml) and inspect them (kubectl getor a tool like k9s)
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 stackablectl Stacks.
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 --kind-cluster (or -k) flag to let stackablectl deploy one for you.
stackablectl stack install trino-superset-s3This command will take a few minutes to complete.
| The stack installed here is used in the trino-tax-datademo. 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 svc 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-openldapInspect
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,bobldapadmin 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 openldapstack instead oftutorial-openldapwhich 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-ldapStack | 
| 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 SecretClasswe are creating that is referred to by the Secret | 
| 2 | This determines the namespace in which the referenced Secretwill be looked for. In this case it searches for aSecretin 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.yamlThe 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 supersetModify your superset.yaml to include this new authenticationConfig property under the spec:
spec:
  authenticationConfig:            (1)
    authenticationClass: openldap  (2)
    userRegistrationRole: Admin    (3)| 1 | The new authenticationConfigsection which configures how Superset is authenticating users | 
| 2 | The authenticationClassproperty is referencing the AuthenticationClassopenldapyou 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.yamlConnect 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.yamlThe 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 trinoReplace 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 ldapauthentication method replaces the previousmultiUserauthentication method | 
| 2 | The authenticationClassproperty is referencing the AuthenticationClassopenldapyou 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.yamlAgain, 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.yamlApply 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.yamlThe 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.