def test_bb_not_implemented(self):
     """Ensure NotImplementedError raised for Bitbucket."""
     evidence = RepoBranchProtectionEvidence('bb_foo.json', 'bar')
     evidence.set_content('{"matters": "not"}')
     gl_err_msg = 'Support for Bitbucket coming soon...'
     with self.assertRaises(NotImplementedError) as ae:
         _ = evidence.admin_enforce
     self.assertEqual(str(ae.exception), gl_err_msg)
     with self.assertRaises(NotImplementedError) as scr:
         _ = evidence.signed_commits_required
     self.assertEqual(str(scr.exception), gl_err_msg)
 def test_signed_commits_required(self):
     """Ensure enforce admin details returned."""
     evidence = RepoBranchProtectionEvidence('gh_foo.json', 'bar')
     evidence.set_content('{"foo": "bar"}')
     self.assertFalse(evidence.signed_commits_required)
     evidence.set_content('{"required_signatures": {"enabled": true}}')
     # False expected because as_a_dict content already fetched
     self.assertFalse(evidence.signed_commits_required)
     evidence = RepoBranchProtectionEvidence('gh_foo.json', 'bar')
     evidence.set_content('{"required_signatures": {"enabled": true}}')
     # True expected because evidence is a new object
     self.assertTrue(evidence.signed_commits_required)
 def test_branch_protection_integrity(self):
     """Check whether branch protection settings are set for admins."""
     locker_branches = self.config.get(
         'org.auditree.locker_integrity.branches',
         self.config.get('org.auditree.repo_integrity.branches',
                         {self.config.get('locker.repo_url'): ['master']}))
     for locker_url, branches in locker_branches.items():
         parsed = urlparse(locker_url)
         service = 'gh'
         if 'gitlab' in parsed.hostname:
             service = 'gl'
         elif 'bitbucket' in parsed.hostname:
             service = 'bb'
         repo = parsed.path.strip('/')
         for branch in branches:
             filename = [
                 service,
                 repo.lower().replace('/', '_').replace('-', '_'),
                 branch.lower().replace('-', '_'), 'branch_protection.json'
             ]
             path = f'raw/auditree/{"_".join(filename)}'
             with evidences(self, path) as raw:
                 evidence = RepoBranchProtectionEvidence.from_evidence(raw)
                 if not evidence.admin_enforce:
                     self.add_failures(
                         'Locker Branch Protection',
                         (f'Branch protection for `{locker_url}` '
                          f'`{branch}` branch '
                          'is not enforced for administrators.'))
 def test_branch_protection_commit_integrity(self):
     """Check that branch protection requires signed commits."""
     locker_branches = self.config.get(
         'org.auditree.locker_integrity.branches',
         self.config.get('org.auditree.repo_integrity.branches',
                         {self.config.get('locker.repo_url'): ['master']}))
     for locker_url, branches in locker_branches.items():
         parsed = urlparse(locker_url)
         service = 'gh'
         if 'gitlab' in parsed.hostname:
             service = 'gl'
         elif 'bitbucket' in parsed.hostname:
             service = 'bb'
         repo = parsed.path.strip('/')
         for branch in branches:
             filename = [
                 service,
                 repo.lower().replace('/', '_').replace('-', '_'),
                 branch.lower().replace('-', '_'), 'branch_protection.json'
             ]
             path = f'raw/auditree/{"_".join(filename)}'
             with evidences(self, path) as raw:
                 evidence = RepoBranchProtectionEvidence.from_evidence(raw)
                 if not evidence.signed_commits_required:
                     self.add_failures(('Locker Branch Protection - '
                                        '(Signed Commits Disabled)'),
                                       f'`{locker_url}` `{branch}` branch.')
 def fetch_gh_repo_branch_protection_details(self):
     """Fetch Github repository branch protection metadata."""
     branches = self.config.get(
         'org.auditree.repo_integrity.branches',
         {self.config.get('locker.repo_url'): ['master']})
     current_url = None
     github = None
     for repo_url, repo_branches in branches.items():
         parsed = urlparse(repo_url)
         base_url = f'{parsed.scheme}://{parsed.hostname}'
         repo = parsed.path.strip('/')
         for branch in repo_branches:
             file_prefix_parts = [
                 repo.lower().replace('/', '_').replace('-', '_'),
                 branch.lower().replace('-', '_')
             ]
             file_prefix = '_'.join(file_prefix_parts)
             path = ['auditree', f'gh_{file_prefix}_branch_protection.json']
             if base_url != current_url:
                 github = Github(self.config.creds, base_url)
                 current_url = base_url
             self.config.add_evidences([
                 RepoBranchProtectionEvidence(
                     path[1], path[0], DAY,
                     (f'Github branch protection for {repo} repo '
                      f'{branch} branch'))
             ])
             joined_path = os.path.join(*path)
             with raw_evidence(self.locker, joined_path) as evidence:
                 if evidence:
                     evidence.set_content(
                         json.dumps(
                             github.get_branch_protection_details(
                                 repo, branch)))
 def test_as_a_dict(self):
     """Ensure dict returned when content is present."""
     evidence = RepoBranchProtectionEvidence('gh_foo.json', 'bar')
     evidence.set_content('{"foo": "bar"}')
     self.assertEqual(evidence.as_a_dict, {'foo': 'bar'})
 def test_no_content(self):
     """Ensure properties requiring content return None when no content."""
     evidence = RepoBranchProtectionEvidence('gh_foo.json', 'bar')
     self.assertIsNone(evidence.admin_enforce)
     self.assertIsNone(evidence.signed_commits_required)
     self.assertIsNone(evidence.as_a_dict)