Allow config projects to override allowed-projects
To handle the case where an untrusted project defines a job with a secret which another project would like to run, allow a config project to attach that job to a project-pipeline and have it run regardless of the allowed-projects setting. Normally, untrusted jobs with secrets have an implicit and non-overridable allowed-projects setting of only that project, to avoid a situation where another project with a trusted post-review pipeline gains access to the secret by using a Depends-On to a change which lifts the allowed-projects restriction. This change allows a config project to bypass this, in effect saying that the projects involved trust each other sufficiently (or else, do not have access to a post-review pipeline which could be used to obtain secrets). Change-Id: I52ab193d0e39a37de64c8b3cb6953538e4073b43
This commit is contained in:
parent
2029ac77ba
commit
9021fdf8bb
|
@ -1117,11 +1117,15 @@ Here is an example of two job definitions:
|
|||
all projects permitted to use the job. The current project
|
||||
(where the job is defined) is not automatically included, so if
|
||||
it should be able to run this job, then it must be explicitly
|
||||
listed. By default, all projects may use the job.
|
||||
listed. This setting is ignored by :term:`config projects
|
||||
<config-project>` -- they may add any job to any project's
|
||||
pipelines. By default, all projects may use the job.
|
||||
|
||||
If a :attr:`job.secrets` is used in a job definition in an
|
||||
:term:`untrusted-project`, `allowed-projects` is automatically
|
||||
set to the current project only, and can not be overridden.
|
||||
However, a :term:`config-project` may still add such a job to
|
||||
any project's pipeline.
|
||||
|
||||
.. warning::
|
||||
|
||||
|
@ -1519,7 +1523,9 @@ If a job with secrets is unsafe to be used by other projects, the
|
|||
:attr:`job.allowed-projects` attribute can be used to restrict the
|
||||
projects which can invoke that job. If a job with secrets is defined
|
||||
in an `untrusted-project`, `allowed-projects` is automatically set to
|
||||
that project only, and can not be overridden.
|
||||
that project only, and can not be overridden (though a
|
||||
:term:`config-project` may still add the job to any project's pipeline
|
||||
regardless of this setting).
|
||||
|
||||
Secrets, like most configuration items, are unique within a tenant,
|
||||
though a secret may be defined on multiple branches of the same
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Config projects may now add any job to any project's pipelines,
|
||||
regardless of the setting of allowed-projets (including the implicit
|
||||
setting of allowed-projects on jobs with secrets in untrusted
|
||||
projects).
|
2
tests/fixtures/config/allowed-projects-trusted/git/common-config/playbooks/base.yaml
vendored
Normal file
2
tests/fixtures/config/allowed-projects-trusted/git/common-config/playbooks/base.yaml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
- hosts: all
|
||||
tasks: []
|
|
@ -0,0 +1,30 @@
|
|||
- pipeline:
|
||||
name: check
|
||||
manager: independent
|
||||
post-review: True
|
||||
trigger:
|
||||
gerrit:
|
||||
- event: patchset-created
|
||||
success:
|
||||
gerrit:
|
||||
Verified: 1
|
||||
failure:
|
||||
gerrit:
|
||||
Verified: -1
|
||||
|
||||
- job:
|
||||
name: base
|
||||
run: playbooks/base.yaml
|
||||
parent: null
|
||||
|
||||
- project:
|
||||
name: common-config
|
||||
check:
|
||||
jobs: []
|
||||
|
||||
- project:
|
||||
name: org/project2
|
||||
check:
|
||||
jobs:
|
||||
- test-project1
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
- secret:
|
||||
name: project1_secret
|
||||
data: {}
|
||||
|
||||
- job:
|
||||
name: test-project1
|
||||
secrets: project1_secret
|
||||
|
||||
- project:
|
||||
name: org/project1
|
||||
check:
|
||||
jobs:
|
||||
- test-project1
|
|
@ -0,0 +1,4 @@
|
|||
- project:
|
||||
name: org/project2
|
||||
check:
|
||||
jobs: []
|
|
@ -0,0 +1,10 @@
|
|||
- tenant:
|
||||
name: tenant-one
|
||||
source:
|
||||
gerrit:
|
||||
config-projects:
|
||||
- common-config
|
||||
untrusted-projects:
|
||||
- org/project1
|
||||
- org/project2
|
||||
- org/project3
|
|
@ -801,6 +801,22 @@ class TestAllowedProjects(ZuulTestCase):
|
|||
'to run job test-project2b', B.messages[0])
|
||||
|
||||
|
||||
class TestAllowedProjectsTrusted(ZuulTestCase):
|
||||
tenant_config_file = 'config/allowed-projects-trusted/main.yaml'
|
||||
|
||||
def test_allowed_projects_secret_trusted(self):
|
||||
# Test that an untrusted job defined in project1 can be used
|
||||
# in project2, but only if attached by a config project.
|
||||
A = self.fake_gerrit.addFakeChange('org/project2', 'master', 'A')
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertEqual(A.reported, 1)
|
||||
self.assertIn('Build succeeded', A.messages[0])
|
||||
self.assertHistory([
|
||||
dict(name='test-project1', result='SUCCESS', changes='1,1'),
|
||||
], ordered=False)
|
||||
|
||||
|
||||
class TestCentralJobs(ZuulTestCase):
|
||||
tenant_config_file = 'config/central-jobs/main.yaml'
|
||||
|
||||
|
|
|
@ -670,6 +670,14 @@ class JobParser(object):
|
|||
job.variant_description = conf.get(
|
||||
'variant-description', " ".join(as_list(conf.get('branches'))))
|
||||
|
||||
if project_pipeline and conf['_source_context'].trusted:
|
||||
# A config project has attached this job to a
|
||||
# project-pipeline. In this case, we can ignore
|
||||
# allowed-projects -- the superuser has stated they want
|
||||
# it to run. This can be useful to allow untrusted jobs
|
||||
# with secrets to be run in other untrusted projects.
|
||||
job.ignore_allowed_projects = True
|
||||
|
||||
if 'parent' in conf:
|
||||
if conf['parent'] is not None:
|
||||
# Parent job is explicitly specified, so inherit from it.
|
||||
|
|
|
@ -1145,6 +1145,8 @@ class Job(ConfigObject):
|
|||
provides=frozenset(),
|
||||
requires=frozenset(),
|
||||
dependencies=frozenset(),
|
||||
ignore_allowed_projects=None, # internal, but inherited
|
||||
# in the usual manner
|
||||
)
|
||||
|
||||
# These attributes affect how the job is actually run and more
|
||||
|
@ -3941,7 +3943,8 @@ class Layout(object):
|
|||
raise Exception("Job %s is abstract and may not be "
|
||||
"directly run" %
|
||||
(frozen_job.name,))
|
||||
if (frozen_job.allowed_projects is not None and
|
||||
if (not frozen_job.ignore_allowed_projects and
|
||||
frozen_job.allowed_projects is not None and
|
||||
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))
|
||||
|
|
Loading…
Reference in New Issue