content: #
  # Copyright 2015 Hewlett-Packard Enterprise
  #
  # SPDX-License-Identifier: Apache-2.0
  import os
  import subprocess
  from unittest import mock
  
  import fixtures
  import git
  import testtools
  
  from bandit.cli import baseline
  
  config = """
  include:
      - '*.py'
      - '*.pyw'
  
  profiles:
      test:
          include:
              - start_process_with_a_shell
  
  shell_injection:
      subprocess: []
      no_shell: []
      shell:
          - os.system
  """
  
  
  class BanditBaselineToolTests(testtools.TestCase):
      @classmethod
      def setUpClass(cls):
          # Set up prior to running test class
          # read in content used for temporary file contents
          with open("examples/mktemp.py") as fd:
              cls.temp_file_contents = fd.read()
  
      def setUp(self):
          # Set up prior to run each test case
          super().setUp()
          self.current_directory = os.getcwd()
  
      def tearDown(self):
          # Tear down after running each test case
          super().tearDown()
          os.chdir(self.current_directory)
  
      def test_bandit_baseline(self):
          # Tests running bandit via the CLI (baseline) with benign and malicious
          # content
          repo_directory = self.useFixture(fixtures.TempDir()).path
  
          # get benign and findings examples
          with open("examples/okay.py") as fd:
              benign_contents = fd.read()
  
          with open("examples/os_system.py") as fd:
              malicious_contents = fd.read()
  
          contents = {
              "benign_one.py": benign_contents,
              "benign_two.py": benign_contents,
              "malicious.py": malicious_contents,
          }
  
          # init git repo, change directory to it
          git_repo = git.Repo.init(repo_directory)
          git_repo.index.commit("Initial commit")
          os.chdir(repo_directory)
  
          with open("bandit.yaml", "w") as fd:
              fd.write(config)
  
          # create three branches, first has only benign, second adds malicious,
          # third adds benign
  
          branches = [
              {
                  "name": "benign1",
                  "files": ["benign_one.py"],
                  "expected_return": 0,
              },
              {
                  "name": "malicious",
                  "files": ["benign_one.py", "malicious.py"],
                  "expected_return": 1,
              },
              {
                  "name": "benign2",
                  "files": ["benign_one.py", "malicious.py", "benign_two.py"],
                  "expected_return": 0,
              },
          ]
  
          baseline_command = [
              "bandit-baseline",
              "-c",
              "bandit.yaml",
              "-r",
              ".",
              "-p",
              "test",
          ]
  
          for branch in branches:
              branch["branch"] = git_repo.create_head(branch["name"])
              git_repo.head.reference = branch["branch"]
              git_repo.head.reset(working_tree=True)
  
              for f in branch["files"]:
                  with open(f, "w") as fd:
                      fd.write(contents[f])
  
              git_repo.index.add(branch["files"])
              git_repo.index.commit(branch["name"])
  
              self.assertEqual(
                  branch["expected_return"], subprocess.call(baseline_command)
              )
  
      def test_main_non_repo(self):
          # Test that bandit gracefully exits when there is no git repository
          # when calling main
          repo_dir = self.useFixture(fixtures.TempDir()).path
          os.chdir(repo_dir)
  
          # assert the system exits with code 2
          self.assertRaisesRegex(SystemExit, "2", baseline.main)
  
      def test_main_git_command_failure(self):
          # Test that bandit does not run when the Git command fails
          repo_directory = self.useFixture(fixtures.TempDir()).path
          git_repo = git.Repo.init(repo_directory)
          git_repo.index.commit("Initial Commit")
          os.chdir(repo_directory)
  
          additional_content = "additional_file.py"
          with open(additional_content, "w") as fd:
              fd.write(self.temp_file_contents)
          git_repo.index.add([additional_content])
          git_repo.index.commit("Additional Content")
  
          with mock.patch("git.Repo.commit") as mock_git_repo_commit:
              mock_git_repo_commit.side_effect = git.exc.GitCommandError(
                  "commit", ""
              )
  
              # assert the system exits with code 2
              self.assertRaisesRegex(SystemExit, "2", baseline.main)
  
      def test_main_no_parent_commit(self):
          # Test that bandit exits when there is no parent commit detected when
          # calling main
          repo_directory = self.useFixture(fixtures.TempDir()).path
  
          git_repo = git.Repo.init(repo_directory)
          git_repo.index.commit("Initial Commit")
          os.chdir(repo_directory)
  
          # assert the system exits with code 2
          self.assertRaisesRegex(SystemExit, "2", baseline.main)
  
      def test_main_subprocess_error(self):
          # Test that bandit handles a CalledProcessError when attempting to run
          # bandit baseline via a subprocess
          repo_directory = self.useFixture(fixtures.TempDir()).path
  
          git_repo = git.Repo.init(repo_directory)
          git_repo.index.commit("Initial Commit")
          os.chdir(repo_directory)
  
          additional_content = "additional_file.py"
          with open(additional_content, "w") as fd:
              fd.write(self.temp_file_contents)
          git_repo.index.add([additional_content])
          git_repo.index.commit("Additional Content")
  
          with mock.patch("subprocess.check_output") as mock_check_output:
              mock_bandit_cmd = "bandit_mock -b temp_file.txt"
              mock_check_output.side_effect = subprocess.CalledProcessError(
                  "3", mock_bandit_cmd
              )
  
              # assert the system exits with code 3 (returned from
              # CalledProcessError)
              self.assertRaisesRegex(SystemExit, "3", baseline.main)
  
      def test_init_logger(self):
          # Test whether the logger was initialized when calling init_logger
          baseline.init_logger()
          logger = baseline.LOG
  
          # verify that logger was initialized
          self.assertIsNotNone(logger)
  
      def test_initialize_no_repo(self):
          # Test that bandit does not run when there is no current git
          # repository when calling initialize
          repo_directory = self.useFixture(fixtures.TempDir()).path
          os.chdir(repo_directory)
  
          return_value = baseline.initialize()
  
          # assert bandit did not run due to no git repo
          self.assertEqual((None, None, None), return_value)
  
      def test_initialize_git_command_failure(self):
          # Test that bandit does not run when the Git command fails
          repo_directory = self.useFixture(fixtures.TempDir()).path
          git_repo = git.Repo.init(repo_directory)
          git_repo.index.commit("Initial Commit")
          os.chdir(repo_directory)
  
          additional_content = "additional_file.py"
          with open(additional_content, "w") as fd:
              fd.write(self.temp_file_contents)
          git_repo.index.add([additional_content])
          git_repo.index.commit("Additional Content")
  
          with mock.patch("git.Repo") as mock_git_repo:
              mock_git_repo.side_effect = git.exc.GitCommandNotFound("clone", "")
  
              return_value = baseline.initialize()
  
              # assert bandit did not run due to git command failure
              self.assertEqual((None, None, None), return_value)
  
      def test_initialize_dirty_repo(self):
          # Test that bandit does not run when the current git repository is
          # 'dirty' when calling the initialize method
          repo_directory = self.useFixture(fixtures.TempDir()).path
          git_repo = git.Repo.init(repo_directory)
          git_repo.index.commit("Initial Commit")
          os.chdir(repo_directory)
  
          # make the git repo 'dirty'
          with open("dirty_file.py", "w") as fd:
              fd.write(self.temp_file_contents)
          git_repo.index.add(["dirty_file.py"])
  
          return_value = baseline.initialize()
  
          # assert bandit did not run due to dirty repo
          self.assertEqual((None, None, None), return_value)
  
      @mock.patch("sys.argv", ["bandit", "-f", "txt", "test"])
      def test_initialize_existing_report_file(self):
          # Test that bandit does not run when the output file exists (and the
          # provided output format does not match the default format) when
          # calling the initialize method
          repo_directory = self.useFixture(fixtures.TempDir()).path
          git_repo = git.Repo.init(repo_directory)
          git_repo.index.commit("Initial Commit")
          os.chdir(repo_directory)
  
          # create an existing version of output report file
          existing_report = f"{baseline.report_basename}.txt"
          with open(existing_report, "w") as fd:
              fd.write(self.temp_file_contents)
  
          return_value = baseline.initialize()
  
          # assert bandit did not run due to existing report file
          self.assertEqual((None, None, None), return_value)
  
      @mock.patch(
          "bandit.cli.baseline.bandit_args", ["-o", "bandit_baseline_result"]
      )
      def test_initialize_with_output_argument(self):
          # Test that bandit does not run when the '-o' (output) argument is
          # specified
          repo_directory = self.useFixture(fixtures.TempDir()).path
          git_repo = git.Repo.init(repo_directory)
          git_repo.index.commit("Initial Commit")
          os.chdir(repo_directory)
  
          return_value = baseline.initialize()
  
          # assert bandit did not run due to provided -o (--ouput) argument
          self.assertEqual((None, None, None), return_value)
  
      def test_initialize_existing_temp_file(self):
          # Test that bandit does not run when the temporary output file exists
          # when calling the initialize method
          repo_directory = self.useFixture(fixtures.TempDir()).path
          git_repo = git.Repo.init(repo_directory)
          git_repo.index.commit("Initial Commit")
          os.chdir(repo_directory)
  
          # create an existing version of temporary output file
          existing_temp_file = baseline.baseline_tmp_file
          with open(existing_temp_file, "w") as fd:
              fd.write(self.temp_file_contents)
  
          return_value = baseline.initialize()
  
          # assert bandit did not run due to existing temporary report file
          self.assertEqual((None, None, None), return_value)
  