def test_2_evaluatechange_sgnotassociated_noncompliant(self): CONFIG_CLIENT_MOCK.select_resource_config.return_value = { 'Results': ['{"COUNT(*)": 0}'] } config_item = { "configuration": { "groupName": "security-group-1" }, "relationships": [{ "resourceId": "vpc-01234567", "resourceType": "AWS::EC2::VPC" }], "resourceType": "AWS::EC2::SecurityGroup", "configurationItemCaptureTime": "2019-04-28T07:49:40.797Z", "resourceId": "sg-0123456789abcdefg" } response = RULE.evaluate_change({}, CLIENT_FACTORY, config_item, {}) resp_expected = [ Evaluation( ComplianceType.NON_COMPLIANT, annotation= 'This Amazon EC2 security group is not associated with an EC2 instance or an ENI.' ) ] rdklibtest.assert_successful_evaluation(self, response, resp_expected)
def test_scenario2_allAlbListenersAreSsl_returnsCompliant(self): mock_albs_in_config(['arn1']) ELBV2_CLIENT_MOCK.describe_listeners = MagicMock( return_value={'Listeners': [{'ListenerArn': 'arn1', 'SslPolicy': 'Some_policy_1'}, {'ListenerArn': 'arn2', 'SslPolicy': 'Some_policy_2'}]} ) response = RULE.evaluate_periodic(self.event, CLIENT_FACTORY, {}) rdklibtest.assert_successful_evaluation(self, response, [Evaluation(ComplianceType.COMPLIANT, 'arn1', ELB_RESOURCE_TYPE)], 1)
def test_scenario1_evaluatechange_ec2_instance_no_ebs_volumes_attached_returnsnotapplicable( self): response = RULE.evaluate_change( {}, CLIENT_FACTORY, self.ci_ec2_instance_no_ebs_volumes_attached, {}) response_expected = [Evaluation(ComplianceType.NOT_APPLICABLE)] assert_successful_evaluation(self, response, response_expected)
def test_scenario3_oneormoreiamrolesunused_returnsnoncompliant(self): rule_parameters = {"DaysBeforeUnused": "80"} rule_parameters = RULE.evaluate_parameters(rule_parameters) input_event = rdklibtest.create_test_scheduled_event( rule_parameters_json=rule_parameters) CONFIG_CLIENT.select_resource_config.return_value = { "Results": ['{"resourceName":"AWS-CodePipeline-Service"}'] } IAM_CLIENT_MOCK.get_role.return_value = { "Role": { "RoleLastUsed": { "LastUsedDate": datetime.now(timezone.utc) - timedelta(days=100) } } } response = RULE.evaluate_periodic(input_event, CLIENT_FACTORY, rule_parameters) resp_expected = [ Evaluation( ComplianceType.NON_COMPLIANT, 'AWS-CodePipeline-Service', RESOURCE_TYPE, annotation= 'This AWS IAM Role has not been used within the last 80 day(s)' ) ] rdklibtest.assert_successful_evaluation(self, response, resp_expected)
def test_scenario4_describeRulesPagination_returnsCompliant(self): self.mock_albs_in_config(['arn1']) ELBV2_CLIENT_MOCK.describe_listeners = MagicMock( return_value={ 'Listeners': [{ 'ListenerArn': 'listenerArn1', 'DefaultActions': [{ 'RedirectConfig': { 'Protocol': 'HTTPS' }, 'Type': 'redirect' }] }] }) ELBV2_CLIENT_MOCK.describe_rules = MagicMock(side_effect=[{ 'Rules': [ { 'RuleArn': 'ruleArn1', 'Actions': [{ 'RedirectConfig': { 'Protocol': 'HTTPS' }, 'Type': 'redirect' }] }, ], 'NextMarker': 'ghi' }, { 'Rules': [ { 'RuleArn': 'ruleArn2', 'Actions': [{ 'RedirectConfig': { 'Protocol': 'HTTPS' }, 'Type': 'redirect' }] }, ] }]) response = RULE.evaluate_periodic(self.event, CLIENT_FACTORY, {}) resp_expected = [ Evaluation(ComplianceType.COMPLIANT, 'arn1', ELB_RESOURCE_TYPE) ] rdklibtest.assert_successful_evaluation(self, response, resp_expected, 1) self.assertEqual(ELBV2_CLIENT_MOCK.mock_calls, [ call.describe_listeners(LoadBalancerArn='arn1', PageSize=400), call.describe_rules(ListenerArn='listenerArn1', PageSize=400), call.describe_rules( ListenerArn='listenerArn1', PageSize=400, Marker='ghi') ])
def test_evaluate_periodic_1_compliant(self): SECURITYHUB_CLIENT_MOCK.describe_hub.return_value = MOCK_SECURITYHUB_ENABLED response = RULE.evaluate_periodic(MOCK_EVENT, CLIENT_FACTORY, {}) resp_expected = [ Evaluation(ComplianceType.COMPLIANT, '632747342146', RESOURCE_TYPE) ] rdklibtest.assert_successful_evaluation(self, response, resp_expected, 1)
def test_scenario6_evaluatechange_ebs_volume_attached_missing_tags_from_ec2_instance_returnsnoncompliant( self): EC2_CLIENT_MOCK.get_paginator.return_value = EC2_PAGINATOR_MOCK EC2_PAGINATOR_MOCK.paginate.return_value = self.ec2_instance_tags2 response = RULE.evaluate_change({}, CLIENT_FACTORY, self.ci_ebs_volume_attached_with_tags1, {}) response_expected = [Evaluation(ComplianceType.NON_COMPLIANT)] assert_successful_evaluation(self, response, response_expected)
def test_evaluate_periodic_2_non_compliant(self): SECURITYHUB_CLIENT_MOCK.describe_hub.side_effect = my_side_effect response = RULE.evaluate_periodic(MOCK_EVENT, CLIENT_FACTORY, {}) resp_expected = [ Evaluation(ComplianceType.NON_COMPLIANT, '632747342146', RESOURCE_TYPE, 'AWS SecurityHub is not enabled.') ] rdklibtest.assert_successful_evaluation(self, response, resp_expected, 1)
def test_scenario3_evaluatechange_specifiedenginenotpresent_returnsnotapplicable( self): response = RULE.evaluate_change(None, CLIENT_FACTORY, self.engine_not_applicable, None) resp_expected = [ Evaluation(ComplianceType.NOT_APPLICABLE, annotation="Engine is not defined") ] rdklibtest.assert_successful_evaluation(self, response, resp_expected)
def test_scenario6_evaluatechange_ebs_volume_attached_missing_tags_from_ec2_instance_returnsnoncompliant( self): CONFIG_CLIENT_MOCK.select_resource_config = MagicMock( return_value=self.ec2_instance_results_tags2) response = RULE.evaluate_change({}, CLIENT_FACTORY, self.ci_ebs_volume_attached_with_tags1, {}) response_expected = [Evaluation(ComplianceType.NON_COMPLIANT)] assert_successful_evaluation(self, response, response_expected)
def test_scenario2_evaluatechange_onetypeoflogisenabledonrds_returnsnoncompliant( self): response = RULE.evaluate_change(None, CLIENT_FACTORY, self.one_log_enabled_non_compliant, None) resp_expected = [ Evaluation(ComplianceType.NON_COMPLIANT, annotation="One or more logs are not enabled") ] rdklibtest.assert_successful_evaluation(self, response, resp_expected)
def test_scenario3b_evaluatechange_ec2_instance_volumes_has_tags_from_ec2_instance_with_token_returnscompliant( self): CONFIG_CLIENT_MOCK.select_resource_config = MagicMock( return_value=self.ebs_volume_results_tags2_with_token) response = RULE.evaluate_change({}, CLIENT_FACTORY, self.ci_ec2_instance_with_tags2, {}) response_expected = [ Evaluation(ComplianceType.COMPLIANT, "vol-123abc", RESOURCE_TYPE) ] assert_successful_evaluation(self, response, response_expected)
def test_scenario3_evaluatechange_ec2_instance_volumes_has_tags_from_ec2_instance_returnscompliant( self): EC2_CLIENT_MOCK.get_paginator.return_value = EC2_PAGINATOR_MOCK EC2_PAGINATOR_MOCK.paginate.return_value = self.ebs_volume_tags2 response = RULE.evaluate_change({}, CLIENT_FACTORY, self.ci_ec2_instance_with_tags2, {}) response_expected = [ Evaluation(ComplianceType.COMPLIANT, "vol-123abc", RESOURCE_TYPE) ] assert_successful_evaluation(self, response, response_expected)
def test_evaluate_noncompliant_instance_deprecated_ami(self): EC2_CLIENT_MOCK.describe_instances.return_value = self.instance_response EC2_CLIENT_MOCK.describe_images.return_value = self.deprecated_ami_response response = RULE.evaluate_periodic({}, CLIENT_FACTORY, {'mode': 'EC2'}) instance = self.instance_response['Reservations'][0]['Instances'][0] response_expected = [ Evaluation(complianceType=ComplianceType.NON_COMPLIANT, resourceId=instance['InstanceId'], resourceType='AWS::EC2::Instance', annotation=f'Image {instance["ImageId"]} is deprecated') ] assert_successful_evaluation(self, response, response_expected)
def test_1_evaluatechange_sgisdefault_notapplicable(self): config_item = { "configuration": { "groupName": "default" }, "resourceType": "AWS::EC2::SecurityGroup", "configurationItemCaptureTime": "2019-04-28T07:49:40.797Z", "resourceId": "sg-0123456789abcdefg" } response = RULE.evaluate_change({}, {}, config_item, {}) resp_expected = [Evaluation(ComplianceType.NOT_APPLICABLE)] rdklibtest.assert_successful_evaluation(self, response, resp_expected)
def test_scenario1_noAlbsInAccount_returnsNotApplicable(self): CONFIG_CLIENT_MOCK.list_discovered_resources = MagicMock(return_value={ 'resourceIdentifiers': [{'resourceType': ELB_RESOURCE_TYPE, 'resourceId': 'arn1', 'resourceName': 'load-balancer'}] }) CONFIG_CLIENT_MOCK.batch_get_resource_config = MagicMock(return_value={ 'baseConfigurationItems': [{ 'resourceType': ELB_RESOURCE_TYPE, 'resourceId': 'arn1', 'resourceName': 'load-balancer', 'configuration': '{"type": "network"}' }] }) response = RULE.evaluate_periodic(self.event, CLIENT_FACTORY, {}) rdklibtest.assert_successful_evaluation(self, response, [], 0)
def test_evaluate_noncompliant_asg_launch_config_deprecated_ami(self): ASG_CLIENT_MOCK.describe_auto_scaling_groups.return_value = self.asg_launch_config ASG_CLIENT_MOCK.describe_launch_configurations.return_value = self.launch_config EC2_CLIENT_MOCK.describe_images.return_value = self.deprecated_ami_response response = RULE.evaluate_periodic({}, CLIENT_FACTORY, {'mode': 'ASG'}) asg = self.asg_launch_config['AutoScalingGroups'][0] launch_config = self.launch_config['LaunchConfigurations'][0] response_expected = [ Evaluation( complianceType=ComplianceType.NON_COMPLIANT, resourceId=asg['AutoScalingGroupName'], resourceType='AWS::AutoScaling::AutoScalingGroup', annotation=f'Image {launch_config["ImageId"]} is deprecated') ] assert_successful_evaluation(self, response, response_expected)
def test_scenario4_allHttpListenersForAlbHaveSslRedirectionEnabled_returnsCompliant(self): mock_albs_in_config(['arn1', 'arn2']) ELBV2_CLIENT_MOCK.describe_listeners = MagicMock( return_value={'Listeners': [ {'ListenerArn': 'arn1', 'DefaultActions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'redirect'}]}, {'ListenerArn': 'arn2', 'DefaultActions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'redirect'}]}, ]} ) ELBV2_CLIENT_MOCK.describe_rules = MagicMock( return_value={'Rules': [ {'RuleArn': 'arn1', 'Actions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'redirect'}]}, {'RuleArn': 'arn2', 'Actions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'redirect'}]}, ]} ) response = RULE.evaluate_periodic(self.event, CLIENT_FACTORY, {}) resp_expected = [Evaluation(ComplianceType.COMPLIANT, 'arn1', ELB_RESOURCE_TYPE), Evaluation(ComplianceType.COMPLIANT, 'arn2', ELB_RESOURCE_TYPE)] rdklibtest.assert_successful_evaluation(self, response, resp_expected, 2)
def test_evaluate_noncompliant_asg_launch_template_missing_ami(self): ASG_CLIENT_MOCK.describe_auto_scaling_groups.return_value = self.asg_launch_template ASG_CLIENT_MOCK.describe_launch_template_versions.return_value = self.launch_template_versions EC2_CLIENT_MOCK.describe_images.return_value = self.missing_ami_response response = RULE.evaluate_periodic({}, CLIENT_FACTORY, {'mode': 'ASG'}) asg = self.asg_launch_template['AutoScalingGroups'][0] launch_template_version = self.launch_template_versions[ 'LaunchTemplateVersions'][0] response_expected = [ Evaluation( complianceType=ComplianceType.NON_COMPLIANT, resourceId=asg['AutoScalingGroupName'], resourceType='AWS::AutoScaling::AutoScalingGroup', annotation= f'Error checking {launch_template_version["LaunchTemplateData"]["ImageId"]}, assuming noncompliant' ) ] assert_successful_evaluation(self, response, response_expected)
def test_evaluate_asg_mixed_instances_launch_template_compliant(self): ASG_CLIENT_MOCK.describe_auto_scaling_groups.return_value = self.asg_mixed_instances EC2_CLIENT_MOCK.describe_launch_template_versions.return_value = self.launch_template_versions EC2_CLIENT_MOCK.describe_images.return_value = self.compliant_ami_response response = RULE.evaluate_periodic({}, CLIENT_FACTORY, {'mode': 'ASG'}) asg = self.asg_mixed_instances['AutoScalingGroups'][0] launch_template_version = self.launch_template_versions[ 'LaunchTemplateVersions'][0] response_expected = [ Evaluation( complianceType=ComplianceType.COMPLIANT, resourceId=asg['AutoScalingGroupName'], resourceType='AWS::AutoScaling::AutoScalingGroup', annotation= f'Image {launch_template_version["LaunchTemplateData"]["ImageId"]} is not deprecated' ) ] assert_successful_evaluation(self, response, response_expected)
def test_scenario3_AlbHasHttpListenerWithNoSSLRedirect_returnsNonCompliant(self): mock_albs_in_config(['arn1', 'arn2']) ELBV2_CLIENT_MOCK.describe_listeners = MagicMock( return_value={'Listeners': [ {'ListenerArn': 'arn1', 'DefaultActions': [{'RedirectConfig': {'Protocol': 'HTTP'}, 'Type': 'other'}]}, {'ListenerArn': 'arn2', 'DefaultActions': [{'RedirectConfig': {'Protocol': 'HTTP'}, 'Type': 'other'}]}, ]} ) ELBV2_CLIENT_MOCK.describe_rules = MagicMock( return_value={'Rules': [ {'RuleArn': 'arn1', 'Actions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'other'}]}, {'RuleArn': 'arn2', 'Actions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'other'}]}, ]} ) response = RULE.evaluate_periodic(self.event, CLIENT_FACTORY, {}) resp_expected = [] resp_expected.append(Evaluation(ComplianceType.NON_COMPLIANT, 'arn1', ELB_RESOURCE_TYPE, "HTTP listener rule must have HTTP to HTTPS redirection action configured")) resp_expected.append(Evaluation(ComplianceType.NON_COMPLIANT, 'arn2', ELB_RESOURCE_TYPE, "HTTP listener rule must have HTTP to HTTPS redirection action configured")) rdklibtest.assert_successful_evaluation(self, response, resp_expected, 2)
def test_4_evaluatechange_sgassociated_compliant(self): config_item = { "configuration": { "groupName": "security-group-2" }, "relationships": [{ "resourceId": "vpc-01234567", "resourceType": "AWS::EC2::VPC" }, { "resourceId": "eni-123456abcdefghi18", "resourceType": "AWS::EC2::NetworkInterface" }], "resourceType": "AWS::EC2::SecurityGroup", "configurationItemCaptureTime": "2019-04-28T07:49:40.797Z", "resourceId": "sg-0123456789abcdefg" } response = RULE.evaluate_change({}, {}, config_item, {}) resp_expected = [Evaluation(ComplianceType.COMPLIANT)] rdklibtest.assert_successful_evaluation(self, response, resp_expected)
def test_scenario2_noiamroleisunusedwithindaysbeforeunusedrulesparameter_returnscompliant( self): rule_parameters = {"DaysBeforeUnused": "90"} rule_parameters = RULE.evaluate_parameters(rule_parameters) input_event = rdklibtest.create_test_scheduled_event( rule_parameters_json=rule_parameters) CONFIG_CLIENT.select_resource_config.return_value = { "Results": ['{"resourceName":"config-rule"}'] } IAM_CLIENT_MOCK.get_role.return_value = { "Role": { "RoleLastUsed": { "LastUsedDate": datetime.now(timezone.utc) } } } response = RULE.evaluate_periodic(input_event, CLIENT_FACTORY, rule_parameters) resp_expected = [ Evaluation(ComplianceType.COMPLIANT, 'config-rule', RESOURCE_TYPE) ] rdklibtest.assert_successful_evaluation(self, response, resp_expected)
def test_scenario4_configServiceCallPagination_returnsCompliant(self): CONFIG_CLIENT_MOCK.list_discovered_resources = MagicMock(side_effect=[ { 'resourceIdentifiers': [ { 'resourceType': ELB_RESOURCE_TYPE, 'resourceId': 'arn1', 'resourceName': 'load-balancer-arn1' }, { 'resourceType': ELB_RESOURCE_TYPE, 'resourceId': 'arn2', 'resourceName': 'load-balancer-arn2' } ], 'nextToken': 'abc' }, { 'resourceIdentifiers': [ { 'resourceType': ELB_RESOURCE_TYPE, 'resourceId': 'arn3', 'resourceName': 'load-balancer-arn3' } ] } ]) CONFIG_CLIENT_MOCK.batch_get_resource_config = MagicMock(side_effect=[ { 'baseConfigurationItems': [ { 'resourceType': ELB_RESOURCE_TYPE, 'resourceId': 'arn1', 'resourceName': 'load-balancer-arn1', 'configuration': '{"type": "application"}' }, ], 'unprocessedResourceKeys': [{ 'resourceType': ELB_RESOURCE_TYPE, 'resourceId': 'arn2' }] }, { 'baseConfigurationItems': [ { 'resourceType': ELB_RESOURCE_TYPE, 'resourceId': 'arn2', 'resourceName': 'load-balancer-arn2', 'configuration': '{"type": "application"}' }, ] }, { 'baseConfigurationItems': [ { 'resourceType': ELB_RESOURCE_TYPE, 'resourceId': 'arn3', 'resourceName': 'load-balancer-arn3', 'configuration': '{"type": "application"}' }, ] } ]) ELBV2_CLIENT_MOCK.describe_listeners = MagicMock( return_value={'Listeners': [ {'ListenerArn': 'arn1', 'DefaultActions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'redirect'}]}, {'ListenerArn': 'arn2', 'DefaultActions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'redirect'}]}, ]} ) ELBV2_CLIENT_MOCK.describe_rules = MagicMock( return_value={'Rules': [ {'RuleArn': 'arn1', 'Actions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'redirect'}]}, {'RuleArn': 'arn2', 'Actions': [{'RedirectConfig': {'Protocol': 'HTTPS'}, 'Type': 'redirect'}]}, ]} ) response = RULE.evaluate_periodic(self.event, CLIENT_FACTORY, {}) resp_expected = [ Evaluation(ComplianceType.COMPLIANT, 'arn1', ELB_RESOURCE_TYPE), Evaluation(ComplianceType.COMPLIANT, 'arn2', ELB_RESOURCE_TYPE), Evaluation(ComplianceType.COMPLIANT, 'arn3', ELB_RESOURCE_TYPE) ] rdklibtest.assert_successful_evaluation(self, response, resp_expected, 3)
def test_scenario1_noElbsInAccount_returnsNotApplicable(self): CONFIG_CLIENT_MOCK.list_discovered_resources = MagicMock(return_value={ 'resourceIdentifiers': [] }) response = RULE.evaluate_periodic(self.event, CLIENT_FACTORY, {}) rdklibtest.assert_successful_evaluation(self, response, [], 0)
def test_scenario1_evaluatechange_alllogsenabledonrds_returnscompliant( self): response = RULE.evaluate_change(None, CLIENT_FACTORY, self.all_logs_enabled_compliant, None) resp_expected = [Evaluation(ComplianceType.COMPLIANT)] rdklibtest.assert_successful_evaluation(self, response, resp_expected)