Skip to content

A Webhook Token Authentication plugin for kubernetes to use LDAP as authentication source

License

Notifications You must be signed in to change notification settings

gyselroth/kube-ldap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

95 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

kube-ldap

Build Status Coverage Status License: MIT

A Webhook Token Authentication plugin for kubernetes, written in javascript, to use LDAP as authentication source.

Description

The kube-ldap webhook token authentication plugin can be used to integrate username/password authentication via LDAP for your kubernetes cluster. It exposes two API endpoints:

  • /auth
    • HTTP basic authenticated requests to this endpoint result in a JSON Web Token, signed by the webhook, including the username and uid of the authenticated user.
    • The issued token can be used for authenticating to kubernetes.
  • /token
    • Is called by kubernetes (see TokenReview) to verify the token used for authentication.
    • Verifies the integrity of the JWT (using the signature) and returns a TokenReview response containing the username, uid, group memberships and extra attributes (if configured) of the authenticated user.

Deployment

The recommended way to deploy kube-ldap is deplyoing kube-ldap in kubernetes itself using the gyselroth/kube-ldap docker image.

Example YAML for kubernetes (secrets, deployment including tls termination and service):

apiVersion: v1
data:
  key: #base64 encoded jwt key (see "Configuration" in README)
kind: Secret
metadata:
  name: kube-ldap-jwt-key
  namespace: kube-system
type: Opaque
---
apiVersion: v1
data:
  binddn: #base64 encoded bind dn (see "Configuration" in README)
  bindpw: #base64 encoded bind password (see "Configuration" in README)
kind: Secret
metadata:
  name: kube-ldap-ldap-bind-credentials
  namespace: kube-system
type: Opaque
---
apiVersion: v1
data:
  cert.pem: #base64 encoded certificate (pem)
  key.pem: #base64 encoded private key (pem)
kind: Secret
metadata:
  name: kube-ldap-tls
  namespace: kube-system
type: Opaque
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  labels:
    k8s-app: kube-ldap
  name: kube-ldap
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: kube-ldap
  template:
    metadata:
      labels:
        k8s-app: kube-ldap
    spec:
      volumes:
      - name: kube-ldap-tls
        secret:
          secretName: kube-ldap-tls
      containers:
      - env:
        - name: LDAP_URI
          value: #ldap uri (see "Configuration" in README)
        - name: LDAP_BINDDN
          valueFrom:
            secretKeyRef:
              name: kube-ldap-ldap-bind-credentials
              key: binddn
        - name: LDAP_BINDPW
          valueFrom:
            secretKeyRef:
              name: kube-ldap-ldap-bind-credentials
              key: bindpw
        - name: LDAP_BASEDN
          value: #ldap base dn (see "Configuration" in README)
        - name: LDAP_FILTER
          value: #ldap filter(see "Configuration" in README)
        - name: LOGLEVEL
          value: info
        - name: JWT_KEY
          valueFrom:
            secretKeyRef:
              name: kube-ldap-jwt-key
              key: key
        - name: JWT_TOKEN_LIFETIME
          value: #jwt token lifetime (see "Configuration" in README)
        image: gyselroth/kube-ldap:latest # Better use fixed version tag here since 'latest' can point to new major releases with breaking changes
        volumeMounts:
          - name: kube-ldap-tls
            mountPath: "/etc/ssl/kube-ldap"
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 5
          periodSeconds: 10
        name: kube-ldap
        ports:
        - containerPort: 8081
---
apiVersion: v1
kind: Service
metadata:
  labels:
    k8s-app: kube-ldap
  name: kube-ldap
  namespace: kube-system
spec:
  ports:
  - port: 8081
    protocol: TCP
    targetPort: 8081
  selector:
    k8s-app: kube-ldap
  type: ClusterIP

Configuration

kube-ldap

kube-ldap itself can be configured via environment variables.

List of configurable values:

Setting Description Environment Variable Default Value
config.port HTTP port to listen PORT 8081 (8080 if TLS is disabled)
config.loglevel Loglevel for winston logger. CAUTION: debug loglevel may log sensitive parameters like user passwords LOGLEVEL info
config.tls.enabled Enable TLS (HTTPS). DO NOT DISABLE IN PRODUCTION UNLESS YOU HAVE A TLS REVERSE PROXY IN PLACE TLS_ENABLED ("true" or "false") true
config.tls.cert Path to certificate (pem) to use for TLS (HTTPS) TLS_CERT_PATH /etc/ssl/kube-ldap/cert.pem
config.tls.key Path to private key (pem) to use for TLS (HTTPS) TLS_KEY_PATH /etc/ssl/kube-ldap/key.pem
config.tls.ca Optional: Path to ca certificate (pem) to use for TLS (HTTPS) TLS_CA_PATH none
config.ldap.uri URI of LDAP server LDAP_URI ldap://ldap.example.com
config.ldap.binddn DN of LDAP bind user connection LDAP_BINDDN uid=bind,dc=example,dc=com
config.ldap.bindpw Password of LDAP bind user LDAP_BINDPW secret
config.ldap.baseDn Base DN for LDAP search LDAP_BASEDN dc=example,dc=com
config.ldap.filter Filter for LDAP search LDAP_FILTER (uid=%s)
config.ldap.timeout Timeout for LDAP connections & operations (in seconds) LDAP_TIMEOUT 0 (infinite for operations, OS default for connections)
config.mapping.username Name of ldap attribute to be used as username in kubernetes TokenReview MAPPING_USERNAME uid
config.mapping.uid Name of ldap attribute to be used as uid in kubernetes TokenReview MAPPING_UID uid
config.mapping.groups Name of ldap attribute to be used for groups in kubernetes TokenReview MAPPING_GROUPS memberOf
config.mapping.extraFields Comma separated list of additional ldap attributes to be used for extra in kubernetes TokenReview MAPPING_EXTRAFIELDS []
config.mapping.username Name of Ldap attribute to be used as username in kubernetes TokenReview MAPPING_USERNAME uid
config.jwt.key Key for signing the JWT. DO NOT USE THE DEFAULT VALUE IN PRODUCTION JWT_KEY secret
config.jwt.tokenLifetime Seconds until token a expires JWT_TOKEN_LIFETIME 28800
config.prometheus.username Username for prometheus exporter basic auth (use empty string to disable basic auth) PROMETHEUS_USERNAME prometheus
config.prometheus.password Password for prometheus exporter basic auth (use empty string to disable basic auth) PROMETHEUS_PASSWORD secret
config.prometheus.nodejsProbeInterval Probe interval for nodejs metrics in milliseconds PROMETHEUS_NODEJS_PROBE_INTERVAL 10000

kubernetes

Configure your kubernetes apiserver to use the kube-ldap webhook for authentication using the following configuration file.

# clusters refers to the remote service.
clusters:
  - name: kube-ldap
    cluster:
      server: https://your-kube-ldap-url/token

# users refers to the API server's webhook configuration.
users:
  - name: apiserver

# kubeconfig files require a context. Provide one for the API server.
current-context: webhook
contexts:
- context:
    cluster: kube-ldap
    user: apiserver
  name: webhook

kubectl

You can either use kube-ldap-client-go-exec-plugin, a kubectl plugin (client-go credential plugin) doing the authentication for you, or you can do it manually.

To configure kubectl for manual authentication initially:

TOKEN=$(curl https://your-kube-ldap-url/auth -u your-username)
kubectl config set-cluster your-cluster --server=https://your-apiserver-url [...]
kubectl config set-credentials your-cluster-ldap --token="$TOKEN"
kubectl config set-context your-cluster --cluster=your-cluster --user=your-cluster-ldap

To refresh your token after expiration:

TOKEN=$(curl https://your-kube-ldap-url/auth -u your-username)
kubectl config set-credentials your-cluster-ldap --token="$TOKEN"

Development

Requirements

  • nodejs
  • yarn

Development Server

During development an auto-reloading development server (using babel watch) can be used.

Remember to set the environment variables required to configure kube-ldap. E.g.:

LDAP_URI=ldap://ldap.example.local TLS_ENABLED=false yarn start

Test

To run automated tests using jest you can use yarn:

yarn test

Build

kube-ldap can be built via yarn, to get native nodejs code, or via docker (which uses yarn), to get a docker image.

Either way the build process lints the code (including flow type annotations) before building. When building via docker the process also includes running the automated tests. If any of these steps fail, the build will fail too.

yarn

When using yarn, it places the build output in ./build/ directory.

yarn build

docker

When using docker, the ./Dockerfile is used to build an image.

docker -t kube-ldap build .