OIDC Connecting Kubernetes to Google, Okta, and Active Directory
Imagine you have a big team, and creating individual user accounts inside your Kubernetes cluster is becoming a major headache. OpenID Connect (OIDC) solves this problem by allowing your team to use their existing company emails and passwords to log into the cluster safely. It is an industry standard that makes life easier for developers and makes security much stronger for administrators. By outsourcing authentication to a centralized Identity Provider (IdP) like Google Workspace, Okta, or Active Directory, you eliminate the need to manage local cluster credentials.
Think of the Kubernetes cluster as a highly secure office building and the API Server as the security guard at the front desk. Instead of the guard keeping a giant book of every employee’s face and ID (which is hard to manage), the building partners with a trusted external ID agency (like Google or Okta).
When you arrive, you show a stamped badge (a JWT token) from that agency. The guard just checks the agency’s stamp to see if it’s valid and lets you in without needing to know your personal life history!
Quick Reference
- OIDC: OpenID Connect, an identity layer built on top of the OAuth 2.0 protocol.
- JWT Token: JSON Web Token, the digital “badge” carrying user details (known as claims).
- API Server Flags: You strictly need to configure
--oidc-issuer-url,--oidc-client-id, and--oidc-username-claim. - RBAC: Role-Based Access Control is still 100% required. OIDC authenticates who you are; RBAC authorizes what you can do.
OpenID Connect (OIDC) solves this by allowing you to outsource Kubernetes authentication to a centralized Identity Provider (IdP) like Google Workspace, Okta, or Active Directory.
How OIDC Works in Kubernetes
Kubernetes does not have its own identity database. By configuring OIDC, the Kubernetes API server acts as a trusting client of your IdP.
The standard flow looks like this:
- Authentication: A user initiates a login via
kubectl. A browser window opens, directing the user to the IdP (Google, Okta, AD). - Token Issuance: Upon successful login, the IdP returns an
id_token(a JWT – JSON Web Token) and arefresh_token. - API Request:
kubectlattaches theid_tokenas a Bearer token in the Authorization header of requests to the Kubernetes API server. - Verification: The API server verifies the token’s signature using the IdP’s public keys (retrieved via the IdP’s discovery URL).
- Authorization: Once verified, the API server extracts the user’s identity and group membership from the token’s claims and evaluates them against Kubernetes RBAC (Role-Based Access Control) policies.
Let’s break down the basic steps to get this working:
- Step 1: Get an Identity Provider. You need an account with Google Workspace, Okta, or Azure AD. You create an “App” there to get a
Client IDandClient Secret. - Step 2: Teach Kubernetes about the Provider. You must edit the Kubernetes API server configuration. This usually means editing the
/etc/kubernetes/manifests/kube-apiserver.yamlfile on your control plane node and adding OIDC flags. - Step 3: Tell Kubernetes what the user can do. Just because someone can log in doesn’t mean they can delete pods! You have to write a
ClusterRoleBindingthat says “User Alice from Okta is a cluster-admin.” - Step 4: User Login. The user needs a helper tool like kubelogin (also known as
oidc-login) to fetch the token and securely update theirkubeconfigfile.
Core API Server Configuration
For advanced architects, OIDC integration involves a deep understanding of JWT validation, secure Public Key Infrastructure (PKI) handling, and custom claim mappings.
To enable OIDC, the Kubernetes API server requires specific startup flags in the kube-apiserver manifest:
--oidc-issuer-url: The URL of your IdP (e.g.,https://accounts.google.com). The API server fetches the OIDC discovery document (/.well-known/openid-configuration) from this URL to find thejwks_uri(JSON Web Key Set) for cryptographic signature verification. This URL must perfectly match theissclaim in the JWT.--oidc-client-id: The Client ID generated when you registered Kubernetes as an application in your IdP.--oidc-username-claim: The JWT claim to use as the Kubernetes username (oftenemailorsub).--oidc-groups-claim: The JWT claim that contains the user’s group memberships (e.g.,groups). Custom Claim Mapping: If your IdP sends group data in a custom claim, map it using--oidc-groups-claim=custom_groups_claim.--oidc-username-prefix/--oidc-groups-prefix: Optional prefixes added to the claims to prevent clashes with built-in Kubernetes system names. Prefixing is absolutely crucial (e.g., setting the group prefix tooidc:) to prevent privilege escalation where an external IdP user spoofs an internal Kubernetes system group likesystem:masters.- Token Refresh Handling: ID tokens are intentionally short-lived (usually 1 hour). A refresh token must be securely stored in the
kubeconfigvia theauth-providerexec plugin. The CLI handles the PKCE flow and refresh logic transparently. Ensure your IdP is configured to grant theoffline_accessscope, which is strictly required to issue refresh tokens.
DevSecOps Architect level
At a production-grade DevSecOps level, direct API server modification isn’t always feasible (e.g., using managed services like EKS or GKE). Here is how you handle enterprise environments:
- Managed Clusters: For GKE, use the native “GKE Identity Service”. For Amazon EKS, associate an OIDC identity provider directly via the AWS Console or Terraform.
- Impersonation Proxies: If you cannot modify the API Server due to strict enterprise constraints, deploy an OIDC impersonation proxy like Pinniped. Pinniped provides a standardized, cluster-native way to manage identities across massive fleets of clusters.
- Legacy AD Integration: Traditional On-Premises LDAP/AD does not speak OIDC natively. You must use an identity broker. Dex (an open-source CNCF project) is the industry standard here. Dex connects to your LDAP server, speaks LDAP on the backend, and exposes a fully compliant OIDC endpoint to the Kubernetes API server.
- The Client Side: Kubernetes does not handle the browser-based login dance natively. The most widely adopted community standard is kubelogin (often installed via
krew).
Connecting Specific Identity Providers
1. Google Workspace / Cloud Identity
Google provides a highly reliable OIDC endpoint.
- Setup: You must create an OAuth 2.0 Client ID in the Google Cloud Console. Select “Desktop app” or “Web application” depending on how your CLI helper tools are configured.
- Claims: Google standardizes on the
emailclaim for the username. - Limitation: Google’s default OIDC tokens do not inherently include a
groupsclaim. If you need group-based RBAC with Google, you typically have to use a shim/broker like Dex or rely on a managed service like GKE, which integrates Google Groups directly.
2. Okta
Okta is highly flexible and built for enterprise OIDC workflows.
- Setup: Create a new “Native” or “Web” Application in Okta. Assign the app to the relevant users or groups.
- Claims: Ensure you configure Okta’s Authorization Server to include a custom
groupsclaim in theid_token. You will need to write a simple Okta expression (likeMatches regex ".*") to populate this claim. - API Server Flags: Map
--oidc-username-claim=emailand--oidc-groups-claim=groups.
3. Active Directory (On-Prem and Azure AD / Entra ID)
Integrating Microsoft environments depends on where the directory lives.
- Azure AD (Entra ID): Azure provides native OIDC support. Register an Enterprise Application, configure API permissions to read user profiles and groups, and ensure the “Group claim” is emitted in the token.
- Note: By default, Azure AD emits Object IDs (UUIDs) for groups, not human-readable names. You either use the UUIDs in your Kubernetes RBAC or configure Azure to emit
sAMAccountName.
- Note: By default, Azure AD emits Object IDs (UUIDs) for groups, not human-readable names. You either use the UUIDs in your Kubernetes RBAC or configure Azure to emit
- On-Premises AD: Traditional LDAP/AD does not speak OIDC natively. You must use an identity broker. Dex (an open-source CNCF project) is the industry standard here. Dex connects to your LDAP server, speaks LDAP on the backend, and exposes a compliant OIDC endpoint to the Kubernetes API server.
The Client Side: Configuring kubectl
Kubernetes does not handle the browser-based login dance natively. You need an OIDC helper plugin. The most widely adopted community standard is kubelogin (often installed via krew).
Standard kubeconfig setup using kubelogin:
users:
- name: oidc-user
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: kubectl
args:
- oidc-login
- get-token
- --oidc-issuer-url=https://your-idp.com
- --oidc-client-id=YOUR_CLIENT_ID
- --oidc-client-secret=YOUR_CLIENT_SECRET
Tying it Together with RBAC
Once the API server trusts the IdP, you must create Kubernetes RoleBindings or ClusterRoleBindings that map to the OIDC claims.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: devsecops-admin-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: Group
name: oidc:devsecops-team # Assuming a prefix of "oidc:" was used
apiGroup: rbac.authorization.k8s.io
Additional Details
- Clock Skew: A common, hidden issue is clock drift. If the system clock on the Kubernetes control plane nodes drifts away from the IdP’s time servers, the API server will immediately reject perfectly valid tokens, claiming they are “issued in the future” or “expired.” Always run NTP on your nodes.
- Token Revocation Limitation: Kubernetes cannot inherently “revoke” a specific JWT before it expires. It only checks the signature and the expiration time statically. If a user is fired, disabling them in Okta stops them from getting new tokens, but their existing 1-hour token remains valid until it naturally expires. Keep token lifespans short!
- Lack of Native UI: Kubernetes has no built-in web login interface to trigger the OIDC flow natively; it strictly relies on CLI plugins or third-party dashboards.
- Key Components
- Identity Provider (IdP): Google, Okta, AD.
- Kubernetes API Server: Validates the cryptographic signature of the token.
- kubectl & kubelogin: The client-side execution tools.
- JWT (ID Token): The base64-encoded assertion of identity.
- Key Characteristics
- Stateless authentication on the Kubernetes side.
- Delegated credential management.
- Token-based authorization (Bearer tokens).
- Use case
- Enterprise Single Sign-On (SSO) for developer and pipeline access to Kubernetes clusters.
- Centralized offboarding (revoking access in Okta immediately blocks Kubernetes access).
- Benefits
- No need to generate and distribute individual client certificates.
- Eliminates local, hard-to-track Kubernetes user accounts.
- Seamless integration with existing corporate security policies.
- Best practices
- Always use strict prefixes for users and groups (e.g.,
--oidc-groups-prefix=oidc:). - Keep ID token lifespans short (e.g., 15-60 minutes).
- Automate the onboarding of RBAC roles using GitOps tools like ArgoCD.
- Always use strict prefixes for users and groups (e.g.,
- Technical challenges
- Debugging API server flag misconfigurations can be frustrating (the server might crash loop and fail to start).
- Clock skew between the IdP and the Kubernetes control plane can cause immediate token validation failures.
- Limitations
- Kubernetes has no built-in web login interface to trigger the OIDC flow natively; it strictly relies on CLI plugins.
- Kubernetes cannot revoke a specific JWT before it expires; it only checks the signature and the expiration time statically.
- Common issues
- API Server failing to start due to an unreachable
--oidc-issuer-url. - RBAC bindings not taking effect because the
groupsclaim is missing entirely from the ID Token.
- API Server failing to start due to an unreachable
- Problems and solutions
- Problem: Users are getting “Unauthorized” errors.
- Solution: Verify the
kubeconfigis correctly executing theoidc-loginplugin and that the token hasn’t expired. Check API server audit logs for rejection reasons.
- Solution: Verify the
- Problem: Groups are not mapping correctly to ClusterRoles.
- Solution: Decode the JWT using a tool like jwt.io (never paste production tokens online, use local tools) and verify the exact string name of the groups claim. Adjust
--oidc-groups-claimto match the exact JSON key.
- Solution: Decode the JWT using a tool like jwt.io (never paste production tokens online, use local tools) and verify the exact string name of the groups claim. Adjust
- Problem: Users are getting “Unauthorized” errors.
- https://kubernetes.io/docs/reference/access-authn-authz/authentication/#openid-connect-tokens
- https://developer.okta.com/docs/concepts/oauth-openid/
- https://cloud.google.com/kubernetes-engine/enterprise/identity/setup/provider
Conclusion
Integrating OIDC with your Kubernetes cluster is a fundamental step in building a mature DevSecOps platform. By offloading authentication to robust providers like Google, Okta, or Active Directory, you not only enhance the security posture of your infrastructure but also provide a smooth, frictionless experience for your engineering teams. Keep learning and secure those clusters!