Integrate K8s ServiceAccounts into IAM solution
K8s supports providing identity to Pods via ServiceAccounts. A JWT is provided to the workload Pod which may be used to access the apiserver, but also may be used outside of the cluster.
The "Service Account Issuer Discovery" seems like a perfect match to integrate them into SCS IAM/UCS: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-issuer-discovery
CC @stunivention
CC @reqa
As discussed in separate emails and meeting:
- Service Accounts can be created either dynamically be created in K8s via kubectl or other means.
- The frontend OIDC IdP (e.g. Keycloak) can simply federate/delegate authentication to the K8s OIDC IdP.
- The frontend OIDC IdP (e.g. Keycloak) may inject the access control claims in the Web Tokens based on the information it retrieves from the IAM user storage e.g. via LDAP.
- If an application service uses its Service-Account-JWT to access a resource service (e.g. a REST API consumed by the app), the resource service can use the IdP issued claims to decide which level of access is granted.
- We should manage the “access control” relation between Service Accounts and
resource services in the IAM user storage, just like we will do for the users.
GroupOfNamestype objects can be used to assign a resource usage permission e.g. tocluster-xyz:serviceaccounts:application-buisiness-app. - For this it's not required to actually store the Service Accounts (or even Credentials) in the IAM backend.
- This is similar to the way K8s handles users/groups, where it is also just
defined that user
<UUID>from the IAM has access to something, without checking if<UUID>is valid. Then a user comes with its token/cert/... (which refers to<UUID>) and access is checked on-the-fly.
An open question is, which JWT are provided to the Services by K8s. If it's the one issued by K8s's own OIDC IdP, then the authz claims would not be included present. A PoC test is required here.
Example contents:
"Ordinary" Service Account JWT claims
{
"iss": "kubernetes/serviceaccount",
"kubernetes.io/serviceaccount/namespace": "default",
"kubernetes.io/serviceaccount/secret.name": "mytestaccount-token-pnj77",
"kubernetes.io/serviceaccount/service-account.name": "mytestaccount",
"kubernetes.io/serviceaccount/service-account.uid": "a709ef71-30e2-489a-bd19-ade97031b9db",
"sub": "system:serviceaccount:default:mytestaccount"
}
Projected volume token claims
{
"aud": [
"thisismyaudience"
],
"exp": 1616000294,
"iat": 1615999694,
"iss": "https://api.harbor-test.garden.internal.prod.gardener-test.site",
"kubernetes.io": {
"namespace": "default",
"pod": {
"name": "projection-test",
"uid": "900f80ed-bafe-49f0-9ae2-c5f0a3ac2cbe"
},
"serviceaccount": {
"name": "mytestaccount",
"uid": "a709ef71-30e2-489a-bd19-ade97031b9db"
}
},
"nbf": 1615999694,
"sub": "system:serviceaccount:default:mytestaccount"
}
The audience was freely configurable via the PodSpec.
An open question is, which JWT are provided to the Services by K8s. If it's the one issued by K8s's own OIDC IdP, then the authz claims would not be included present. A PoC test is required here.
So indeed, the token only provides AuthN/identifying information, no AuthZ information.
This can probably always be done manually; For an automated/integrated experience, SovereignCloudStack/issues#339 is required. If that happens, this issue may be reopened.