Skip to content

menacit/k8s_crlish_authorizer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

k8s_crlish_authorizer

Kubernetes authorizer for denying specific credential IDs ("CRLish")

Introduction

For almost a decade, the Kubernetes project has been pondering over how to best implement revocation checks for X.509 certificates. Meanwhile, there has been no way to prevent compromised user/node certificate keys from being used for malicious authentication.

In Kubernetes version 1.32, a feature was merged in the X.509 authenticator which adds a "credential ID" (SHA256 digest of client's certificate) to the "UserInfo" object. A similar feature for service account tokens was also marked as GA in the same release. At the time of writing, there doesn't seem to exist much documentation, but the features seem to be targeted towards audit logging. Google Cloud has published a blog post which demonstrates usage.

Luckily, the "UserInfo" object is also available for API server authorizers. This enables usage of a custom WebHook authorizer that validates credential IDs against a user-supplied deny list.

This repository contains an implementation of such as custom authorizer and some guidance covering how to use it!

Current status

Proof of concept - beware of rough edges and limitations. Review the project's open issues.

Acknowledgements

This tool was created during research for Menacit's Kubernetes Security Course. Funding for development of the course was provided by Sweden's National Coordination Centre for Research and Innovation in Cybersecurity, the Swedish Civil Contingencies Agency and the European Union's European Cybersecurity Competence Centre.

Example usage

Generating a "credential ID" for a certificate file:

$ echo "X509SHA256=$(openssl x509 -in /var/lib/kubelet/pki/kubelet-client-current.pem -outform der | sha256sum | cut -d ' ' -f 1)"

Generating a "credential ID" for a service account token or other JWT:

$ echo "JTI=$(cat /run/secrets/kubernetes.io/serviceaccount/token | cut -d . -f 2 | base64 -d | jq -r .jti)"

Response from API server when a request is performed using a deny-listed credential ID:

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:node:worker-1\" cannot get path \"/api\": Credential ID \"X509SHA256=474d0c910180b290210fcba55f6f40054cd7d4a50b476bb1cce87796d899e948\" is included in deny list (\"CRLish\")",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}

Matching log entry from k8s_crlish_authorizer application:

{
  "time": "2025-02-27T13:16:30.156631908Z",
  "level": "WARN",
  "msg": "Subject access review data contains credential ID included in deny list",
  "credential-id": "X509SHA256=474d0c910180b290210fcba55f6f40054cd7d4a50b476bb1cce87796d899e948",
  "uid": "",
  "user": "system:node:worker-1",
  "groups": [
    "system:nodes",
    "system:authenticated"
  ]
}

About

Kubernetes authorizer for denying specific credential IDs ("CRLish")

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages