Description
tl;dr
We should allow Fulcio to accept OIDC tokens from some (see below) federated Kubernetes OIDC issuers.
Background and High-level proposal
Kubernetes has a relatively new feature called "Service Account Projected Volumes", which allows a workload to generate short-lived, audience-scoped OIDC tokens for a given serviceaccount, e.g.
{
"header": {
"alg": "RS256",
"kid": "oDK51cHaX3V8crffIaSQG8Sx1Vys3xHLD6moTkivqaM"
},
"payload": {
"aud": [
"something"
],
"exp": 1634744688,
"iat": 1634744088,
"iss": "https://container.googleapis.com/v1/projects/mattmoor-credit/locations/us-west1-b/clusters/tenant-cluster",
"kubernetes.io": {
"namespace": "default",
"pod": {
"name": "oidc-test",
"uid": "49ad3572-b3dd-43a6-8d77-5858d3660275"
},
"serviceaccount": {
"name": "default",
"uid": "f5720c1d-e152-4356-a897-11b07aff165d"
}
},
"nbf": 1634744088,
"sub": "system:serviceaccount:default:default"
},
"signature": "..."
}
At least GKE and EKS expose public issuer endpoints for these, which enable these tokens to be used with OIDC federation to authenticate with off-cluster services.
Corollary: if we support this, then we can actually start to leverage KinD to run e2e tests for keyless flows
Broken assumptions and work needed
In general, the subject (sub
) of an OIDC flow is only unique within the scoping of the issuer (iss
), but today Fulcio assumes a handful of fairly central OIDC issuers with disjoint subjects. This assumption manifests in the subject being the only piece of information included in the issued certificate. If we don't address this assumption, then we can't meaningfully add support for tokens issued by clusters because any cluster could sign things as system:serviceaccount:default:default
!
AI: So the first order of business is to make the implicit issuer URLs we have today explicit. I'd propose we start to unconditionally include the iss
as the first URI in the URIs section of the certificate we issue.
AI: Once it is safe to start including Kubernetes OIDC in the issuer configuration, I propose that we add support for Kubernetes OIDC issuers (not configured in the public instance!), and use it to stand up some basic KinD e2e testing for Fulcio following: https://github.com/mattmoor/kind-oidc. Once this lands, we can also use this same setup to start doing presubmit testing for keyless flows downstream in cosign
(cc @dekkagaijin).
AI: Once we have support for directly configured Kubernetes OIDC issuers, I propose that we refactor the current issuer configuration to support a degree of fuzzy matching, and start adding well-known public prefixes like GKE and EKS.
AI: Once we have support for Kubernetes OIDC issuers, I propose we augment the cosign
OIDC "magic" to support a particular mount path (e.g. /var/run/sigstore/cosign/oidc-token
)
I believe that with the sum total of these features, we should be able to support fairly broad K8s "workload identity" based flows (both public Fulcio w/ public cloud vendor, and private Fulcios on-prem), and start supporting "keyless" presubmit testing (upstream and downstream in tools ๐คฉ).
cc @dlorenc @lukehinds