pipeline
pipeline copied to clipboard
RBAC to disable inline TaskSpec/PipelineSpec
Feature request
I'd like to allow developers to use a predefined Pipeline to build their software, without the (potentially dangerous) permission to create their own. If they were allowed to create their own Tasks (or inline taskSpec within a PipelineRun), they could dump out Secrets within the namespace.
The best I can do is to setup RBAC to grant developers view access to a namespace, and additionally grant create PipelineRuns. I'd supply the Tasks they'd need - they'd not be able to directly view Secrets, nor create a pod or Task to dump them. However because PipelineRun allows an inline Pipeline definition, which in turn allows an inline Task definition, I can't find a way of preventing developers from creating an arbitrary Task to dump Secrets.
I have considered an admission controller, but that would need coordination with the cluster admin, which can be problematic. I could also use EventListeners to create the PipelineRun on behalf of the developers, but this integrates poorly with gitops (would need to use hooks rather than directly syncing objects, so would rerun on a change of an unrelated object in the same ArgoCD Application - not really declarative)
Use case
Allow developers to use a predefined Pipeline to build their software, without the (potentially dangerous) permission to create their own. If they were allowed to create their own Tasks (or inline taskSpec within a PipelineRun), they could dump out Secrets within the namespace.
@jimmyjones2 thanks for the issue. Would an option on the controller's config be a valid solution for you ? (a key "disable-embedded-specs" with boolean value). Once https://github.com/tektoncd/community/blob/main/teps/0085-per-namespace-controller-configuration.md is implemented, it could be something enabled/disabled per namespaces as well.
@vdemeester Yes, that sounds good!
My workaround is to let less privileged users (users) only use eventlisteners to create taskruns or pipelineruns. This allows to specify workspaces and other runtime parameters in advance aswell. Without knowing the required amount of work for the implementation, I could imagine a custom kubernetes verb create/run applicable to tasks, pipelines, and ~triggerbindings(?)~ triggers such that kubernetes RBAC can be used to precisely define who can execute what.
Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale with a justification.
Stale issues rot after an additional 30d of inactivity and eventually close.
If this issue is safe to close now please do so with /close with a justification.
If this issue should be exempted, mark the issue as frozen with /lifecycle frozen with a justification.
/lifecycle stale
Send feedback to tektoncd/plumbing.
/remove-lifecycle stale Still an issue
/remove-lifecycle stale
Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale with a justification.
Stale issues rot after an additional 30d of inactivity and eventually close.
If this issue is safe to close now please do so with /close with a justification.
If this issue should be exempted, mark the issue as frozen with /lifecycle frozen with a justification.
/lifecycle stale
Send feedback to tektoncd/plumbing.
/remove-lifecycle stale
/lifecycle frozen
So technically, doing something with RBAC, in a similar fashion as @lbernick's approach in https://github.com/tektoncd/pipeline/pull/7083 is doable. The question is, should we do it ?
Essentially we have the following options:
- RBAC setup (with a modified webhook)
- A cluster-wide option
- A cluster-wide option and a per-namespace option (namespace label or configmap)
- Nothing, relying on things like OPA to enforce these, outside of tektoncd/pipeline scope.
@tektoncd/core-maintainers what do you think about these options ?
I was just about to write another feature request on this until someone pointed me here.
Question how hard would it be to just create a new object like a PipelineRunStrict or something. That just didn't have the pipelineSpec field and only allowed for pipelineRef ?
If we had that we could just use normal RBAC to give users access to create the PipelineRunStrict object in a namespace and they would at least be limited to only being able to run existing pipelines.
@jimmyjones2 @jland-redhat We also have resolvers, so do we need to control that also?
@jimmyjones2 @jland-redhat We also have resolvers, so do we need to control that also?
I am not totally following the question here, I am not too familiar with resolvers in tekton but that looks like a code level change.
I think at a high level the ask here is that there should be a way in which we can give a user or group access to run an existing Pipeline without giving them access to create their own Pipeline/Task/etc... on the fly.
@jimmyjones2 @jland-redhat We also have resolvers, so do we need to control that also?
Resolvers can be disable already, so I don't think
I think at a high level the ask here is that there should be a way in which we can give a user or group access to run an existing
Pipelinewithout giving them access to create their own Pipeline/Task/etc... on the fly.
Agreed, as of today, the only thing that "gets" in the way for this is the embedded spec (and at a different level the resolvers, but those can be disabled already — and even it wasn't the case, this would be another issue).
Resolvers can be disable already, so I don't think
Isn't it clusterwide disabling?
Agreed, as of today, the only thing that "gets" in the way for this is the embedded spec (and at a different level the resolvers, but those can be disabled already — and even it wasn't the case, this would be another issue).
Why not have a flag for disabling embedded spec instead of RBAC? Like we have for resolvers.
If that suggestion is fine, then I can raise a PR for that.
@khrm yeah that’s one of the suggestion above. for resolvers it is cluster wide yes. I think we can start with that for both and figure out the per namespace later
Just to add on to this, from a practical use-cases I have seen in the field, cluster wide would cover most of the issues. So if we can solve that quicker I think it would be great!
Generally I have only wanted to have them disabled in production which I would want to do at the cluster level anyway.
I wonder if how we want to handle StepActions with this. A remote Task that references remote StepActions. May be one might want to consider allowing inlined Tasks with StepActions.
I think inlined Steps is where the issue truly lies, correct? That's where the secrets can get leaked? If so, may be what we need is to only disallow Inlined Steps. Which means that at validation time, we must not detect an inlined Step. Meaning that either the pipeline is remote, Tasks are remote or inlined (but use StepActions).
I think inlined Steps is where the issue truly lies, correct? That's where the secrets can get leaked? If so, may be what we need is to only disallow Inlined Steps.
It might quickly become complex to assess security of all possible combinations of Tasks and StepActions.
I think implementation on our end is not that hard but the user experience could be hindered here. Suddenly, if they want to add even a single inlined step then they have to make the Task remote. So it might be best to pick a mode of execution like it's been suggested above.
Would the suggestion by @jland-redhat of PipelineRunStrict be a better option? There would be no breaking changes or surprising behaviour and it could be controlled per namespace or cluster wide using RBAC
Would the suggestion by @jland-redhat of PipelineRunStrict be a better option? There would be no breaking changes or surprising behaviour and it could be controlled per namespace or cluster wide using RBAC
I am not a fan of creating a CRD just for this. There is already too much CRD everywhere 😅. What if tomorrow we want hermetic pipeline, do we create yet another CRD, etc.. ?
Would the suggestion by @jland-redhat of PipelineRunStrict be a better option? There would be no breaking changes or surprising behaviour and it could be controlled per namespace or cluster wide using RBAC
I am not a fan of creating a CRD just for this. There is already too much CRD everywhere 😅. What if tomorrow we want hermetic pipeline, do we create yet another CRD, etc.. ?
Agreed! I think disabling it cluster wide makes more sense since it feels more like a behavioural change.
Note : the CRD approach is possible today, one could define a new CRD, a controller for it, and setup rbac to put tekton CR as read only, and make the controller translate that CR into a PipelineRun CR.
Note: one could even, today, write a custom admission controller that disallow inline spec 😇.
I was thinking of raising a PR with a new feature flag to disable embedded spec. Isn't that OK? It's not a breaking change. We can default behaviour as allowed.