The Vault issuer can now be given a serviceAccountRef#4524
The Vault issuer can now be given a serviceAccountRef#4524maelvls wants to merge 1 commit intocert-manager:masterfrom
Conversation
|
Skipping CI for Draft Pull Request. |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: maelvls The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
2b33c21 to
99fee0d
Compare
|
I have tested this PR with EKS 1.20 (using |
| verbs: ["create", "patch"] | ||
| - apiGroups: [""] | ||
| resources: ["serviceaccounts/token"] | ||
| verbs: ["create"] |
There was a problem hiding this comment.
Self-review: I should document why this is required; and most importantly that it is only required when using Vault + Kubernetes auth + serviceAccountRef.
| if kubeAuth != nil && (len(kubeAuth.SecretRef.Name) == 0 && len(kubeAuth.ServiceAccountRef.Name) == 0) { | ||
| logf.V(logf.WarnLevel).Infof("%s: %s", v.issuer.GetObjectMeta().Name, messageKubeAuthSingleRequired) | ||
| apiutil.SetIssuerCondition(v.issuer, v.issuer.GetGeneration(), v1.IssuerConditionReady, cmmeta.ConditionFalse, errorVault, messageKubeAuthSingleRequired) | ||
| return nil | ||
| } |
There was a problem hiding this comment.
Self-review: would it be worth adding these "runtime" constraints to the webhook validation too?
|
We just hit this in one of our dev environments. What's the likely timeline for a release assuming this solution is accepted (I see some alternatives being mentioned)? |
|
Hi. If this solution is accepted (it seems like the discussion is going towards implementing it with serviceAccountRef), I plan on getting this PR merged for 1.7, but you can expect a 1.7.0-alpha.0 to test the feature probably next week or the week after. |
|
I feel more and more uncomfortable with the idea of giving even more privileges to cert-manager. More specifically, this feature requires adding to everybody's cert-manager a "god-like" role: - apiGroups: [""]
resources: [serviceaccounts/token]
verbs: [create]With this new role, cert-manager is able to make requests to the apiserver using any service account that exists across all namespaces. If one of them has more privileges than cert-manager's own service account, it is a privilege escalation. I have looked around to see if anyone else is using this role and the TokenRequest API, and whether there is a way to "minimize" the impact of this new role. It seems like only cloud providers controllers, such as cloud-provider-aws, have "seriously" been using this feature. cloud-provider-aws is only able to request tokens for three service accounts using - apiGroups:
- ""
resourceNames:
- node-controller
- service-controller
- route-controller
resources:
- serviceaccounts/token
verbs:
- createThe strings |
Previously, the Vault issuer was only able to use a Secret in order to use the "Kubernetes authentication" method. The downside to this service account Secret token is that it has the default JWT iss "kubernetes/serviceaccount" (along with the fact that the token is not bound to a particular pod and has no expiry). With the new serviceAccountRef, cert-manager now requests the token on behalf of the pod in order to authenticate with Vault. Signed-off-by: Maël Valais <mael@vls.dev>
99fee0d to
ddfdf4d
Compare
|
I would also prefer the approach outlined in #2345. We currently use Banzai Bank-Vaults to inject Vault secrets into the pod's ENV which also makes requests to Vault using the pod's service account token. |
|
Hi, After a discussion on Slack, due to the high level of privileges required for the On a positive note, #2345 suggests re-using the existing token mounted to the cert-manager pod, which seems a much better approach. The only issue is that when we hand Vault the token, it will have way too many permissions (such as reading secrets). Vault does not require any permission to call the the tokenreview API. |
|
As we can see the implementation for this particular feature presented multiple security challenges, that are currently reflected in https://hackmd.io/MNQf9ReSR6GdkFl04oS-fA However, It seems that even the Vault team is actually advising to set "disable_iss_validation=true" (or leave blank for 1.9+ as it's default) on the authentication engine:
If you're actually already on Vault 1.9 the iss issuer validation, which is causing this whole issue is being deprecated. So that first workaround of disabling the disable_iss_validation=true for (1.9 or below) and leaving blank from 1.9+ is now the most sensible approach for Kubernetes vault auth engine, which sidesteps the issue. Aside from issuer validation, we would want to natively support bounded service accounts as it adds an extra layer of security but we can now say conclusively that this is not a blocker to cert-manager vault issuer setup in Kubernetes 1.21+. |
|
Note: I re-created this PR in #5502. |
As detailed in #4144, the Vault issuer is only able to use a Secret in order to use the "Kubernetes authentication" method. The downside to this service account Secret token is that it has the default JWT is "kubernetes/serviceaccount" (along with the fact that the token is not bound to a particular pod and has no expiry).
With the new
serviceAccountReffield, cert-manager now requests the token on behalf of the pod in order to authenticate with Vault.I manually tested the feature on these environments:
Still to be done:
Notes to the reviewer:
This approach requires cert-manager to be given even more permissions.The user now has to create an RBAC Role and RoleBinding for the service account they want to use.The expiry is currently hardcoded to 2 hours.It is configurable now.3.~ The audience is currently hardcoded to
vault.~ It is configurable now.vault.auth.kubernetes.secretReffrom mandatory to optional; I don't think that's a breaking change since I am relaxing constraints.UPDATE: another idea, suggested in #2345, is to reuse cert-manager's own token to do the authentication. I don't know what are the security implications of this yet.
If you want to test this feature, here are the steps:
Then, create an issuer and a certificate:
If you want to run the new e2e locally:
make -j e2e-setup-certmanager e2e-setup-vault make e2e GINKGO_FOCUS=".*should be ready with a valid serviceAccountRef"/kind feature
/area vault