feat: Provide credentials in imagePullSecret without global access#2161
Conversation
When running a cluster that contains images from a private registry one needs to configure authentication. This is done by using kubernetes ImagePullSecrets. By default the trivy-operator is able to read the secrets attached to a target workload and use them to access the container registry. While this is necessary when working with different registries inside the cluster, this comes with one security downside: the operator needs access to all secrets inside the cluster. If all images are being pulled from a single private registry then one ImagePullSecret can be used for all of them. The easiest one to use is inside the operator namespace. This change does not impact any deployments running with default settings (global access enabled). But in case one disables that access this allows to instead read a single ImagePullSecret and use it for all images.
|
Hey, this MR is not finished (and tests will fail for sure), but I wanted to get your opinion on my approach first - afterwards, I will try to add and fix the necessary tests. operator:
accessGlobalSecretsAndServiceAccount: false
privateRegistryScanSecretsNames: {"trivy-operator":"internal-pullsecret"}With this change the above configuration would allow the trivy-operator to pull all images inside the cluster that use the same private registry - while not having to grant it access to every secret in the entire cluster. WDYT? |
|
@maltemorgenstern looks ok in general |
The unit tests have been fixed and now cover three different scenarios: - No credentials have been configured at all - ImagePullSecret for workload exists but global access is disabled - ImagePullSecret for workload exists and global access is enabled Also a small typo in the CONTRIBUTING.md is being fixed.
In [1] the trivy-operator updates the temporary secrets to reflect the ownership by
each scan job. This requires the 'update' persmission for secrets - otherwise the
call with result in an error ("forbidden").
While the ClusterRole has this permission the Role does not. This needs to be added
to run the trivy-operator without global access - while still using imagePullSecrets
to configure authentication for private registries.
[1]: https://github.com/aquasecurity/trivy-operator/blob/d5d7e3d25c5e98f92c6a596af639b1f8df721869/pkg/vulnerabilityreport/controller/workload.go#L380-L389
|
Hey @chen-keinan, I finally found the time to finalize this PR - it's ready for review now. FYI: I don't have much experience in Go - so any hints about styling or optimizations are welcome! |
|
Hey @chen-keinan, just wanted to check in - what to you think about these changes? |
|
This PR is stale because it has been labeled with inactivity. |
|
Hey, we would still like this to be merged. @chen-keinan do you mind giving it a review? |
|
@afdesk could you take a look when you have a chance? |
|
@maltemorgenstern can we follow up this job? thanks |
|
@maltemorgenstern great to hear it! thanks a lot for your contribution! we (@simar7 ) have a concern about backward compatibilities, please, feel free to correct me. Now |
|
@maltemorgenstern could you also rebase the PR with the main branch? thanks |
| } else { | ||
| // Global access is disabled - check if privateRegistrySecrets references an imagePullSecret in the operator namespace | ||
| imagePullSecretName, ok := privateRegistrySecrets[r.Config.Namespace] | ||
| if ok { | ||
| // privateRegistrySecrets references an imagePullSecret in the operator namespace - use this for pulling private images | ||
| credentials, err = r.CredentialsByServer(ctx, owner, map[string]string{r.Config.Namespace: imagePullSecretName}, multiSecretSupport, false) | ||
| if err != nil { | ||
| return err | ||
| } |
There was a problem hiding this comment.
this else statement will run If reusedReports isn't empty
| privateRegistrySecrets, err := r.Config.GetPrivateRegistryScanSecretsNames() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| pConfig, err := r.PluginContext.GetConfig() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| multiSecretSupport := trivy.MultiSecretSupport(trivy.Config{PluginConfig: pConfig}) |
There was a problem hiding this comment.
also I have a concern about this block.
should we run it for existed KBOM reports?
74e1f17 to
46ef0f6
Compare
|
@simar7 @maltemorgenstern |
Description
When running a cluster that contains images from a private registry one needs to configure authentication. This is done by using kubernetes ImagePullSecrets. By default the trivy-operator is able to read the secrets attached to a target workload and use them to access the container registry.
While this is necessary when working with different registries inside the cluster, this comes with one security downside: the operator needs access to all secrets inside the cluster.
If all images are being pulled from a single private registry then one ImagePullSecret can be used for all of them. The easiest one to use is inside the operator namespace (because the operator has access to secrets in its own namespace).
This change does not impact any deployments running with default settings (global access enabled). But in case one disables that access this allows to instead read a single ImagePullSecret and use it for all images.
Related issues
Checklist