Opt-in which CI/CD variables are passed to a job
Proposal
Currently, all defined CI/CD variables are automatically passed to all jobs, unless they are marked as being passed only on protected tags/branches. In the later case they are still passed to all jobs.
I think this is problematic from the security perspective and does not follow the rule of least privilege when those variables are secrets. Often only some jobs need some of the variables. But currently all jobs (even if they are on protected branch) get them. This is problematic from multiple reasons:
- Not all jobs are trusted to the same degree: for some jobs I might be using an external Docker image, which might work fine today but might be compromised in the future. It is not viable for me to audit all Docker images and make sure nobody pushed a new malicious version of it. We can try to make audit automatic, but it can still fail. So, it would be great if there was a way to simply not pass those variables to the job, especially because they do not need them.
- It is hard to review which jobs needs which variables.
- It is also not clear (especially when you CI configuration spawns multiple files and includes) which variables you have to define at all for CI to work.
I suggest that each job should be able to define which CI/CD it requires, I suggest the following syntax (but I am not married to it):
requires:
- MY_SECRET
Other jobs then do not get any of variables. Once any of jobs use this opt-in mechanism.
What I like about this proposal is that it also allows the CI/CD variables UI form to be prepopulated with variables required by the pipeline. Admin could inspect them and set values (or decide to not set them for jobs to be skipped). This works great also with CI_JOB_TOKEN
extension and &6310 mentioned below: CD/CD variables UI form could tell which permissions are needed by each job and admin could decide to grant them.
Current state
You can currently define:
rules:
- if: $MY_SECRET
To run the job only if MY_SECRET
is available. But my proposal makes it explicit that the job needs the variable (and other jobs in the file do not, unless they opt-in as well) and is ran only if the variable is available. So besides controlling which jobs run it also makes only those jobs get MY_SECRET
.
Alternative
Current proposal suggest that once any job opts-in into requires
no other jobs get variables anymore. I think this is important but might break things for people who might include some file which uses requires
So maybe middle ground could be that you can define:
requires: []
To explicitly tell that you do not want any variables.
And:
default:
requires: []
For this to be default for all jobs.
Extension to CI_JOB_TOKEN
The same could apply to CI_JOB_TOKEN
. Not all jobs require it. With &6310, CI_JOB_TOKEN
might even have different permissions. So we could define something like:
requires:
- name: CI_JOB_TOKEN
permission: ['REGISTRY_READ']
Extension what happens if variable is not available
Probably there should be an option to cover two cases:
- Skip the job if variable is not available.
- Fail the job if variable is not available.
So this could be handled by extended syntax like:
requires:
- name: MY_SECRET
allow_missing: true
So in this case jobs would fail unless allow_missing
. In that case the job would be skipped.
Variable might not be available because the user did not provide the value for it (didn't yet configure it or choose not to), or in the case of CI_JOB_TOKEN
, user did not yet approve permissions the job is asking for.
More extensions
I also think that configuration how a variable is passed to the job should be defined in a job and not for a variable. Variable should be the value. And one job might want to get that value as a file and another as a environment variable. So we could also allow:
requires:
- name: MY_SECRET
type: file
Discussion
In a way variables are inputs to jobs. While current syntax supports defining variables, there is no way to define arguments the job defines. So what are expected inputs. This makes it harder to reason about pipelines in general, and I argue is a security issue as well.