Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

161 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

KubeUser

Latest Release Go Report Card License Tests Go Version Artifact Hub

KubeUser is a Kubernetes-native way to manage users, certificates, RBAC, and kubeconfigs declaratively β€” without running an external identity provider.


Overview

Managing Kubernetes access often means manually creating kubeconfigs, handling certificates, and keeping RBAC in sync. This quickly becomes error-prone, hard to audit, and unfriendly to GitOps workflows.

KubeUser solves this by managing Kubernetes users through declarative custom resources. It automatically generates and rotates certificates, applies RBAC bindings, and produces ready-to-use kubeconfigs using native Kubernetes APIs.

Designed for small teams and self-managed clusters that want Kubernetes-native, GitOps-friendly access control without a full IAM or OIDC stack. Not a replacement for enterprise identity providers.

Architecture

   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚   User CR    β”‚   kubectl apply -f user.yaml
   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚   Admission Webhooks     β”‚   TLS via cert-manager
   β”‚   β€’ Mutating  (defaults) β”‚
   β”‚   β€’ Validating (rules)   β”‚
   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚     User Controller      β”‚   reconcile loop
   β”‚       (Reconciler)       β”‚
   β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”˜
      β”‚         β”‚          β”‚
      β–Ό         β–Ό          β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ CSR  β”‚ β”‚ Secrets β”‚ β”‚   RBAC     β”‚
   β”‚ API  β”‚ β”‚  key +  β”‚ β”‚  Role &    β”‚
   β”‚      β”‚ β”‚ kubecfg β”‚ β”‚  Cluster   β”‚
   β”‚signedβ”‚ β”‚         β”‚ β”‚  Bindings  β”‚
   β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Quickstart

Try KubeUser in a few commands on any cluster with a working kubectl context:

# 1. Install cert-manager (required for webhook TLS)
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.2/cert-manager.yaml
kubectl wait --for=condition=ready pod -l app=cert-manager -n cert-manager --timeout=60s

# 2. Install KubeUser (uses the API server from your current kubeconfig)
helm repo add kubeuser https://openkube-hub.github.io/KubeUser

export KUBERNETES_API_SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')

helm install kubeuser kubeuser/kubeuser \
  --namespace kubeuser --create-namespace \
  --set env.KUBERNETES_API_SERVER="$KUBERNETES_API_SERVER"

# 3. Create a User
cat <<EOF | kubectl apply -f -
apiVersion: auth.openkube.io/v1alpha1
kind: User
metadata:
  name: alice
spec:
  auth:
    type: x509
  clusterRoles:
    - existingClusterRole: view
EOF

# 4. Retrieve the kubeconfig and use it
kubectl get secret alice-kubeconfig -n kubeuser \
  -o jsonpath='{.data.config}' | base64 -d > alice.kubeconfig
kubectl --kubeconfig alice.kubeconfig get pods -A

For production installs, see Installation below.


Features

βœ… Implemented

  • Declarative User CRD β€” status tracking, conditions, and finalizers for clean resource lifecycles
  • Automatic Certificate Generation β€” seamless integration with the Kubernetes CSR API
  • Stateful Rotation Engine β€” resumable, multi-step rotation via the Shadow Secret pattern; survives controller restarts
  • Atomic Secret Updates β€” zero-downtime credential flip with rollback on failure
  • Dynamic RBAC Reconciliation β€” automatic RoleBinding and ClusterRoleBinding management
  • Mutating & Validating Webhooks β€” TLS-secured via cert-manager CA injection
  • Managed K8s Support β€” configurable CSR signers for EKS, GKE, and vanilla clusters
  • Anti-Thundering-Herd Design β€” smart requeue with jitter, 24h TTL floor, 33% renew window, and an idempotent single-status-update reconcile path
  • High Availability β€” leader election and multi-replica deployment shipped via Helm
  • Prometheus Metrics & Alerting β€” rotation counters, duration histograms, expiry gauges, pre-built Grafana dashboard, and shipped PrometheusRule alerts
  • Kubernetes Events β€” structured events surfaced via kubectl describe user
  • Status Conditions β€” standard Ready, Renewing, and AutoRenewal conditions for declarative status checks
  • kubectl Printer Columns β€” kubectl get users shows Phase, AutoRenew, Expiry, NextRenewal, Age, and Message

🚧 Planned

  • Deletion Warning Event β€” admission warning and Warning event on User delete clarifying that issued certs remain cryptographically valid until expiry (Kubernetes does not consult CRL/OCSP for client certs)
  • kubectl Plugin β€” kubectl kubeuser kubeconfig <name> to replace the manual kubectl get secret | base64 -d flow
  • Audit Log β€” immutable record of every certificate issuance and rotation event
  • Short-Lived Certificates (< 24h) β€” sub-24h TTL for ephemeral, zero-trust access
  • ECDSA Key Support β€” configurable key algorithm via spec.auth.keyAlgorithm
  • OpenTelemetry Tracing β€” end-to-end traces across reconcile and rotation paths
  • Example Role Manifests β€” a curated folder of well-defined, ready-to-apply Role/ClusterRole YAMLs for common access patterns (read-only, developer, namespace-admin) that users can reference directly

Security Considerations

Deleting a User does NOT invalidate issued certificates.

When deleting a User:

  • RBAC bindings are removed immediately (access revoked)
  • Secrets are deleted
  • Certificates remain cryptographically valid until natural expiry

Plan your TTL accordingly. For short-lived access, use a short ttl and autoRenew: false.


Installation

Prerequisites

  • Kubernetes v1.28+
  • kubectl with cluster-admin permissions
  • cert-manager (required for webhook certificates)

Install cert-manager

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.2/cert-manager.yaml
kubectl wait --for=condition=ready pod -l app=cert-manager -n cert-manager --timeout=60s

Option 1: Helm (Recommended)

helm repo add kubeuser https://openkube-hub.github.io/KubeUser
helm repo update

export KUBERNETES_API_SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')

helm upgrade --install kubeuser kubeuser/kubeuser \
  --create-namespace \
  --namespace kubeuser \
  --version <version> \
  --set env.KUBERNETES_API_SERVER="$KUBERNETES_API_SERVER"

# Verify
kubectl get pods -n kubeuser
kubectl get certificates -n kubeuser

All resource names are prefixed by the Helm release name. Use helm search repo kubeuser --versions to list available versions.

Option 2: Kustomize

git clone https://github.com/openkube-hub/KubeUser.git
cd KubeUser
kubectl create namespace kubeuser
kubectl apply -k config/default
kubectl wait --for=condition=ready pod -l control-plane=controller-manager -n kubeuser --timeout=120s

Option 3: Local Development (kind)

make docker-build
kind load docker-image ghcr.io/openkube-hub/kubeuser-controller:latest --name <cluster-name>
kubectl apply -k config/default
kubectl patch deployment kubeuser-controller-manager -n kubeuser \
  -p '{"spec":{"template":{"spec":{"containers":[{"name":"manager","imagePullPolicy":"Never"}]}}}}'

Usage

How Defaults Work

KubeUser uses a mutating admission webhook to persist defaults into the User spec at creation time:

# You submit:
spec:
  auth:
    type: x509

# Webhook persists:
spec:
  auth:
    type: x509
    ttl: "2160h"      # from KUBEUSER_DEFAULT_TTL
    autoRenew: true   # from KUBEUSER_DEFAULT_AUTORENEW

Verify applied defaults: kubectl get user <name> -o yaml

Customize defaults via Helm:

helm upgrade --install kubeuser kubeuser/kubeuser \
  --set authDefaults.ttl=720h \
  --set authDefaults.autoRenew=false

Important: authDefaults changes only apply to users created after the upgrade. Existing users retain their persisted defaults.

Basic User (Namespace-Scoped Access)

apiVersion: auth.openkube.io/v1alpha1
kind: User
metadata:
  name: alice
spec:
  auth:
    type: x509        # REQUIRED: currently only 'x509' is supported
    ttl: "72h"        # Optional: default 2160h (90 days)
    autoRenew: false  # Optional: default true
  roles:
    - namespace: "development"
      existingRole: "developer"
    - namespace: "staging"
      existingRole: "viewer"

User with Cluster-wide Access

apiVersion: auth.openkube.io/v1alpha1
kind: User
metadata:
  name: bob-admin
spec:
  auth:
    type: x509
    ttl: "2160h"
    autoRenew: true
  clusterRoles:
    - existingClusterRole: "cluster-admin"

Mixed Permissions

apiVersion: auth.openkube.io/v1alpha1
kind: User
metadata:
  name: contractor-jane
spec:
  auth:
    type: x509
    ttl: "720h"        # 30 days
    autoRenew: true
    renewBefore: "72h" # Renew 3 days before expiry (overrides 33% rule)
  roles:
    - namespace: "project-x"
      existingRole: "developer"
    - namespace: "monitoring"
      existingClusterRole: "view"  # ClusterRole bound to a specific namespace
  clusterRoles:
    - existingClusterRole: "view"

Retrieve a User's Kubeconfig

kubectl get secret <username>-kubeconfig -n kubeuser \
  -o jsonpath='{.data.config}' | base64 -d > /tmp/kubeconfig

kubectl --kubeconfig /tmp/kubeconfig get pods -n dev

Field Reference

Field Type Required Description
spec.auth AuthSpec Yes Authentication configuration
spec.auth.type string Yes Auth method β€” only x509 is supported
spec.auth.ttl string No Certificate lifetime (default: 2160h)
spec.auth.autoRenew boolean No Enable automatic renewal (default: true)
spec.auth.renewBefore string No Renew this duration before expiry. Cannot exceed 90% of TTL
spec.roles []RoleSpec No Namespace-scoped role bindings
spec.roles[].namespace string Yes Target namespace
spec.roles[].existingRole string Yes (or existingClusterRole) Existing Role in the same namespace
spec.roles[].existingClusterRole string Yes (or existingRole) ClusterRole bound into the namespace
spec.clusterRoles []ClusterRoleSpec No Cluster-wide role bindings
spec.clusterRoles[].existingClusterRole string Yes Existing ClusterRole

For each spec.roles[] entry, exactly one of existingRole or existingClusterRole must be set.


Managed Kubernetes Support

KubeUser issues client certificates via the Kubernetes CSR API. The default signer is kubernetes.io/kube-apiserver-client, which works on any cluster that permits third-party client-auth CSR signing.

For environments with a custom CA controller (e.g., cert-manager's CA issuer fronting a custom signer), override via Helm:

helm install kubeuser kubeuser/kubeuser \
  --set signerName="<your-signer-name>" \
  --set rbac.signerResourceNames[0]="<your-signer-name>"

To see what signers your cluster already accepts:

kubectl get csr -o jsonpath='{range .items[*]}{.spec.signerName}{"\n"}{end}' | sort -u

Configuration

Certificate Duration Limits

Limit Value Notes
Minimum TTL 24h Enforced by validating webhook β€” prevents thundering herd loops
Maximum TTL Bounded by the cluster signing duration (Kubernetes default: 8760h / 1 year) Configure --cluster-signing-duration on kube-controller-manager to allow longer
Default TTL 2160h (90 days) Applied by mutating webhook; configurable via authDefaults.ttl

Environment Variables

Variable Default Description
KUBERNETES_API_SERVER https://127.0.0.1:6443 API server address written into generated kubeconfigs
CLUSTER_DOMAIN cluster.local Cluster DNS domain
KUBEUSER_DEFAULT_TTL 2160h Default certificate TTL
KUBEUSER_DEFAULT_AUTORENEW true Default auto-renewal behaviour
KUBEUSER_SIGNER_NAME kubernetes.io/kube-apiserver-client CSR signer name

Documentation


🀝 Contributing

We welcome contributions of all kinds β€” bug reports, features, documentation, and tests.

See CONTRIBUTING.md for the full guide: prerequisites, local setup, code style, commit format, testing, and PR checklist.


πŸ›οΈ Community

Document Description
CONTRIBUTING.md How to contribute
GOVERNANCE.md Project roles, decision-making, and release process
MAINTAINERS.md Current and emeritus maintainers
SECURITY.md How to report security vulnerabilities
CODE_OF_CONDUCT.md Community standards

If you find KubeUser useful, please consider giving it a ⭐ on GitHub!

Releases

Packages

Used by

Contributors

Languages