def test_repositories_added_can_be_scanned(self, mock_rootdir, repo_to_scan): directory = '{}/repos/{}'.format( mock_rootdir, BaseStorage.hash_filename('Yelp/detect-secrets'), ) mocked_sha = 'aabbcc' # We don't **actually** want to clone the repo per test run. with mock_git_calls( SubprocessMock(expected_input=( 'git clone https://github.com/Yelp/detect-secrets {} --bare' ).format(directory, ), ), # Since there is no prior sha to retrieve SubprocessMock( expected_input='git rev-parse HEAD', mocked_output=mocked_sha, )): assert main([ 'add', 'https://github.com/Yelp/detect-secrets', '--root-dir', mock_rootdir, ]) == 0 with mock_git_calls( # Getting latest changes SubprocessMock( expected_input='git rev-parse --abbrev-ref HEAD', mocked_output='master', ), SubprocessMock( expected_input= 'git fetch --quiet origin master:master --force', ), # Getting relevant diff SubprocessMock( expected_input= 'git diff {} HEAD --name-only --diff-filter ACM'.format( mocked_sha), mocked_output='filenameA', ), SubprocessMock( expected_input='git diff {} HEAD -- filenameA'.format( mocked_sha), mocked_output='', ), # Storing latest sha SubprocessMock(expected_input='git rev-parse HEAD', ), ): assert main([ 'scan', repo_to_scan, '--root-dir', mock_rootdir, ]) == 0
def test_no_baseline(self, mock_logic, mock_rootdir): repo = mock_logic() with mock_git_calls(*self.git_calls(mock_rootdir)): secrets = repo.scan() # It matches both HexHighEntropyString and AWSKeyDetector assert len(secrets.data['examples/aws_credentials.json']) == 2
def test_add_local_repo(self, mock_file_operations, mock_rootdir): # This just needs to exist; no actual operations will be done to this. repo = 'examples' git_calls = [ # repo.update SubprocessMock( expected_input='git rev-parse HEAD', mocked_output='mocked_sha', ), ] with mock_git_calls(*git_calls): args = self.parse_args( 'add {} --baseline .secrets.baseline --local --root-dir {}'. format( repo, mock_rootdir, )) add_repo(args) mock_file_operations.write.assert_called_with( metadata_factory( sha='mocked_sha', repo=os.path.abspath( os.path.join( os.path.dirname(__file__), '../../examples', ), ), baseline_filename='.secrets.baseline', json=True, ), )
def test_no_baseline_file_provided(self, mock_logic, mock_rootdir): repo = mock_logic( baseline_filename=None, ) with mock_git_calls(*self.git_calls(mock_rootdir)[:-1]): secrets = repo.scan() assert len(secrets.data['examples/aws_credentials.json']) == 3
def wrapped_mock_git_calls(git_calls): if not git_calls: # Need to yield **something** yield return with mock_git_calls(*git_calls): yield
def test_clone_repo_if_exists(self, base_storage, mock_rootdir): with assert_directories_created(): repo = base_storage.setup('[email protected]:yelp/detect-secrets') with mock_git_calls( self.construct_subprocess_mock_git_clone( repo, b'fatal: destination path \'blah\' already exists', mock_rootdir, ), ): repo.clone()
def test_name(self, repo, name, local_storage): """OK, I admit this is kinda a lame test case, because technically everything is mocked out. However, it's needed for coverage, and it *does* test things (kinda). """ with mock_git_calls( SubprocessMock( expected_input='git remote get-url origin', mocked_output='[email protected]:yelp/detect-secrets', ), ), assert_directories_created(): assert local_storage.setup(repo).repository_name == name
def test_success(self, mock_logic): repo = mock_logic() with mock_git_calls( SubprocessMock( expected_input='git rev-parse HEAD', mocked_output='new_hash', )): repo.update() assert repo.last_commit_hash == 'new_hash'
def test_clone_repo_something_else_went_wrong(self, mock_rootdir, base_storage): with assert_directories_created(): repo = base_storage.setup('[email protected]:yelp/detect-secrets') with mock_git_calls( self.construct_subprocess_mock_git_clone( repo, b'Some other error message, not expected', mock_rootdir, )), pytest.raises(subprocess.CalledProcessError): repo.clone()
def test_error_when_getting_git_tracked_files(self, path): with mock_git_calls( 'detect_secrets.core.baseline.subprocess.check_output', (SubprocessMock( expected_input='git -C ./test_data/files ls-files', should_throw_exception=True, mocked_output='', ), ), ): results = self.get_results(path=['./test_data/files']) assert not results
def test_no_files_in_git_repo(self): with mock_git_calls( 'detect_secrets.core.baseline.subprocess.check_output', (SubprocessMock( expected_input='git ls-files will_be_mocked', should_throw_exception=True, mocked_output='', ), ), ): results = self.get_results(path=['will_be_mocked']) assert not results
def test_unable_to_find_baseline(self, mock_logic, mock_rootdir): calls = self.git_calls(mock_rootdir) calls[-1] = SubprocessMock( expected_input='git show HEAD:foobar', mocked_output=b'fatal: Path \'foobar\' does not exist', should_throw_exception=True, ) repo = mock_logic() with mock_git_calls(*calls): secrets = repo.scan() assert len(secrets.data['examples/aws_credentials.json']) == 2
def test_no_files_in_git_repo(self): with mock_git_calls( 'detect_secrets.core.baseline.subprocess.check_output', ( SubprocessMock( expected_input='git ls-files will_be_mocked', should_throw_exception=True, mocked_output='', ), ), ): results = self.get_results(rootdir='will_be_mocked') assert not results
def test_quit_if_baseline_is_changed_but_not_staged(self, mock_log): with mock_git_calls( 'detect_secrets.pre_commit_hook.subprocess.check_output', (SubprocessMock( expected_input='git diff --name-only', mocked_output=b'baseline.file', ), ), ): assert_commit_blocked( '--baseline baseline.file test_data/files/file_with_secrets.py', ) assert mock_log.error_messages == ( 'Your baseline file (baseline.file) is unstaged.\n' '`git add baseline.file` to fix this.\n')
def test_scan_nonexistent_last_saved_hash(self, mock_logic, mock_rootdir): calls = self.git_calls(mock_rootdir) calls[-2] = SubprocessMock( expected_input= 'git diff sha256-hash HEAD -- examples/aws_credentials.json', mocked_output=b'fatal: the hash is not in git history', should_throw_exception=True, ) calls[-1] = SubprocessMock(expected_input='git rev-parse HEAD', ) repo = mock_logic() with mock_git_calls(*calls): secrets = repo.scan() assert secrets.data == {}
def test_exclude_lines( self, mock_logic, mock_rootdir, exclude_lines_regex, expected_line_number, ): repo = mock_logic() with mock_git_calls(*self.git_calls(mock_rootdir)): secrets = repo.scan(exclude_lines_regex=exclude_lines_regex) assert len(secrets.data) == 1 assert len(secrets.data['examples/aws_credentials.json']) == 1 for _, secret in secrets.data['examples/aws_credentials.json'].items(): assert secret.lineno == expected_line_number
def test_scan_with_baseline(self, mock_logic, mock_rootdir): baseline = json.dumps({ 'results': { 'examples/aws_credentials.json': [ { 'type': 'Hex High Entropy String', 'hashed_secret': '2353d31737bbbdb10eb97466b8f2dc057ead1432', 'line_number': 3, # does not matter }, { 'type': 'AWS Access Key', 'hashed_secret': '25910f981e85ca04baf359199dd0bd4a3ae738b6', 'line_number': 3, # does not matter }, { 'type': 'IBM COS HMAC Credentials', 'hashed_secret': '9c6e0753631454e4ab8d896c242dcf4f8300fd57', 'line_number': 3, # does not matter }, ], }, 'exclude_regex': '', 'plugins_used': [ { 'hex_limit': 3.5, 'name': 'HexHighEntropyString', }, { 'name': 'AWSKeyDetector', }, { 'name': 'IbmCosHmacDetector', }, ], }) calls = self.git_calls(mock_rootdir) calls[-1] = SubprocessMock( expected_input='git show HEAD:foobar', mocked_output=baseline, ) repo = mock_logic() with mock_git_calls(*calls): secrets = repo.scan() assert len(secrets.data) == 0
def test_quit_if_baseline_is_changed_but_not_staged(self, mock_log): with mock_git_calls( 'detect_secrets.pre_commit_hook.subprocess.check_output', ( SubprocessMock( expected_input='git diff --name-only', mocked_output=b'baseline.file', ), ), ): assert_commit_blocked( '--baseline baseline.file test_data/files/file_with_secrets.py', ) assert mock_log.error_messages == ( 'Your baseline file (baseline.file) is unstaged.\n' '`git add baseline.file` to fix this.\n' )
def add_non_local_repo(self, mock_rootdir): repo = '[email protected]:yelp/detect-secrets' directory = '{}/repos/{}'.format( mock_rootdir, BaseStorage.hash_filename('yelp/detect-secrets'), ) git_calls = [ SubprocessMock(expected_input='git clone {} {} --bare'.format( repo, directory), ), SubprocessMock( expected_input='git rev-parse HEAD', mocked_output='mocked_sha', ), ] with mock_git_calls(*git_calls): args = self.parse_args('add {} --root-dir {}'.format( repo, mock_rootdir)) add_repo(args)
def test_add_s3_backend_repo(self, mock_file_operations, mocked_boto): args = self.parse_args( 'add {} ' '--local ' '--storage s3 ' '--s3-credentials-file examples/aws_credentials.json ' '--s3-bucket pail'.format('examples'), has_s3=True, ) git_calls = [ # repo.update SubprocessMock( expected_input='git rev-parse HEAD', mocked_output='mocked_sha', ), ] with mock_git_calls(*git_calls): mocked_boto.list_objects_v2.return_value = {} add_repo(args)
def test_exclude_files(self, mock_logic, mock_rootdir): repo = mock_logic() with mock_git_calls(*self.git_calls(mock_rootdir)): secrets = repo.scan(exclude_files_regex=r'aws_credentials.json$') assert 'examples/aws_credentials.json' not in secrets.data
def test_clone(self, local_storage): # We're asserting that nothing is run in this case. with mock_git_calls(), assert_directories_created(): local_storage.setup('[email protected]:yelp/detect-secrets')\ .clone()