How to setup RBAC in Ververica Platform using Dex & LDAP

Question

I want to use an enterprise LDAP server for authentication & authorization in Ververica Platform. How can I use Dex as the OIDC provider to make it work?

Answer

Note: This section applies to Ververica Platform Stream Edition 2.0 and later.

Ververica Platform standalone does not support direct integration with LDAP for authentication and authorization. In order to achieve this, one would need a bridge that can translate OIDC requests to LDAP queries and connect the gap. Dex is an open-source OIDC provider that has a rich connector ecosystem. It can serve as a middleware to authenticate and authorize against LDAP servers.

Here are the steps to configure Ververica Platform to use Dex & LDAP for RBAC.

1) LDAP Deployment

In this article, we setup an OpenLDAP server in Kubernetes to show how the connectivity works between Dex and LDAP. If you have already a running LDAP server, note down your ldap server host and the listening port, then you can skip the rest of this section.

The LDAP setup consists of three parts: the LDAP configuration, the LDAP deployment, and the service so that the LDAP server is accessible by Dex. We have three users with each of them being a member of the three different groups named admins, developers, and operations.

configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
    name: ldap
    namespace: auth
data:
    config.ldif: |
        dn: ou=People,dc=example,dc=org
        objectClass: organizationalUnit
        ou: People

        # User definitions

        dn: cn=admin,ou=People,dc=example,dc=org
        objectClass: person
        objectClass: inetOrgPerson
        sn: doe
        cn: admin
        mail: admin@example.org
        userpassword: password

        dn: cn=jane,ou=People,dc=example,dc=org
        objectClass: person
        objectClass: inetOrgPerson
        sn: doe
        cn: jane
        mail: jane@example.org
        userpassword: foo

        dn: cn=john,ou=People,dc=example,dc=org
        objectClass: person
        objectClass: inetOrgPerson
        sn: doe
        cn: john
        mail: john@example.org
        userpassword: bar

        # Group definitions

        dn: ou=Groups,dc=example,dc=org
        objectClass: organizationalUnit
        ou: Groups

        dn: cn=admins,ou=Groups,dc=example,dc=org
        objectClass: groupOfNames
        cn: admins
        member: cn=admin,ou=People,dc=example,dc=org

        dn: cn=developers,ou=Groups,dc=example,dc=org
        objectClass: groupOfNames
        cn: developers
        member: cn=jane,ou=People,dc=example,dc=org

        dn: cn=operations,ou=Groups,dc=example,dc=org
        objectClass: groupOfNames
        cn: operations
        member: cn=john,ou=People,dc=example,dc=org

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: ldap
    namespace: auth
spec:
    replicas: 1
    selector:
        matchLabels:
            app: ldap
    template:
        metadata:
            labels:
                app: ldap
        spec:
            containers:
                - name: ldap
                  image: osixia/openldap:1.4.0
                  args: ["--copy-service"]
                  ports:
                      - containerPort: 389
                  env:
                      - name: LDAP_TLS_VERIFY_CLIENT
                        value: "try"
                  volumeMounts:
                      - name: config
                        mountPath: /container/service/slapd/assets/config/bootstrap/ldif/custom/config.ldif
                        subPath: config.ldif
            volumes:
                - name: config
                  configMap:
                      name: ldap

service.yaml

apiVersion: v1
kind: Service
metadata:
    name: ldap
    namespace: auth
spec:
    selector:
        app: ldap
    ports:
        - name: ldap
          port: 389
          protocol: TCP

Now you can run kubectl apply -f <yaml file> to get the LDAP server up and running at ldap.auth.svc:389 in your Kubernetes cluster.

2) Dex Deployment

Dex has many connectors available. Here, we configure Dex to use the LDAP connector to connect to our LDAP server. If you are using your own LDAP server, adapt config accordingly. We also register Ververica Platform as a static client with its redirect URL. The service is used by Ververica Platform to communicate with Dex.

Tip: Secure the secret information for the Ververica Platform client in a production environment, as well as the network communication. See Related Information for more information.

configmap.yaml

apiVersion: v1
kind: ConfigMap
metadata:
    name: dex
    namespace: auth
data:
    config.yaml: |
        issuer: http://dex.auth.svc:5556/dex
        storage:
            type: sqlite3
            config:
                file: /storage/dex.db
        web:
            http: 0.0.0.0:5556
        
        oauth2:
            responseTypes: ["code", "token"]
            skipApprovalScreen: true

        connectors:
            - type: ldap
              name: Example LDAP
              id: ldap
              config:
                  host: ldap.auth.svc:389
                  insecureNoSSL: true

                  bindDN: cn=admin,dc=example,dc=org
                  bindPW: admin

                  usernamePrompt: Email Address

                  userSearch:
                      baseDN: ou=People,dc=example,dc=org
                      filter: "(objectClass=person)"
                      username: mail
                      idAttr: DN
                      emailAttr: mail
                      nameAttr: cn

                  groupSearch:
                      baseDN: ou=Groups,dc=example,dc=org
                      filter: "(objectClass=groupOfNames)"

                      userMatchers:
                          - userAttr: DN
                            groupAttr: member

                      nameAttr: cn

        staticClients:
            - id: vvp
              name: 'Ververica Platform'
              secret: hJQ8kTtZoDZKWIoX9lx7a4JK81LQ4DCB
              redirectURIs:
                  - 'http://ververica-platform.vvp.svc:8080/login/oauth2/code/dex'

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
    name: dex
    namespace: auth
spec:
    replicas: 1
    selector:
        matchLabels:
            app: dex
    template:
        metadata:
            labels:
                app: dex
        spec:
            containers:
                - name: dex
                  image: ghcr.io/dexidp/dex:v2.30.2
                  command: ["dex"]
                  args: ["serve", "/etc/dex/config.yaml"]
                  ports:
                      - containerPort: 5556
                  volumeMounts:
                      - name: config
                        mountPath: /etc/dex/config.yaml
                        subPath: config.yaml
                      - name: storage
                        mountPath: /storage
            volumes:
                - name: config
                  configMap:
                      name: dex
                - name: storage
                  emptyDir: {}

service.yaml

apiVersion: v1
kind: Service
metadata:
    name: dex
    namespace: auth
spec:
    selector:
        app: dex
    ports:
        - name: dex
          port: 5556
          protocol: TCP

Similarly, you can run kubectl apply -f <yaml file> to get the Dex server up and running at dex.auth.svc:5556 in your Kubernetes cluster.

3) VVP Configuration

Finally, we add the auth part to point to our Dex deployment. The issuerUri configuration is enough for Ververica Platform to resolve available common OIDC request endpoints. We are also setting the admins of the Ververica Platform to be the users that are members of the group named admins.

Tip: Some of the OIDC request endpoints are only for application to application communication, whereas some of the endpoints are meant for public access to an end-user, such as redirect and authorization URI's. Explicitly specify internal and external DNS names for OIDC request endpoints accordingly to optimize the network costs.

vvp:
    auth:
        enabled: true
        admins:
            - group:admins
        oidc:
            groupsClaim: groups
            registrationId: dex
            registration:
                clientId: vvp
                clientSecret: hJQ8kTtZoDZKWIoX9lx7a4JK81LQ4DCB
                authorizationGrantType: authorization_code
                redirectUri: "{baseUrl}/{action}/oauth2/code/{registrationId}"
                clientAuthenticationMethod: basic
                scope:
                    - openid
                    - groups
                    - email
            provider:
                issuerUri: http://dex.auth.svc:5556/dex
                userNameAttribute: email

Note: please use the redirectUri above literally as it is, Ververica Platform takes care of the placeholder substatution automatically.

4) RBAC Configuration

Now that Ververica Platform is set to use Dex for RBAC, all the unauthenticated page requests will be redirected to Dex's login page.

Screenshot_2022-01-18_at_12.04.59

After the user credentials that are stored in LDAP are entered, it will redirect the requester back to the Ververica Platform. Admins of Ververica Platform can then set up RBAC using the user and/or group information retrieved from the LDAP server via Dex.

Screenshot_2022-01-18_at_12.10.11

Related Information