예제 #1
0
    def setUp(self):
        self.session = FakeSession({'config_file': 'myconfigfile'})
        self.subscribe = CloudTrailSubscribe(self.session)

        self.subscribe.iam = Mock()
        self.subscribe.iam.GetUser = Mock(
            return_value={'User': {'Arn': '::::123:456'}})

        self.subscribe.s3 = Mock()
        self.subscribe.s3.endpoint = Mock()
        self.subscribe.s3.endpoint.region_name = 'us-east-1'
        policy_template = io.StringIO(initial_value=u'{"Statement": []}')
        self.subscribe.s3.GetObject = Mock(
            return_value={'Body': policy_template})
        self.subscribe.s3.ListBuckets = Mock(
            return_value={'Buckets': [{'Name': 'test2'}]})

        self.subscribe.sns = Mock()
        self.subscribe.sns.endpoint = Mock()
        self.subscribe.sns.endpoint.region_name = 'us-east-1'
        self.subscribe.sns.ListTopics = Mock(
            return_value={'Topics': [{'TopicArn': ':test2'}]})
        self.subscribe.sns.CreateTopic = Mock(
            return_value={'TopicArn': 'foo'})
        self.subscribe.sns.GetTopicAttributes = Mock(
            return_value={'Attributes': {'Policy': '{"Statement": []}'}})
예제 #2
0
    def test_setup_services(self):
        parsed_args = []
        parsed_globals = argparse.Namespace()
        parsed_globals.region = 'us-east-1'
        parsed_globals.verify_ssl = 'foo'
        parsed_globals.endpoint_url = 'https://cloudtrail.aws.com'

        ref_args = {
            'region_name': parsed_globals.region,
            'verify': parsed_globals.verify_ssl,
            'endpoint_url': None
        }

        # Reset some of the mocks because we need some introspection on the
        # session.
        fake_service = Mock()
        self.session = Mock()
        self.session.get_service.return_value = fake_service
        self.subscribe = CloudTrailSubscribe(self.session)

        self.subscribe.setup_services(parsed_args, parsed_globals)

        get_service_call_args = self.session.get_service.call_args_list
        endpoint_call_args = fake_service.get_endpoint.call_args_list

        # Ensure all of the services got called.
        self.assertEqual('iam', get_service_call_args[0][0][0])
        self.assertEqual('s3', get_service_call_args[1][0][0])
        self.assertEqual('sns', get_service_call_args[2][0][0])
        self.assertEqual('cloudtrail', get_service_call_args[3][0][0])

        # Make sure the endpoints were called correctly
        # The order is iam, s3, sns, cloudtrail based on ``get_service`` calls
        # from above.
        self.assertEqual(endpoint_call_args[0][1], ref_args)
        self.assertEqual(endpoint_call_args[1][1], ref_args)
        self.assertEqual(endpoint_call_args[2][1], ref_args)
        # CloudTrail should be using the endpoint.
        ref_args['endpoint_url'] = parsed_globals.endpoint_url
        self.assertEqual(endpoint_call_args[3][1], ref_args)
예제 #3
0
class TestCloudTrail(unittest.TestCase):
    def setUp(self):
        self.session = FakeSession({'config_file': 'myconfigfile'})
        self.subscribe = CloudTrailSubscribe(self.session)

        self.subscribe.iam = Mock()
        self.subscribe.iam.GetUser = Mock(
            return_value={'User': {'Arn': '::::123:456'}})

        self.subscribe.s3 = Mock()
        self.subscribe.s3.endpoint = Mock()
        self.subscribe.s3.endpoint.region_name = 'us-east-1'
        policy_template = io.StringIO(initial_value=u'{"Statement": []}')
        self.subscribe.s3.GetObject = Mock(
            return_value={'Body': policy_template})
        self.subscribe.s3.ListBuckets = Mock(
            return_value={'Buckets': [{'Name': 'test2'}]})

        self.subscribe.sns = Mock()
        self.subscribe.sns.endpoint = Mock()
        self.subscribe.sns.endpoint.region_name = 'us-east-1'
        self.subscribe.sns.ListTopics = Mock(
            return_value={'Topics': [{'TopicArn': ':test2'}]})
        self.subscribe.sns.CreateTopic = Mock(
            return_value={'TopicArn': 'foo'})
        self.subscribe.sns.GetTopicAttributes = Mock(
            return_value={'Attributes': {'Policy': '{"Statement": []}'}})

    def test_s3_create(self):
        iam = self.subscribe.iam
        s3 = self.subscribe.s3

        self.subscribe.setup_new_bucket('test', 'logs')

        iam.GetUser.assert_called()

        s3.GetObject.assert_called()
        s3.ListBuckets.assert_called()
        s3.CreateBucket.assert_called()
        s3.PutBucketPolicy.assert_called()

        s3.DeleteBucket.assert_not_called()

    def test_s3_create_already_exists(self):
        with self.assertRaises(Exception):
            self.subscribe.setup_new_bucket('test2', 'logs')

    def test_s3_create_set_policy_fail(self):
        s3 = self.subscribe.s3
        orig = s3.PutBucketPolicy
        s3.PutBucketPolicy = Mock(side_effect=Exception('Error!'))

        with self.assertRaises(Exception):
            self.subscribe.setup_new_bucket('test', 'logs')

        s3.CreateBucket.assert_called()
        s3.PutBucketPolicy.assert_called()
        s3.DeleteBucket.assert_called()

        s3.PutBucketPolicy = orig

    def test_get_policy_fail(self):
        orig = self.subscribe.s3.GetObject
        self.subscribe.s3.GetObject = Mock(side_effect=Exception('Error!'))

        with self.assertRaises(Exception):
            self.subscribe.setup_new_bucket('test', 'logs')

        self.subscribe.s3.GetObject = orig

    def test_sns_create(self):
        s3 = self.subscribe.s3
        sns = self.subscribe.sns

        self.subscribe.setup_new_topic('test')

        s3.GetObject.assert_called()
        sns.ListTopics.assert_called()
        sns.CreateTopic.assert_called()
        sns.SetTopicAttributes.assert_called()

        sns.DeleteTopic.assert_not_called()

    def test_sns_create_already_exists(self):
        with self.assertRaises(Exception):
            self.subscribe.setup_new_topic('test2')

    def test_cloudtrail_new_call_format(self):
        self.subscribe.cloudtrail = Mock()
        self.subscribe.cloudtrail.CreateTrail = Mock(return_value={})
        self.subscribe.cloudtrail.DescribeTrail = Mock(return_value={})

        self.subscribe.upsert_cloudtrail_config('test', 'bucket', 'prefix',
                                                'topic', True)

        self.subscribe.cloudtrail.CreateTrail.assert_called_with(
            name='test',
            s3_bucket_name='bucket',
            s3_key_prefix='prefix',
            sns_topic_name='topic',
            include_global_service_events=True
        )

    def test_sns_policy_merge(self):
        left = '''
{
   "Version":"2008-10-17",
   "Id":"us-east-1/698519295917/test__default_policy_ID",
   "Statement":[
      {
         "Effect":"Allow",
         "Sid":"us-east-1/698519295917/test__default_statement_ID",
         "Principal":{
            "AWS":"*"
         },
         "Action":[
            "SNS:GetTopicAttributes",
            "SNS:SetTopicAttributes",
            "SNS:AddPermission",
            "SNS:RemovePermission",
            "SNS:DeleteTopic",
            "SNS:Subscribe",
            "SNS:ListSubscriptionsByTopic",
            "SNS:Publish",
            "SNS:Receive"
         ],
         "Resource":"arn:aws:sns:us-east-1:698519295917:test",
         "Condition":{
            "StringLike":{
               "AWS:SourceArn":"arn:aws:*:*:698519295917:*"
            }
         }
      }
   ]
}'''
        right = '''
{
   "Version":"2008-10-17",
   "Id":"us-east-1/698519295917/test_foo",
   "Statement":[
      {
         "Effect":"Allow",
         "Sid":"us-east-1/698519295917/test_foo_ID",
         "Principal":{
            "AWS":"*"
         },
         "Action":[
            "SNS:GetTopicAttributes",
            "SNS:SetTopicAttributes",
            "SNS:AddPermission",
            "SNS:RemovePermission",
            "SNS:DeleteTopic",
            "SNS:Subscribe",
            "SNS:ListSubscriptionsByTopic",
            "SNS:Publish",
            "SNS:Receive"
         ],
         "Resource":"arn:aws:sns:us-east-1:698519295917:test",
         "Condition":{
            "StringLike":{
               "AWS:SourceArn":"arn:aws:*:*:698519295917:*"
            }
         }
      }
   ]
}'''
        expected = '''
{
   "Version":"2008-10-17",
   "Id":"us-east-1/698519295917/test__default_policy_ID",
   "Statement":[
      {
         "Effect":"Allow",
         "Sid":"us-east-1/698519295917/test__default_statement_ID",
         "Principal":{
            "AWS":"*"
         },
         "Action":[
            "SNS:GetTopicAttributes",
            "SNS:SetTopicAttributes",
            "SNS:AddPermission",
            "SNS:RemovePermission",
            "SNS:DeleteTopic",
            "SNS:Subscribe",
            "SNS:ListSubscriptionsByTopic",
            "SNS:Publish",
            "SNS:Receive"
         ],
         "Resource":"arn:aws:sns:us-east-1:698519295917:test",
         "Condition":{
            "StringLike":{
               "AWS:SourceArn":"arn:aws:*:*:698519295917:*"
            }
         }
      },
      {
         "Effect":"Allow",
         "Sid":"us-east-1/698519295917/test_foo_ID",
         "Principal":{
            "AWS":"*"
         },
         "Action":[
            "SNS:GetTopicAttributes",
            "SNS:SetTopicAttributes",
            "SNS:AddPermission",
            "SNS:RemovePermission",
            "SNS:DeleteTopic",
            "SNS:Subscribe",
            "SNS:ListSubscriptionsByTopic",
            "SNS:Publish",
            "SNS:Receive"
         ],
         "Resource":"arn:aws:sns:us-east-1:698519295917:test",
         "Condition":{
            "StringLike":{
               "AWS:SourceArn":"arn:aws:*:*:698519295917:*"
            }
         }
      }
   ]
}'''

        merged = self.subscribe.merge_sns_policy(left, right)

        self.assertEqual(json.loads(expected), json.loads(merged))
예제 #4
0
class TestCloudTrail(unittest.TestCase):
    def setUp(self):
        self.session = FakeSession({'config_file': 'myconfigfile'})
        self.subscribe = CloudTrailSubscribe(self.session)

        self.subscribe.iam = Mock()
        self.subscribe.iam.GetUser = Mock(
            return_value={'User': {
                'Arn': '::::123:456'
            }})

        self.subscribe.s3 = Mock()
        self.subscribe.s3.endpoint = Mock()
        self.subscribe.s3.endpoint.region_name = 'us-east-1'
        policy_template = six.BytesIO(six.b(u'{"Statement": []}'))
        self.subscribe.s3.GetObject = Mock(
            return_value={'Body': policy_template})
        self.subscribe.s3.ListBuckets = Mock(
            return_value={'Buckets': [{
                'Name': 'test2'
            }]})

        self.subscribe.sns = Mock()
        self.subscribe.sns.endpoint = Mock()
        self.subscribe.sns.endpoint.region_name = 'us-east-1'
        self.subscribe.sns.ListTopics = Mock(
            return_value={'Topics': [{
                'TopicArn': ':test2'
            }]})
        self.subscribe.sns.CreateTopic = Mock(return_value={'TopicArn': 'foo'})
        self.subscribe.sns.GetTopicAttributes = Mock(
            return_value={'Attributes': {
                'Policy': '{"Statement": []}'
            }})

    def test_setup_services(self):
        parsed_args = []
        parsed_globals = argparse.Namespace()
        parsed_globals.region = 'us-east-1'
        parsed_globals.verify_ssl = 'foo'
        parsed_globals.endpoint_url = 'https://cloudtrail.aws.com'

        ref_args = {
            'region_name': parsed_globals.region,
            'verify': parsed_globals.verify_ssl,
            'endpoint_url': None
        }

        # Reset some of the mocks because we need some introspection on the
        # session.
        fake_service = Mock()
        self.session = Mock()
        self.session.get_service.return_value = fake_service
        self.subscribe = CloudTrailSubscribe(self.session)

        self.subscribe.setup_services(parsed_args, parsed_globals)

        get_service_call_args = self.session.get_service.call_args_list
        endpoint_call_args = fake_service.get_endpoint.call_args_list

        # Ensure all of the services got called.
        self.assertEqual('iam', get_service_call_args[0][0][0])
        self.assertEqual('s3', get_service_call_args[1][0][0])
        self.assertEqual('sns', get_service_call_args[2][0][0])
        self.assertEqual('cloudtrail', get_service_call_args[3][0][0])

        # Make sure the endpoints were called correctly
        # The order is iam, s3, sns, cloudtrail based on ``get_service`` calls
        # from above.
        self.assertEqual(endpoint_call_args[0][1], ref_args)
        self.assertEqual(endpoint_call_args[1][1], ref_args)
        self.assertEqual(endpoint_call_args[2][1], ref_args)
        # CloudTrail should be using the endpoint.
        ref_args['endpoint_url'] = parsed_globals.endpoint_url
        self.assertEqual(endpoint_call_args[3][1], ref_args)

    def test_s3_create(self):
        iam = self.subscribe.iam
        s3 = self.subscribe.s3

        self.subscribe.setup_new_bucket('test', 'logs')

        iam.GetUser.assert_called()

        s3.GetObject.assert_called()
        s3.ListBuckets.assert_called()
        s3.CreateBucket.assert_called()
        s3.PutBucketPolicy.assert_called()

        s3.DeleteBucket.assert_not_called()

        args, kwargs = s3.CreateBucket.call_args
        self.assertNotIn('create_bucket_configuration', kwargs)

    def test_s3_create_non_us_east_1(self):
        # Because this is outside of us-east-1, it should create
        # a bucket configuration with a location constraint.
        s3 = self.subscribe.s3
        s3.endpoint.region_name = 'us-west-2'

        self.subscribe.setup_new_bucket('test', 'logs')

        args, kwargs = s3.CreateBucket.call_args
        self.assertIn('create_bucket_configuration', kwargs)

        bucket_config = kwargs['create_bucket_configuration']
        self.assertEqual(bucket_config['LocationConstraint'], 'us-west-2')

    def test_s3_create_already_exists(self):
        with self.assertRaises(Exception):
            self.subscribe.setup_new_bucket('test2', 'logs')

    def test_s3_create_set_policy_fail(self):
        s3 = self.subscribe.s3
        orig = s3.PutBucketPolicy
        s3.PutBucketPolicy = Mock(side_effect=Exception('Error!'))

        with self.assertRaises(Exception):
            self.subscribe.setup_new_bucket('test', 'logs')

        s3.CreateBucket.assert_called()
        s3.PutBucketPolicy.assert_called()
        s3.DeleteBucket.assert_called()

        s3.PutBucketPolicy = orig

    def test_get_policy_fail(self):
        orig = self.subscribe.s3.GetObject
        self.subscribe.s3.GetObject = Mock(side_effect=Exception('Error!'))

        with self.assertRaises(Exception):
            self.subscribe.setup_new_bucket('test', 'logs')

        self.subscribe.s3.GetObject = orig

    def test_sns_create(self):
        s3 = self.subscribe.s3
        sns = self.subscribe.sns

        self.subscribe.setup_new_topic('test')

        s3.GetObject.assert_called()
        sns.ListTopics.assert_called()
        sns.CreateTopic.assert_called()
        sns.SetTopicAttributes.assert_called()

        sns.DeleteTopic.assert_not_called()

    def test_sns_create_already_exists(self):
        with self.assertRaises(Exception):
            self.subscribe.setup_new_topic('test2')

    def test_cloudtrail_new_call_format(self):
        self.subscribe.cloudtrail = Mock()
        self.subscribe.cloudtrail.CreateTrail = Mock(return_value={})
        self.subscribe.cloudtrail.DescribeTrail = Mock(return_value={})

        self.subscribe.upsert_cloudtrail_config('test', 'bucket', 'prefix',
                                                'topic', True)

        self.subscribe.cloudtrail.CreateTrail.assert_called_with(
            name='test',
            s3_bucket_name='bucket',
            s3_key_prefix='prefix',
            sns_topic_name='topic',
            include_global_service_events=True)

    def test_sns_policy_merge(self):
        left = '''
{
   "Version":"2008-10-17",
   "Id":"us-east-1/698519295917/test__default_policy_ID",
   "Statement":[
      {
         "Effect":"Allow",
         "Sid":"us-east-1/698519295917/test__default_statement_ID",
         "Principal":{
            "AWS":"*"
         },
         "Action":[
            "SNS:GetTopicAttributes",
            "SNS:SetTopicAttributes",
            "SNS:AddPermission",
            "SNS:RemovePermission",
            "SNS:DeleteTopic",
            "SNS:Subscribe",
            "SNS:ListSubscriptionsByTopic",
            "SNS:Publish",
            "SNS:Receive"
         ],
         "Resource":"arn:aws:sns:us-east-1:698519295917:test",
         "Condition":{
            "StringLike":{
               "AWS:SourceArn":"arn:aws:*:*:698519295917:*"
            }
         }
      }
   ]
}'''
        right = '''
{
   "Version":"2008-10-17",
   "Id":"us-east-1/698519295917/test_foo",
   "Statement":[
      {
         "Effect":"Allow",
         "Sid":"us-east-1/698519295917/test_foo_ID",
         "Principal":{
            "AWS":"*"
         },
         "Action":[
            "SNS:GetTopicAttributes",
            "SNS:SetTopicAttributes",
            "SNS:AddPermission",
            "SNS:RemovePermission",
            "SNS:DeleteTopic",
            "SNS:Subscribe",
            "SNS:ListSubscriptionsByTopic",
            "SNS:Publish",
            "SNS:Receive"
         ],
         "Resource":"arn:aws:sns:us-east-1:698519295917:test",
         "Condition":{
            "StringLike":{
               "AWS:SourceArn":"arn:aws:*:*:698519295917:*"
            }
         }
      }
   ]
}'''
        expected = '''
{
   "Version":"2008-10-17",
   "Id":"us-east-1/698519295917/test__default_policy_ID",
   "Statement":[
      {
         "Effect":"Allow",
         "Sid":"us-east-1/698519295917/test__default_statement_ID",
         "Principal":{
            "AWS":"*"
         },
         "Action":[
            "SNS:GetTopicAttributes",
            "SNS:SetTopicAttributes",
            "SNS:AddPermission",
            "SNS:RemovePermission",
            "SNS:DeleteTopic",
            "SNS:Subscribe",
            "SNS:ListSubscriptionsByTopic",
            "SNS:Publish",
            "SNS:Receive"
         ],
         "Resource":"arn:aws:sns:us-east-1:698519295917:test",
         "Condition":{
            "StringLike":{
               "AWS:SourceArn":"arn:aws:*:*:698519295917:*"
            }
         }
      },
      {
         "Effect":"Allow",
         "Sid":"us-east-1/698519295917/test_foo_ID",
         "Principal":{
            "AWS":"*"
         },
         "Action":[
            "SNS:GetTopicAttributes",
            "SNS:SetTopicAttributes",
            "SNS:AddPermission",
            "SNS:RemovePermission",
            "SNS:DeleteTopic",
            "SNS:Subscribe",
            "SNS:ListSubscriptionsByTopic",
            "SNS:Publish",
            "SNS:Receive"
         ],
         "Resource":"arn:aws:sns:us-east-1:698519295917:test",
         "Condition":{
            "StringLike":{
               "AWS:SourceArn":"arn:aws:*:*:698519295917:*"
            }
         }
      }
   ]
}'''

        merged = self.subscribe.merge_sns_policy(left, right)

        self.assertEqual(json.loads(expected), json.loads(merged))