Add 'allow-secrets' pipeline attribute

This permits an operator to specify that a given pipeline should
never run a job with secrets.  This may be used, for example, to
ensure that no one adds, say, the pypi-upload job to a check
pipeline and then uses that to expose credentials.

Change-Id: I606a76fe9ed19bb87d78f07195fb3950805e8726
This commit is contained in:
James E. Blair 2017-03-17 13:59:35 -07:00
parent b3f5db1de3
commit d234836387
4 changed files with 50 additions and 2 deletions

View File

@ -2,6 +2,7 @@
name: check
manager: independent
source: gerrit
allow-secrets: true
trigger:
gerrit:
- event: patchset-created

View File

@ -616,6 +616,43 @@ class TestJob(BaseTestCase):
"Project project2 is not allowed to run job job"):
item.freezeJobGraph()
def test_job_pipeline_allow_secrets(self):
self.pipeline.allow_secrets = False
job = configloader.JobParser.fromYaml(self.tenant, self.layout, {
'_source_context': self.context,
'_start_mark': self.start_mark,
'name': 'job',
})
auth = model.AuthContext()
auth.secrets.append('foo')
job.auth = auth
self.layout.addJob(job)
project_config = configloader.ProjectParser.fromYaml(
self.tenant, self.layout, [{
'_source_context': self.context,
'_start_mark': self.start_mark,
'name': 'project',
'gate': {
'jobs': [
'job'
]
}
}]
)
self.layout.addProjectConfig(project_config)
change = model.Change(self.project)
# Test master
change.branch = 'master'
item = self.queue.enqueueChange(change)
item.current_build_set.layout = self.layout
with testtools.ExpectedException(
Exception,
"Pipeline gate does not allow jobs with secrets"):
item.freezeJobGraph()
class TestJobTimeData(BaseTestCase):
def setUp(self):

View File

@ -608,6 +608,7 @@ class PipelineParser(object):
'footer-message': str,
'dequeue-on-new-patchset': bool,
'ignore-dependencies': bool,
'allow-secrets': bool,
'disable-after-consecutive-failures':
vs.All(int, vs.Range(min=1)),
'window': window,
@ -655,6 +656,7 @@ class PipelineParser(object):
'dequeue-on-new-patchset', True)
pipeline.ignore_dependencies = conf.get(
'ignore-dependencies', False)
pipeline.allow_secrets = conf.get('allow-secrets', False)
for conf_key, action in PipelineParser.reporter_actions.items():
reporter_set = []

View File

@ -121,6 +121,7 @@ class Pipeline(object):
self.success_message = None
self.footer_message = None
self.start_message = None
self.allow_secrets = False
self.dequeue_on_new_patchset = True
self.ignore_dependencies = False
self.manager = None
@ -2321,7 +2322,9 @@ class Layout(object):
def addProjectConfig(self, project_config):
self.project_configs[project_config.name] = project_config
def _createJobGraph(self, change, job_list, job_graph):
def _createJobGraph(self, item, job_list, job_graph):
change = item.change
pipeline = item.pipeline
for jobname in job_list.jobs:
# This is the final job we are constructing
frozen_job = None
@ -2360,6 +2363,11 @@ class Layout(object):
change.project.name not in frozen_job.allowed_projects):
raise Exception("Project %s is not allowed to run job %s" %
(change.project.name, frozen_job.name))
if ((not pipeline.allow_secrets) and frozen_job.auth and
frozen_job.auth.secrets):
raise Exception("Pipeline %s does not allow jobs with "
"secrets (job %s)" % (
pipeline.name, frozen_job.name))
job_graph.addJob(frozen_job)
def createJobGraph(self, item):
@ -2371,7 +2379,7 @@ class Layout(object):
if project_config and item.pipeline.name in project_config.pipelines:
project_job_list = \
project_config.pipelines[item.pipeline.name].job_list
self._createJobGraph(item.change, project_job_list, ret)
self._createJobGraph(item, project_job_list, ret)
return ret