Enterprise Kubernetes, delivered

Tectonic ships with CoreOS's signature automated operations, runs multi-cloud, and is the fastest, most secure path to Kubernetes.

LDAP User Management

Overview

Tectonic Identity is an authentication service for both Tectonic Console and kubectl. It facilitates communication to the API server on the end user's behalf. All Tectonic clusters enable Role Based Access Control (RBAC). Tectonic Identity can be mapped to an LDAP service ensuring RBAC role bindings for groups and users map to your exiting LDAP system.

This document describes managing users and access control in Tectonic and Kubernetes using LDAP.

Identity LDAP configuration

Tectonic Identity LDAP integration is configured through the Tectonic console. In order to integrate with LDAP, you'll need the following:

  • Your LDAP server host name and port
  • An LDAP service account capable of querying for users and groups
  • An LDAP base distinguished name (dn) representing where to start the search from for users and groups
  • The attributes used to describe users and groups (e.g. mail, username, etc)
  • (Optional) The root CA if certificate CA verification is desired

Follow these steps in the Tectonic UI to enable LDAP in your cluster:

First navigate to Cluster Settings under Administration.

Next click the LDAP link and add your LDAP host. Specify whether your LDAP host uses SSL; if so, specify whether the certificate should be verified against a trusted root CA and click Continue. Add an LDAP service account capable of querying for groups and users and click Continue.

Configure the user search criteria by adding the following fields:

  • Base DN: The root LDAP directory to begin the user search from.
  • Filter: Filter(s) applied to every user search to limit the results. For example, when a user search executes, object results could be limited to those with an objectClass of person.
  • Username: The field used when searching for users. This is the field users will use to login. For example, a commonName (assuming its unique) or a mail (email) address.
  • Attribute: The field mapping to a user's uid.
  • Email Attribute: The field mapping to a user's email address.
  • Name Attribute: The field mapping to a user's display name.

The example configuration above translates to the following diagram:

Continue to the group search configuration; add the following fields:

  • Base DN: The root LDAP directory to begin the group search from.
  • Filter: Filter(s) applied to every group search to limit the results. For example, when a group search executes, object results could be limited to those with an objectClass of groupOfNames.
  • User Attribute: The user field that a group uses to identify a user is part of a group. For example, groups that specify each member as member: cn=john,dc=example,dc=org in the LDAP directory, are using the Distinguished Name (DN) attribute.
  • Member Attribute: The member field associating a user, using the User Attribute mentioned above, with the group.
  • Name Attribute: The field mapping to a group's display name.

The example configuration above translates to the following diagram:

Input a valid user and click Test Configuration to verify that users and groups are correctly configured. If the query does not return expected results, see the Troubleshooting section, below.

The following is a sample LDAP directory used in the test steps.

# john, example.org
dn: cn=john,dc=example,dc=org
objectClass: person
objectClass: inetOrgPerson
uid: john.doe
mail: john.doe@example.org
cn: john
sn: doe
userPassword:: e1NTSEF9dkltSFZkNTgzN3JBaVdEZ2xyVXFyeE9nM1FETHBkM04=

# jane, example.org
dn: cn=jane,dc=example,dc=org
objectClass: person
objectClass: inetOrgPerson
uid: jane.doe
mail: jane.doe@example.org
cn: jane
sn: doe
userPassword:: e1NTSEF9dkltSFZkNTgzN3JBaVdEZ2xyVXFyeE9nM1FETHBkM04=

# tstgrp, groups, example.org
dn: cn=tstgrp,ou=groups,dc=example,dc=org
objectClass: top
objectClass: groupOfNames
member: cn=john,dc=example,dc=org
cn: tstgrp

In this example the user john.doe's dn is in tstgrp, but jane.doe is in no groups. You can query for these users in the Test Configuration page to verify this.

From the Test Configuration page, click Continue to see instructions on updating the given Tectonic Identity. Click My Account. From the Profile page, download the new and existing configuration file. Keep a backup of the existing config in case something goes wrong during the update.

Applying a new Tectonic Identity configuration

To apply a new Tectonic Identity configuration to your Kubernetes cluster use kubectl apply:

$ kubectl apply -f ~/Downloads/new-tectonic-config.yaml

configmap "tectonic-identity" configured

Restart the Tectonic Identity pods for the changes to take effect. The following command triggers a rolling update and attaches the current date as an annotation. Verify the pods are patched.

$ kubectl patch deployment tectonic-identity \
    --patch "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}" \
    --namespace tectonic-system

"tectonic-identity" patched

You can now log out of Tectonic Console and log back in using LDAP.

In order for an LDAP user to have any access to Kubernetes resources, both from the console and kubectl, you must setup role bindings. See Configuring Access for more details.

Using kubectl as an LDAP user

To use kubectl as an LDAP user:

  1. Log in to your Tectonic Console as the desired user.
  2. Navigate to My Account
  3. Verify your identity and download kubectl configuration.
  4. Set the KUBECONFIG environment variable to the kubectl configuration file. For example:
  export KUBECONFIG=~/Download/kubectl-config

Until otherwise modified, you can still use your static account for further administrative setup.

Configuring access

Access configuration requires understanding Kubernetes Roles, RoleBindings, ClusterRoles, and ClusterRoleBindings. LDAP-based users do not alter this model. LDAP usernames and groups can be used with Kubernetes bindings; visit the Kubernetes authorization docs to learn how to setup these configurations.

Basic access example

The following shows an example of granting user john.doe@example.org basic access to the cluster.

Add a role named support-readonly that can run commands get, logs, list, and watch for namespaces and pods:

apiVersion: rbac.authorization.k8s.io/v1alpha1
kind: ClusterRole
metadata:
  name: support-readonly
rules:
- apiGroups:
  - ""
  attributeRestrictions: null
  resources:
  - namespaces
  - namespaces/finalize
  - namespaces/status
  - pods
  verbs:
  - get
  - logs
  - list
  - watch

Bind the role to john.doe's group tstgrp:

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1alpha1
metadata:
  name: support-reader
  namespace: kube-system
subjects:
  - kind: Group
    name: tstgrp
roleRef:
  kind: ClusterRole
  name: support-readonly
  apiGroup: rbac.authorization.k8s.io

Tectonic Console and kubectl now reflect the updated role and binding:

$ kubectl --kubeconfig=johnDoeConfig --namespace=tectonic-system get pods

NAME                                         READY     STATUS    RESTARTS   AGE
default-http-backend-4080621718-f3gql        1/1       Running   0          2h
kube-version-operator-2694564828-crpz4       1/1       Running   0          2h
...

An attempt to access a resource or perform a command to which a user does not have access will be rejected by the API server:

$ kubectl --kubeconfig=johnDoeConfig --namespace=tectonic-system get services

Error from server (Forbidden): the server does not allow access to the requested resource (get services)

Troubleshooting

To troubleshoot users and groups configuration, check the tectonic-console's logs to see what LDAP query is being sent.

Locate the Console's pod name:

$ kubectl --namespace=tectonic-system get pods

NAME                                         READY     STATUS    RESTARTS   AGE
tectonic-console-3824021701-50j0x            1/1       Running   0          2h
tectonic-identity-3193269714-bg19p           1/1       Running   0          24m
tectonic-ingress-controller-99581103-rd0cj   1/1       Running   0          2h

Using kubectl, tail the logs for the console pod:

$ kubectl --namespace=tectonic-system logs -f tectonic-console-3824021701-50j0x

2017/01/29 22:29:47 ldap: no results returned for filter: "(&(objectClass=person)(mail=jane2.doe@example.org))"
2017/01/29 22:30:16 ldap: groups search with filter "(&(objectClass=groupOfNames)(member=john.doe@example.org))" returned no groups

In the above example, two issues are visible. First, jane2.doe@example.org was not found in the LDAP directory. Second, a group search is attempting to check if the member field contains john.doe@example.org. However, the original example and LDAP server output, shown earlier in this document, qualify members based on DN rather than mail.