Test that secrets don't leak into logs
This executes a job which writes a secret into a file in the jobdir, which is typical of how we would expect many jobs which use secrets to operate. It also executes a similar job where ansible fails to write the file, to test that error-handling code doesn't helpfully leak the secret. It runs both of those tests with and without '-vvv' set. It then searches for that secret in all files in the jobdir and ensures it doesn't show up in any unexpected files. This includes the ansible log(s). Change-Id: Ie6ebe301f256d20e482b5f6c64f3ce2fb2b5135d
This commit is contained in:
parent
6345e20e56
commit
db08903c81
6
tests/fixtures/config/secret-leaks/git/common-config/playbooks/secret-file-fail.yaml
vendored
Normal file
6
tests/fixtures/config/secret-leaks/git/common-config/playbooks/secret-file-fail.yaml
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
- hosts: all
|
||||
tasks:
|
||||
- copy:
|
||||
content: "{{test_secret.username}} {{test_secret.password}}"
|
||||
dest: "{{zuul.executor.work_root}}/failure-file.txt"
|
||||
group: "hopefullythisgroupdoesnotexist"
|
5
tests/fixtures/config/secret-leaks/git/common-config/playbooks/secret-file.yaml
vendored
Normal file
5
tests/fixtures/config/secret-leaks/git/common-config/playbooks/secret-file.yaml
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
- hosts: all
|
||||
tasks:
|
||||
- copy:
|
||||
content: "{{test_secret.username}} {{test_secret.password}}"
|
||||
dest: "{{zuul.executor.work_root}}/secret-file.txt"
|
|
@ -0,0 +1,70 @@
|
|||
- pipeline:
|
||||
name: check
|
||||
manager: independent
|
||||
post-review: true
|
||||
trigger:
|
||||
gerrit:
|
||||
- event: patchset-created
|
||||
success:
|
||||
gerrit:
|
||||
Verified: 1
|
||||
failure:
|
||||
gerrit:
|
||||
Verified: -1
|
||||
|
||||
- pipeline:
|
||||
name: gate
|
||||
manager: dependent
|
||||
success-message: Build succeeded (gate).
|
||||
trigger:
|
||||
gerrit:
|
||||
- event: comment-added
|
||||
approval:
|
||||
- Approved: 1
|
||||
success:
|
||||
gerrit:
|
||||
Verified: 2
|
||||
submit: true
|
||||
failure:
|
||||
gerrit:
|
||||
Verified: -2
|
||||
start:
|
||||
gerrit:
|
||||
Verified: 0
|
||||
precedence: high
|
||||
|
||||
- secret:
|
||||
name: test_secret
|
||||
data:
|
||||
username: test-username
|
||||
password: !encrypted/pkcs1-oaep |
|
||||
BFhtdnm8uXx7kn79RFL/zJywmzLkT1GY78P3bOtp4WghUFWobkifSu7ZpaV4NeO0s71YUsi1wGZZ
|
||||
L0LveZjUN0t6OU1VZKSG8R5Ly7urjaSo1pPVIq5Rtt/H7W14Lecd+cUeKb4joeusC9drN3AA8a4o
|
||||
ykcVpt1wVqUnTbMGC9ARMCQP6eopcs1l7tzMseprW4RDNhIuz3CRgd0QBMPl6VDoFgBPB8vxtJw+
|
||||
3m0rqBYZCLZgCXekqlny8s2s92nJMuUABbJOEcDRarzibDsSXsfJt1y+5n7yOURsC7lovMg4GF/v
|
||||
Cl/0YMKjBO5bpv9EM5fToeKYyPGSKQoHOnCYceb3cAVcv5UawcCic8XjhEhp4K7WPdYf2HVAC/qt
|
||||
xhbpjTxG4U5Q/SoppOJ60WqEkQvbXs6n5Dvy7xmph6GWmU/bAv3eUK3pdD3xa2Ue1lHWz3U+rsYr
|
||||
aI+AKYsMYx3RBlfAmCeC1ve2BXPrqnOo7G8tnUvfdYPbK4Aakk0ds/AVqFHEZN+S6hRBmBjLaRFW
|
||||
Z3QSO1NjbBxWnaHKZYT7nkrJm8AMCgZU0ZArFLpaufKCeiK5ECSsDxic4FIsY1OkWT42qEUfL0Wd
|
||||
+150AKGNZpPJnnP3QYY4W/MWcKH/zdO400+zWN52WevbSqZy90tqKDJrBkMl1ydqbuw1E4ZHvIs=
|
||||
|
||||
- job:
|
||||
name: base
|
||||
parent: null
|
||||
|
||||
- job:
|
||||
parent: base
|
||||
name: secret-file
|
||||
secrets:
|
||||
- test_secret
|
||||
|
||||
- job:
|
||||
parent: base
|
||||
name: secret-file-fail
|
||||
secrets:
|
||||
- test_secret
|
||||
|
||||
- project:
|
||||
name: org/project
|
||||
check:
|
||||
jobs: []
|
|
@ -0,0 +1 @@
|
|||
test
|
|
@ -0,0 +1,8 @@
|
|||
- tenant:
|
||||
name: tenant-one
|
||||
source:
|
||||
gerrit:
|
||||
config-projects:
|
||||
- common-config
|
||||
untrusted-projects:
|
||||
- org/project
|
|
@ -1245,3 +1245,89 @@ class TestBaseJobs(ZuulTestCase):
|
|||
self.assertIn('Base jobs must be defined in config projects',
|
||||
A.messages[0])
|
||||
self.assertHistory([])
|
||||
|
||||
|
||||
class TestSecretLeaks(AnsibleZuulTestCase):
|
||||
tenant_config_file = 'config/secret-leaks/main.yaml'
|
||||
|
||||
def searchForContent(self, path, content):
|
||||
matches = []
|
||||
for (dirpath, dirnames, filenames) in os.walk(path):
|
||||
for filename in filenames:
|
||||
filepath = os.path.join(dirpath, filename)
|
||||
with open(filepath, 'rb') as f:
|
||||
if content in f.read():
|
||||
matches.append(filepath[len(path):])
|
||||
return matches
|
||||
|
||||
def _test_secret_file(self):
|
||||
# Or rather -- test that they *don't* leak.
|
||||
# Keep the jobdir around so we can inspect contents.
|
||||
self.executor_server.keep_jobdir = True
|
||||
conf = textwrap.dedent(
|
||||
"""
|
||||
- project:
|
||||
name: org/project
|
||||
check:
|
||||
jobs:
|
||||
- secret-file
|
||||
""")
|
||||
|
||||
file_dict = {'.zuul.yaml': conf}
|
||||
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
||||
files=file_dict)
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertHistory([
|
||||
dict(name='secret-file', result='SUCCESS', changes='1,1'),
|
||||
], ordered=False)
|
||||
matches = self.searchForContent(self.history[0].jobdir.root,
|
||||
b'test-password')
|
||||
self.assertEqual(set(['/ansible/playbook_0/secrets.yaml',
|
||||
'/work/secret-file.txt']),
|
||||
set(matches))
|
||||
|
||||
def test_secret_file(self):
|
||||
self._test_secret_file()
|
||||
|
||||
def test_secret_file_verbose(self):
|
||||
# Output extra ansible info to exercise alternate logging code
|
||||
# paths.
|
||||
self.executor_server.verbose = True
|
||||
self._test_secret_file()
|
||||
|
||||
def _test_secret_file_fail(self):
|
||||
# Or rather -- test that they *don't* leak.
|
||||
# Keep the jobdir around so we can inspect contents.
|
||||
self.executor_server.keep_jobdir = True
|
||||
conf = textwrap.dedent(
|
||||
"""
|
||||
- project:
|
||||
name: org/project
|
||||
check:
|
||||
jobs:
|
||||
- secret-file-fail
|
||||
""")
|
||||
|
||||
file_dict = {'.zuul.yaml': conf}
|
||||
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A',
|
||||
files=file_dict)
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
self.assertHistory([
|
||||
dict(name='secret-file-fail', result='FAILURE', changes='1,1'),
|
||||
], ordered=False)
|
||||
matches = self.searchForContent(self.history[0].jobdir.root,
|
||||
b'test-password')
|
||||
self.assertEqual(set(['/ansible/playbook_0/secrets.yaml',
|
||||
'/work/failure-file.txt']),
|
||||
set(matches))
|
||||
|
||||
def test_secret_file_fail(self):
|
||||
self._test_secret_file_fail()
|
||||
|
||||
def test_secret_file_fail_verbose(self):
|
||||
# Output extra ansible info to exercise alternate logging code
|
||||
# paths.
|
||||
self.executor_server.verbose = True
|
||||
self._test_secret_file_fail()
|
||||
|
|
Loading…
Reference in New Issue