Integrate VMware Pinniped with Microsoft Entra ID for federated authentication on Kubernetes clusters.

Integrate VMware Pinniped with Microsoft Entra ID for federated authentication on Kubernetes clusters.

VMware Pinniped is an open-source authentication service for Kubernetes clusters. It allows you to plug external OpenID Connect (OIDC) or LDAP identity providers (IdP) into Kubernetes clusters so that you can control user access to those clusters.

Pinniped is composed of two parts.

  1. The Pinniped Supervisor is an OIDC server that allows users to authenticate with external identity providers (IDP).
  1. The Pinniped Concierge is a credential exchange API that takes as input a credential from the Pinniped Supervisor. authenticates the user via that credential, and returns another credential that is understood by the host Kubernetes cluster.

This article shows you how to install and integrate Pinniped with Microsoft Entra ID (Azure AD).

Prerequisites:

  1. Domain Name (FQDN) for Pinniped-Supervisor endpoint.
  2. K8s Layer 4 Load Balancer/Ingress.

Microsoft Entra (Azure AD)

Perform the following steps to prepare Microsoft Entra (Azure AD) for Pinniped integration:

  • Sign in to the Microsoft Azure portal.
  • Navigate to Microsoft Entra ID.
  • Select App registrations under the Manage side menu.
  • Enter the name of the application. For example, tkg-pinniped-supervisor-app.
  • Under Supported account types, select Accounts in this organizational directory only (Single tenant).

  • Select Register to create the app.
  • Select Token Configuration under the Manage menu.
  • Select Add groups claim > All groups (includes distribution lists but not groups assigned to the application).
  • Select Add to create the group claim.
  • Select the app name in the navigation to return to the app settings page.
  • Select the Endpoints tab and record the value in the OpenID Connect metadata document field.
  • Return to the app settings page and record the Application (client) ID.
  • Select Certificates & secrets under the Manage menu.

Create a new client secret and record this value.

  • Select Groups under the Manage side menu.
  • Identify or create a list of groups for each of the needed roles (tkg-operator, tkg-viewer, and tkg-editor).
  • Retrieve the corresponding object IDs for each group and add users to the groups accordingly.

Pinniped Supervisor

Expose the Pinniped Supervisor endpoint outside the K8s cluster

The supervisor endpoint should be exposed as HTTPS endpoints with proper TLS certificates through TCP LoadBalancer or Ingress.

Create a Load Balancer Service

Create a Service to expose port 8443 of the Supervisor app outside the cluster.

apiVersion: v1
kind: Service
metadata:
  name: pinniped-supervisor-loadbalancer
  namespace: pinniped-supervisor
spec:
  type: LoadBalancer
  selector:
    app: pinniped-supervisor
  ports:
  - protocol: TCP
    port: 443
    targetPort: 8443 

Configuring TLS for the Supervisor OIDC endpoints

The TLS certificate for the Supervisor should be created for the DNS Name (FQDN) that end users will use to make requests to the Supervisor.

Install cert-manager

kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.5.3/cert-manager.yaml

Create a TLS Certificate

Pinniped Supervisor needs TLS certificates that are trusted by the end users’ web browsers.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: selfsigned-cluster-issuer
  namespace: cert-manager
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: supervisor-tls-cert
  namespace: pinniped-supervisor
spec:
  secretName: supervisor-tls-cert
  dnsNames:
  - "$DNS_NAME"		
  issuerRef:
    name: selfsigned-cluster-issuer
    kind: ClusterIssuer

Install Pinniped Supervisor

Install the latest version of the Supervisor into the pinniped-supervisor namespace with default options:

kubectl apply -f https://get.pinniped.dev/v0.27.0/install-pinniped-supervisor.yaml

Configuring the Supervisor to act as an OIDC provider

At least one FederationDomain must be configured for the Supervisor to provide its functionality. You can create multiple FederationDomains in a single Pinniped Supervisor, as long as each has a unique issuer string.

When the user has started a single sign-on session with that FederationDomain which will last approximately 9 hours. The user will not need to authenticate again into any cluster or any cluster that chooses to trust the FederationDomain for authentication until the session expires.

Behind the scenes, the user’s client (e.g. kubectl) will only be given short-lived access to each cluster (approximately 5 minutes), but will automatically refresh those credentials without the need for user interaction.

---
apiVersion: idp.supervisor.pinniped.dev/v1alpha1
kind: OIDCIdentityProvider
metadata:
  namespace: pinniped-supervisor
  name: azure-ad
spec:
  # Specify the upstream issuer URL.
  issuer: https://login.microsoftonline.com/{Value}/v2.0

  authorizationConfig:
    additionalScopes: ["openid", "email", "profile"]
    allowPasswordGrant: false

  # Specify how claims are mapped to Kubernetes identities.
  claims:
    username: preferred_username
    groups: groups

  # Specify the name of the Kubernetes Secret that contains your
  # application's client credentials (created below).
  client:
    secretName: azure-ad-client-credentials
---
apiVersion: v1
kind: Secret
metadata:
  namespace: pinniped-supervisor
  name: azure-ad-client-credentials
type: secrets.pinniped.dev/oidc-client
stringData:
  clientID: "{Value}"
  clientSecret: "{Value}"
---
apiVersion: config.supervisor.pinniped.dev/v1alpha1
kind: FederationDomain
metadata:
  name: pinniped-supervisor-federation-domain
  namespace: pinniped-supervisor
spec:
  issuer: "https://{$DNS_NAME}/azure-ad"
  tls:
    secretName: supervisor-tls-cert

Check that the DNS, certificate, and FederationDomain are all working together by trying to fetch one of its endpoints. If it works it should return a JSON-formatted discovery response.

curl "https://{$DNS_NAME}/azure-ad/.well-known/openid-configuration"

Install Pinniped Concierge

Install the latest version of the Concierge CustomResourceDefinitions:

kubectl apply -f "https://get.pinniped.dev/v0.27.0/install-pinniped-concierge-crds.yaml"

Install the latest version of the Concierge into the pinniped-concierge namespace with default options:

kubectl apply -f "https://get.pinniped.dev/v0.27.0/install-pinniped-concierge-resources.yaml"

Configure the Concierge to trust the Supervisor’s FederationDomain for authentication by creating a JWTAuthenticator.

apiVersion: authentication.concierge.pinniped.dev/v1alpha1
kind: JWTAuthenticator
metadata:
  name: pinniped-jwt-authenticator
spec:
  issuer: https://{$DNS_NAME}/azure-ad # 
  audience: workload1 # Replace this with your own unique value.
  tls:
    certificateAuthorityData: #LS0tLS1CRUdJTiBDRVJUSUZJQ0...0tLQo=

Where:

  • $DNS_NAME  should be the issuer URL that was declared in the FederationDomain.
  • CA DATA is the public key of the signing CA or the public key of the Pinniped certificate in base64 format.

Configure RBAC rule for DevOps users

RBAC rules can be defined using usernames and/or group memberships.# Allow DevOps users to view everything in all namespaces.

kubectl create clusterrolebinding devops-view --clusterrole view --user devops01@domain.onmicrosoft.com

Install the Pinniped command-line tool

The Pinniped command-line tool is used to generate Pinniped-compatible kubeconfig files and is also an important part of the Pinniped-based login flow.

It must be installed by administrators setting up a Pinniped cluster as well as by users accessing a Pinniped-enabled cluster.

curl -Lso pinniped https://get.pinniped.dev/v0.27.0/pinniped-cli-linux-amd64 \
  && chmod +x pinniped \
  && sudo mv pinniped /usr/local/bin/pinniped

Generate a kubeconfig file

Create kubeconfig file for the workload clusters that can be used by the DevOps users. It does not contain any identity or credentials.

pinniped get kubeconfig --oidc-ca-bundle ca.pem > devops-view.yaml

Use the kubeconfig with kubectl 

DevOps users can run any kubectl command using a kubeconfig file that was provided to them.

kubectl --kubeconfig devops-view.yaml get namespaces

You should see:

  • The pinniped login oidc command is executed automatically by kubectl.
  • Pinniped opens your browser window and directs you to log in with your identity provider.
  • After you’ve logged in, you see a page telling you you have been logged in and may now close this tab.
  • In your shell, you see your clusters’ namespaces.

To see the username and group membership as understood by the Kubernetes cluster, you can use this command:

pinniped whoami --kubeconfig devops-view.yaml

Notes:

  • Pinniped kubeconfig files do not contain secrets.
  • Temporary OIDC session credentials such as ID, access, and refresh tokens are stored in:
  • ~/.config/pinniped/sessions.yaml (macOS/Linux)
  • %USERPROFILE%/.config/pinniped/sessions.yaml (Windows).

Reference: Pinniped Documentation

Leave a comment