Exemple #1
0
def main() -> None:
    """Main command dispatcher."""
    if not (sys.version_info.major == 3 and sys.version_info.minor == 6):
        print('ERROR: Python 3.6 is required, found Python {}.{}.{}'.format(
            sys.version_info.major, sys.version_info.minor,
            sys.version_info.micro))
        exit(1)

    manager = Manager()

    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument('command',
                        choices=sorted(manager.commands),
                        help=manager.help,
                        metavar='command')
    parser.add_argument('--version',
                        action='version',
                        version='BinaryAlert v{}'.format(__version__))
    args = parser.parse_args()

    manager.run(args.command)
Exemple #2
0
 def test_cb_copy_all_not_enabled(self):
     """Raises InvalidConfigError if the downloader is not enabled."""
     self._write_config(enable_downloader=False)
     self.manager = Manager()  # Reload manager with the new config.
     with self.assertRaises(InvalidConfigError):
         self.manager.cb_copy_all()
Exemple #3
0
class ManagerTest(FakeFilesystemBase):
    """Tests for the Manager class."""
    @mock.patch('sys.stderr', mock.MagicMock()
                )  # pyhcl complains about unused tokens to stderr.
    def setUp(self):
        super().setUp()
        self.manager = Manager()

    def test_commands(self):
        """Each command should be a function in the class."""
        for command in self.manager.commands:
            self.assertTrue(hasattr(self.manager, command))

    def test_help(self):
        """Help string should contain as many lines as there are commands."""
        self.assertEqual(len(self.manager.commands),
                         len(self.manager.help.split('\n')))

    @mock.patch.object(manager_module, 'JoinableQueue')
    @mock.patch.object(manager_module, 'Worker')
    @mock.patch.object(manager_module, 'print')
    def test_enqueue(self, mock_print: mock.MagicMock,
                     mock_worker: mock.MagicMock,
                     mock_task_queue: mock.MagicMock):
        """SQS messages are batched and enqueued"""
        messages = ({'index': i} for i in range(25))
        self.manager._enqueue('test-queue', messages, lambda msg:
                              (1, msg['index']))
        mock_task_queue.assert_called()
        mock_worker.assert_called()
        mock_print.assert_called()

    @mock.patch.object(subprocess, 'check_call')
    def test_apply(self, mock_subprocess: mock.MagicMock):
        """Validate order of Terraform operations."""
        self.manager.apply()
        mock_subprocess.assert_has_calls([
            mock.call(['terraform', 'init']),
            mock.call(['terraform', 'fmt']),
            mock.call(['terraform', 'apply', '-auto-approve=false'])
        ])

    @mock.patch.object(manager_module, 'lambda_build')
    def test_build(self, mock_build: mock.MagicMock):
        """Calls lambda_build function (tested elsewhere)."""
        self.manager.build()
        mock_build.assert_called_once()

    def test_cb_copy_all_not_enabled(self):
        """Raises InvalidConfigError if the downloader is not enabled."""
        self._write_config(enable_downloader=False)
        self.manager = Manager()  # Reload manager with the new config.
        with self.assertRaises(InvalidConfigError):
            self.manager.cb_copy_all()

    @mock.patch.object(manager_module.clone_rules, 'clone_remote_rules')
    def test_clone_rules(self, mock_clone: mock.MagicMock):
        """Calls clone_remote_rules (tested elsewhere)."""
        self.manager.clone_rules()
        mock_clone.assert_called_once()

    @mock.patch.object(manager_module.compile_rules, 'compile_rules')
    @mock.patch.object(manager_module, 'print')
    def test_compile_rules(self, mock_print: mock.MagicMock,
                           mock_compile: mock.MagicMock):
        """Calls compile_rules (tested elsewhere)."""
        self.manager.compile_rules()
        mock_compile.assert_called_once()
        mock_print.assert_called_once()

    @mock.patch.object(BinaryAlertConfig, 'configure')
    @mock.patch.object(manager_module, 'print')
    def test_configure(self, mock_print: mock.MagicMock,
                       mock_configure: mock.MagicMock):
        """Calls BinaryAlertConfig:configure() (tested elsewhere)."""
        self.manager.configure()
        mock_configure.assert_called_once()
        mock_print.assert_called_once()

    @mock.patch.object(Manager, 'unit_test')
    @mock.patch.object(Manager, 'build')
    @mock.patch.object(Manager, 'apply')
    def test_deploy(self, mock_apply: mock.MagicMock,
                    mock_build: mock.MagicMock, mock_test: mock.MagicMock):
        """Deploy docstring includes each executed command and runs each."""
        for command in ['unit_test', 'build', 'apply']:
            self.assertIn(command, inspect.getdoc(Manager.deploy))

        self.manager.deploy()
        mock_test.assert_called_once()
        mock_build.assert_called_once()
        mock_apply.assert_called_once()

    @mock.patch.object(config_module, 'input', side_effect=mock_input)
    @mock.patch.object(manager_module, 'print')
    @mock.patch.object(subprocess, 'call')
    @mock.patch.object(subprocess, 'check_call')
    def test_destroy(self, mock_check_call: mock.MagicMock,
                     mock_call: mock.MagicMock, mock_print: mock.MagicMock,
                     mock_user_input: mock.MagicMock):
        """Destroy asks whether S3 objects should also be deleted."""
        self.manager.destroy()
        mock_user_input.assert_called_once()
        mock_print.assert_called_once()
        mock_check_call.assert_called_once()
        mock_call.assert_called_once()

    @mock.patch.object(manager_module.live_test, 'run', return_value=False)
    def test_live_test(self, mock_live_test: mock.MagicMock):
        """Live test wrapper raises TestFailureError if appropriate."""
        with self.assertRaises(TestFailureError):
            self.manager.live_test()
        mock_live_test.assert_called_once()

    @mock.patch.object(manager_module.boto3, 'resource')
    def test_purge_queue(self, mock_resource: mock.MagicMock):
        """Purge operation calls out to SQS"""
        self.manager.purge_queue()
        mock_resource.assert_has_calls([
            mock.call('sqs'),
            mock.call().get_queue_by_name(
                QueueName='test_prefix_binaryalert_analyzer_queue'),
            mock.call().get_queue_by_name().purge()
        ])

    def test_most_recent_manifest_found(self):
        """Finds the first summary key ending in manifest.json"""
        bucket = mock.MagicMock()
        files = [
            MockSummary(
                'inventory/test-bucket/EntireBucketDaily/2000-01-01/checksum.txt'
            ),
            MockSummary(
                'inventory/test-bucket/EntireBucketDaily/2000-01-01/manifest.json'
            ),
            MockSummary('inventory/end')
        ]
        bucket.objects.filter.return_value = files
        self.assertEqual(files[1].key,
                         self.manager._most_recent_manifest(bucket))

    def test_most_recent_manifest_not_found(self):
        """Returns None if no manifest files were found"""
        bucket = mock.MagicMock()
        bucket.objects.filter.return_value = [MockSummary('inventory/end')]
        self.assertIsNone(self.manager._most_recent_manifest(bucket))

    def test_s3_batch_iterator(self):
        """Multiple S3 objects are grouped together by batch iterator"""
        self.manager._config._config['objects_per_retro_message'] = 2
        sqs_messages = list(
            self.manager._s3_batch_iterator(str(i) for i in range(3)))
        expected = [
            {
                'Records': [  # Full batch
                    {
                        's3': {
                            'bucket': {
                                'name': mock.ANY
                            },
                            'object': {
                                'key': '0'
                            }
                        }
                    }, {
                        's3': {
                            'bucket': {
                                'name': mock.ANY
                            },
                            'object': {
                                'key': '1'
                            }
                        }
                    }
                ]
            },
            {
                'Records': [  # Final batch
                    {
                        's3': {
                            'bucket': {
                                'name': mock.ANY
                            },
                            'object': {
                                'key': '2'
                            }
                        }
                    },
                ]
            }
        ]
        self.assertEqual(expected, sqs_messages)

    def test_s3_msg_summary(self):
        """S3 message summaries include a record count and print the last key"""
        message = {
            'Records': [{
                's3': {
                    'bucket': {
                        'name': 'bucket-name'
                    },
                    'object': {
                        'key': 'ABC'
                    }
                }
            }, {
                's3': {
                    'bucket': {
                        'name': 'bucket-name'
                    },
                    'object': {
                        'key': 'DEF'
                    }
                }
            }]
        }
        count, summary = self.manager._s3_msg_summary(message)

        self.assertEqual(2, count)
        self.assertEqual('DEF', summary)

    @mock.patch.object(manager_module.boto3, 'resource')
    @mock.patch.object(manager_module.Manager,
                       '_most_recent_manifest',
                       return_value=None)
    @mock.patch.object(manager_module, 'print')
    def test_retro_fast_no_manifest(self, mock_print: mock.MagicMock,
                                    mock_manifest: mock.MagicMock,
                                    mock_resource: mock.MagicMock):
        """Retro fast - error message printed if no manifest exists when"""
        self.manager.retro_fast()
        mock_resource.assert_called_once()
        mock_manifest.assert_called_once()
        mock_print.assert_has_calls([mock.call(mock.ANY)] * 2)

    @mock.patch.object(manager_module.boto3, 'resource')
    @mock.patch.object(manager_module.Manager, '_enqueue')
    @mock.patch.object(manager_module.Manager,
                       '_most_recent_manifest',
                       return_value='inventory/manifest.json')
    @mock.patch.object(manager_module, 'print')
    def test_retro_fast(self, mock_print: mock.MagicMock,
                        mock_manifest: mock.MagicMock,
                        mock_enqueue: mock.MagicMock,
                        mock_resource: mock.MagicMock):
        """Retro fast - enqueue is called if manifest was found"""
        self.manager.retro_fast()
        mock_resource.assert_called_once()
        mock_manifest.assert_called_once()
        mock_enqueue.assert_called_once()
        mock_print.assert_called_once_with('Reading inventory/manifest.json')

    @mock.patch.object(manager_module.boto3, 'resource')
    @mock.patch.object(manager_module.Manager, '_enqueue')
    def test_retro_slow(self, mock_enqueue: mock.MagicMock,
                        mock_resource: mock.MagicMock):
        """Retro slow - enqueue is called"""
        self.manager.retro_slow()
        mock_resource.assert_called_once()
        mock_enqueue.assert_called_once()
Exemple #4
0
 def setUp(self):
     super().setUp()
     self.manager = Manager()
Exemple #5
0
import shelve
from cli.manager import Manager
from cli.person import Person

bob = Person('Bob Smith', 42, 30000, 'software')
sue = Person('Sue Jones', 45, 40000, 'hardware')
tom = Manager('Tom Doe', 50, 50000)

db = shelve.open('class_shelve')
db['bob'] = bob
db['sue'] = sue
db['tom'] = tom
db.close()