Couchbase User Authentication

A tutorial for configuring Couchbase user authentication and authorization using the Autonomous Operator.

Tutorials are accurate at the time of writing but rely heavily on third party software. Tutorials are provided to demonstrate how a particular problem may be solved. Use of third party software is not supported by Couchbase. For further help in the event of a problem, contact the relevant software maintainer.

Overview

This tutorial describes how to use the Autonomous Operator to create authenticated users and bind them to specific roles to provide different levels of authorization.

User authentication can be provided by Couchbase itself or an external LDAP service (such as OpenLDAP). The Autonomous Operator refers to Couchbase Authentication as the local domain, and LDAP Authentication as the external domain.

Couchbase Authentication

The local Couchbase domain performs internal password management and requires a password to be provided during user creation.

Create a User Secret

When using Couchbase for authentication, a Kubernetes Secret containing the user password needs to be created.

The following command creates a secret with mypass set as the password:

$ cat << EOF | kubectl create -f -
---
apiVersion: v1
kind: Secret
metadata:
  name: my-password-secret
type: Opaque
data:
  password: bXlwYXNz        # mypass
EOF

Create and Authorize a User

Utilizing the Secret from the previous step, create a user and bind it to a set of roles which could be used for basic application development.

The following command creates a new user, a new group containing the roles, and a new role binding to aggregate the the user and the group together:

$ cat << EOF | kubectl apply -f -
---
apiVersion: couchbase.com/v2
kind: CouchbaseUser
metadata:
  name: developer (1)
spec:
  fullName: "Jane Doe"
  authDomain: local
  authSecret: my-password-secret (2)
---
apiVersion: couchbase.com/v2
kind: CouchbaseGroup
metadata:
  name: my-group (3)
spec:
  roles: (4)
  - name: replication_admin
  - name: data_reader
  - name: data_writer
    bucket: default
---
apiVersion: couchbase.com/v2
kind: CouchbaseRoleBinding
metadata:
  name: my-group-binding (5)
spec:
  subjects:
  - kind: CouchbaseUser
    name: developer
  roleRef:
    kind: CouchbaseGroup
    name: my-group
EOF
1 The new user, with username developer.
2 The Secret from the previous step.
3 The new group, with name my-group.
4 The Couchbase roles that we want to assign to the new user.
5 The new role binding, with name my-group-binding, that binds the new user (developer) with the new group (my-group).

To test that the new user was created and assigned the desired roles, connect to the Couchbase Web Console and log in as user developer with password mypass.

# forward the ui port of a couchbase pod
$ kubectl port-forward --namespace default <couchbase-pod-name> 8091:8091

# open localhost:8091

Create and Authorize Additional Users

Additional users can be added to the development group with a similar set of roles. To authorize the additional users with the same roles as the user from the previous section, you only need to update the role binding to include the new users, since the group is already created.

The following command creates two new users, and updates the role binding to bind them to the group that was created in the previous section:

$ cat << EOF | kubectl apply -f -
---
apiVersion: couchbase.com/v2
kind: CouchbaseUser
metadata:
  name: admin
spec:
  fullName: "Joe Day"
  authDomain: local
  authSecret: my-password-secret
---
  apiVersion: couchbase.com/v2
  kind: CouchbaseUser
  metadata:
    name: security
  spec:
    fullName: "Bin Nash"
    authDomain: local
    authSecret: my-password-secret
---
apiVersion: couchbase.com/v2
kind: CouchbaseRoleBinding
metadata:
  name: my-group-binding
spec:
  subjects: (1)
  - kind: CouchbaseUser
    name: developer
  - kind: CouchbaseUser
    name: admin
  - kind: CouchbaseUser
    name: security
  roleRef:
    kind: CouchbaseGroup
    name: my-group
EOF
1 Updates the role binding to include the two new users alongside the user from the previous section. The group now contains three users, and each user is bound to same set of roles.
In this example, the two new users reference the same Secret as the user from the previous section. In production, you will want to create an individual secret for each user.

At this point, you can modify the roles of all three users at once by updating the group. To do this, use the following command to edit the CouchbaseGroup resource and add the security_admin role:

$ kubectl edit couchbasegroup my-group

...
# Please edit the object below. Lines beginning with a '#' will be ignored,
spec:
  roles:
  - name: replication_admin
  - bucket: '*'
    name: data_reader
  - bucket: default
    name: data_writer
  - name: security_admin

LDAP Authentication

Couchbase is able to delegate authentication to an external LDAP service. Using LDAP for authentication adds an additional level of security and places password management within an external domain.

Running an OpenLDAP server

The OpenLDAP service will be created using Helm. To seed the service with users and groups, a value override file needs to be created:

$ echo "
customLdifFiles:
  01-default-users.ldif: |-
    dn: ou=People,dc=example,dc=org
    objectClass: organizationalUnit
    ou: People

    dn: uid=jbrown,ou=People,dc=example,dc=org
    objectclass: top
    objectclass: person
    objectclass: organizationalPerson
    objectclass: inetOrgPerson
    uid: jbrown
    cn: James
    sn: Brown
    userPassword: password" > ldap-values.yaml

Now run the OpenLDAP server with the custom values in ldap-values.yaml:

# helm 3.1
$ helm install my-release --set adminPassword=ldappassword -f ldap-values.yaml stable/openldap

Couchbase will communicate with the OpenLDAP server using the service created by the Helm Chart.

Run helm status to see the service endpoint:

$ helm status my-release

NOTES:
OpenLDAP has been installed. You can access the server from within the k8s cluster using:

  my-release-openldap.default.svc.cluster.local:389

The Couchbase service will also need to authenticate with OpenLDAP in order to query for user records and groups. Therefore, a kubernetes secret will need to be created with the adminPassword which has been set to ldappassword:

$ cat << EOF | kubectl create -f -
---
apiVersion: v1
data:
  password: bGRhcHBhc3N3b3Jk      # ldappassword
kind: Secret
metadata:
  name: ldap-secret
type: Opaque

Edit the CouchbaseCluster Resource

The LDAP configuration must be added to the CouchbaseCluster resource in order to authenticate external users. Add the OpenLDAP service endpoint as one of the hosts along with organizational information required to communicate with the service.

apiVersion: couchbase.com/v2
kind: CouchbaseCluster
metadata:
  name: cb-example
spec:
  image: couchbase/server:6.5.0
  security:
    rbac:
      managed: true
    ldap:
      hosts:
      - my-release-openldap.default.svc.cluster.local
      port: 389
      encryption: None
      bindDN: "cn=admin,dc=example,dc=org"
      bindSecret: ldap-secret
      userDNMapping:
        template: "uid=%u,ou=People,dc=example,dc=org"
   ...
In production you will want to set encryption to StartTLS or TLS.

After updating the CouchbaseCluster resource, you can test LDAP authentication from the Couchbase Web Console. Start by connecting to the Couchbase Web Console.

# forward the ui port of a couchbase pod
$ kubectl port-forward --namespace default <couchbase-pod-name> 8091:8091

# open localhost:8091

After logging in, go to the Security view, and click LDAP. Under "Test User Authentication", enter the username jbrown and the password password, and then click Test User Authentication. Couchbase Server will map the specified username to an LDAP DN, and perform authentication on the LDAP server. If your LDAP configuration is set up correctly, you’ll get a notification that the test was successful.

Grant Roles to an LDAP User

LDAP users are added to Couchbase using the same steps as local users except that the authDomain is set to external.

Create a CouchbaseUser resource for the LDAP user:

$ cat << EOF | kubectl apply -f -
---
apiVersion: couchbase.com/v2
kind: CouchbaseUser
metadata:
  name: jbrown
spec:
  fullName: "James Brown"
  authDomain: external
EOF

The next step is to bind the user to a group that contains the roles that you want the user to have. If you were to use the same groups and bindings from the local users section, the command would be as follows:

$ cat << EOF | kubectl apply -f -
---
apiVersion: couchbase.com/v2
kind: CouchbaseRoleBinding
metadata:
  name: my-group-binding
spec:
  subjects:
  - kind: CouchbaseUser
    name: developer
  - kind: CouchbaseUser
    name: admin
  - kind: CouchbaseUser
    name: security
  - kind: CouchbaseUser
    name: jbrown
  roleRef:
    kind: CouchbaseGroup
    name: my-group
EOF

If you followed this setup, the LDAP user has the same roles as the other uses, even though it relies on a different authentication path (external vs local).

You can test authentication/authorization by logging into the Couchbase Web Console with the username jbrown and password password.