def test_single_event_good(mocker):
    # Read test data
    event = utils.load_test_data(test_data + 'CIS_1-6-single-select.json',
                                 my_region)

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)

    # create client directly through boto3 and stub it
    iamc = boto3.client('iam')
    iamc_s = Stubber(iamc)

    iamc_s.add_response('update_account_password_policy', {})
    iamc_s.activate()

    mocker.patch('lib.awsapi_helpers.BotoSession.client', return_value=iamc)
    mocker.patch('lib.awsapi_helpers.AWSClient.postit', return_value=None)

    # Mock Notifier
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')

    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    cis15111.lambda_handler(event, None)
    init.assert_called_once_with(
        'INITIAL: "Set IAM Password Policy" remediation started')
    resolve.assert_called_once_with(
        'RESOLVED: "Set IAM Password Policy" remediation was successful')
def test_send_metrics(mocker):

    expected_response = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/1.3',
            'type':
            '1.3 Ensure credentials unused for 90 days or greater are disabled',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'unit-test',
            'region': mocker.ANY
        },
        'Version': 'v1.2.0TEST'
    }

    os.environ['sendAnonymousMetrics'] = 'Yes'

    finding = utils.load_test_data(test_data + 'cis_1-3-iamuser1.json',
                                   my_region).get('detail').get('findings')[0]

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.activate()

    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)

    metrics = Metrics({"detail-type": "unit-test"})
    metrics_data = metrics.get_metrics_from_finding(finding)

    send_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    metrics.send_metrics(metrics_data)

    send_metrics.assert_called_with(expected_response)
def test_handler(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis24.json', my_region)
    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)

    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)
    remediate = mocker.patch('cis24.remediate', return_value=None)

    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    cis24.lambda_handler(event, None)
    remediate.assert_called_once()
def test_event_bad(mocker):
    # Read test data
    event = utils.load_test_data(test_data + 'cis_1-3.json', my_region)

    iam_keys = {
        "AccessKeyMetadata": [
            {
                "UserName": "******",
                "AccessKeyId": "AKIAADFHWEREFGFHSDDF",
                "Status": "Active",
                "CreateDate": "2015-05-22T14:43:16+00:00"
            },
            {
                "UserName": "******",
                "AccessKeyId": "AKIAGHJGJFGHJFGETHFG",
                "Status": "Active",
                "CreateDate": "2020-05-15T15:20:04+00:00"
            }
        ]
    }
    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)

    # create client and resource directly through boto3
    iamc = boto3.client('iam', region_name=my_region)
    iamr = boto3.resource('iam', region_name=my_region)

    # stub the client
    iamc_s = Stubber(iamc)
    iamr_s = Stubber(iamr.meta.client)

    iamc_s.add_response(
        'list_access_keys',
        iam_keys
    )
    iam_keys['AccessKeyMetadata'][0]['Status'] = 'Inactive'
    iamc_s.add_response(
        'list_access_keys',
        iam_keys
    )

    iamc_s.activate()
    iamr_s.activate()

    # Mock the client and resource to return the clients we created
    mocker.patch('lib.awsapi_helpers.BotoSession.client', return_value=iamc)
    mocker.patch('lib.awsapi_helpers.BotoSession.resource', return_value=iamr)
    mocker.patch('lib.awsapi_helpers.AWSClient.postit', return_value=None)

    # Mock flush so we don't
    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    # Mock Notifier
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    update = mocker.patch('lib.sechub_findings.Finding.update_text')

    cis1314.lambda_handler(event, None)
    init.assert_called_with(
        'INITIAL: "Deactivate unused keys over 90 days old" remediation started'
    )
    update.assert_called_once_with(
        'FAILED: "Deactivate unused keys over 90 days old" remediation failed. Please remediate manually'
    )
def test_event_good(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis29.json', my_region)

    sns_message = {
        'Note':
        '"Enable VPC flow logging in all VPCs" remediation was successful',
        'State': 'RESOLVED',
        'Account': '111111111111',
        'Remediation': 'Enable VPC flow logging in all VPCs',
        'AffectedObject': 'VPC Flow Logs for VPC: vpc-d1a07fba',
        'metrics_data': mocker.ANY
    }
    os.environ['AWS_SESSION_TOKEN'] = 'FAKETOKEN'
    os.environ['FLOW_LOG_ROLE_ARN'] = 'FAKELOGROLEARN'

    post_metrics_expected_parms = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/2.9',
            'type': '2.9 Ensure VPC flow logging is enabled in all VPCs',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'Security Hub Findings - Custom Action',
            'region': mocker.ANY,
            'status': 'RESOLVED'
        },
        'Version': 'v1.2.0TEST'
    }

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    awsc = [boto3.client('logs'), boto3.client('ec2')]

    def mock_select(thing1, thing2):
        if thing2 == 'logs':
            return awsc[0]
        else:
            return awsc[1]

    # Mock the boto clients and replace the BotoSession client with our stub
    awsc_s = Stubber(awsc[0])
    awsc_s.add_response('create_log_group', {})
    awsc_s.activate()

    aws2c_s = Stubber(awsc[1])
    aws2c_s.add_response('create_flow_logs', {})
    aws2c_s.add_response('describe_flow_logs',
                         {'FlowLogs': [{
                             'FlowLogStatus': 'ACTIVE'
                         }]})
    aws2c_s.activate()

    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit',
                       return_value=None)

    # redirect to mock_select above to return the proper stub
    mocker.patch('lib.awsapi_helpers.BotoSession.client', new=mock_select)

    # Mock notifications
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')

    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis29.lambda_handler(event, None)
    init.assert_called_once_with(
        'INITIAL: "Enable VPC flow logging in all VPCs" remediation started')
    resolve.assert_called_once_with(
        'RESOLVED: "Enable VPC flow logging in all VPCs" remediation was successful'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
    post_metrics.assert_called_with(post_metrics_expected_parms)
def test_not_remediated(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis29.json', my_region)
    post_metrics_expected_parms = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/2.9',
            'type': '2.9 Ensure VPC flow logging is enabled in all VPCs',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'Security Hub Findings - Custom Action',
            'region': mocker.ANY,
            'status': 'FAILED'
        },
        'Version': 'v1.2.0TEST'
    }
    os.environ['AWS_SESSION_TOKEN'] = 'FAKETOKEN'
    os.environ['FLOW_LOG_ROLE_ARN'] = 'FAKELOGROLEARN'

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)

    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    awsc = [boto3.client('logs'), boto3.client('ec2')]

    def mock_select(thing1, thing2):
        if thing2 == 'logs':
            return awsc[0]
        else:
            return awsc[1]

    awsc_s = Stubber(awsc[0])
    awsc_s.add_response('create_log_group', {})
    awsc_s.activate()

    aws2c_s = Stubber(awsc[1])
    aws2c_s.add_response('create_flow_logs', {})
    aws2c_s.add_response('describe_flow_logs', {'FlowLogs': []})
    aws2c_s.activate()

    # redirect to mock_select above to return the proper stub
    mocker.patch('lib.awsapi_helpers.BotoSession.client', new=mock_select)

    # Mock notifications
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')
    update = mocker.patch('lib.sechub_findings.Finding.update_text')

    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis29.lambda_handler(event, None)

    init.assert_called_once_with(
        'INITIAL: "Enable VPC flow logging in all VPCs" remediation started')
    update.assert_called_once_with(
        'FAILED: "Enable VPC flow logging in all VPCs" remediation failed. Please remediate manually',
        status='FAILED')
    resolve.assert_not_called()
    post_metrics.assert_called_with(post_metrics_expected_parms)
def test_event_good(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis43.json', my_region)

    sns_message = {
        'Note':
        '"Remove all rules from the default security group" remediation was successful',
        'State': 'RESOLVED',
        'Account': '111111111111',
        'Remediation': 'Remove all rules from the default security group',
        'AffectedObject': 'Security Group: sg-02cfbecbc814a3c24',
        'metrics_data': mocker.ANY
    }

    desc_sg = {
        "SecurityGroups": [{
            "Description":
            "Default SG",
            "GroupName":
            "SC-111111111111-pp-gz465ubujkfrs-SandboxSecurityGroup-175ZDF23V5MGX",
            "IpPermissions": [{
                "FromPort": 80,
                "IpProtocol": "tcp",
                "IpRanges": [{
                    "CidrIp": "0.0.0.0/0"
                }],
                "Ipv6Ranges": [],
                "PrefixListIds": [],
                "ToPort": 80,
                "UserIdGroupPairs": []
            }, {
                "FromPort": 9000,
                "IpProtocol": "tcp",
                "IpRanges": [{
                    "CidrIp": "72.21.198.65/32"
                }],
                "Ipv6Ranges": [],
                "PrefixListIds": [],
                "ToPort": 9000,
                "UserIdGroupPairs": []
            }, {
                "FromPort": 22,
                "IpProtocol": "tcp",
                "IpRanges": [{
                    "CidrIp": "0.0.0.0/0"
                }],
                "Ipv6Ranges": [],
                "PrefixListIds": [],
                "ToPort": 22,
                "UserIdGroupPairs": []
            }],
            "OwnerId":
            "123412341234",
            "GroupId":
            "sg-006bf520b9581b2d9",
            "IpPermissionsEgress": [{
                "IpProtocol": "-1",
                "IpRanges": [{
                    "CidrIp": "0.0.0.0/0"
                }],
                "Ipv6Ranges": [],
                "PrefixListIds": [],
                "UserIdGroupPairs": []
            }],
            "Tags": [],
            "VpcId":
            "vpc-11111113"
        }]
    }

    post_metrics_expected_parms = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/4.3',
            'type':
            '4.3 Ensure the default security group of every VPC restricts all traffic',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'Security Hub Findings - Custom Action',
            'region': mocker.ANY,
            'status': 'RESOLVED'
        },
        'Version': 'v1.2.0TEST'
    }

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    # Mock the boto client and replace the BotoSession client with our stub
    awsc = boto3.resource('ec2')
    awsc_s = Stubber(awsc.meta.client)
    awsc_s.add_response('describe_security_groups', desc_sg)
    awsc_s.add_response('revoke_security_group_ingress', {})
    awsc_s.add_response('revoke_security_group_egress', {})
    awsc_s.activate()
    mocker.patch('lib.awsapi_helpers.BotoSession.resource', return_value=awsc)

    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit',
                       return_value=None)

    # Mock Notifier
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')

    # Prevent flushing to logs
    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis43.lambda_handler(event, None)
    init.assert_called_once_with(
        'INITIAL: "Remove all rules from the default security group" remediation started'
    )
    resolve.assert_called_once_with(
        'RESOLVED: "Remove all rules from the default security group" remediation was successful'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
    post_metrics.assert_called_with(post_metrics_expected_parms)
예제 #8
0
def test_event_good(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis26.json', my_region)

    sns_message = {
        'Note':
        '"Enable Access Logging on CloudTrail logs bucket" remediation was successfully invoked via AWS Systems Manager',
        'State': 'RESOLVED',
        'Account': '111111111111',
        'Remediation': 'Enable Access Logging on CloudTrail logs bucket',
        'AffectedObject':
        'CloudTrail: cloudtrail-awslogs-111111111111-cv5ddz5l-isengard-do-not-delete',
        'metrics_data': mocker.ANY
    }

    post_metrics_expected_parms = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/2.6',
            'type':
            '2.6 Ensure S3 bucket access logging is enabled on the CloudTrail S3 bucket',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'Security Hub Findings - Custom Action',
            'region': mocker.ANY,
            'status': 'RESOLVED'
        },
        'Version': 'v1.2.0TEST'
    }

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    awsc = [boto3.client('ssm'), boto3.client('s3')]

    def mock_select(thing1, thing2):
        if thing2 == 'ssm':
            return awsc[0]
        elif thing2 == 's3':
            return awsc[1]
        else:
            return

    # Mock the boto client and replace the BotoSession client with our stub
    awsc_s = Stubber(awsc[0])
    awsc_s.add_response('start_automation_execution', {})
    awsc_s.activate()

    awss3_s = Stubber(awsc[1])
    awss3_s.add_response('create_bucket', {})
    awss3_s.add_response('put_bucket_encryption', {})
    awss3_s.activate()

    mocker.patch('lib.awsapi_helpers.BotoSession.client', new=mock_select)

    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit',
                       return_value=None)

    # Mock Notifier
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')

    # Prevent flushing to logs
    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis26.lambda_handler(event, None)

    init.assert_called_once_with(
        'INITIAL: "Enable Access Logging on CloudTrail logs bucket" remediation started'
    )
    resolve.assert_called_once_with(
        'RESOLVED: "Enable Access Logging on CloudTrail logs bucket" remediation was successfully invoked via AWS Systems Manager'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
    post_metrics.assert_called_with(post_metrics_expected_parms)
def test_event_bad(mocker):
    # Read test data
    event = utils.load_test_data(test_data + 'cis_1-3.json', my_region)

    iam_keys = {
        "AccessKeyMetadata": [{
            "UserName": "******",
            "AccessKeyId": "AKIAADFHWEREFGFHSDDF",
            "Status": "Active",
            "CreateDate": "2015-05-22T14:43:16+00:00"
        }, {
            "UserName": "******",
            "AccessKeyId": "AKIAGHJGJFGHJFGETHFG",
            "Status": "Active",
            "CreateDate": "2020-05-15T15:20:04+00:00"
        }]
    }

    post_metrics_expected_parms = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/1.3',
            'type':
            '1.3 Ensure credentials unused for 90 days or greater are disabled',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'Security Hub Findings - Custom Action',
            'region': mocker.ANY,
            'status': 'FAILED'
        },
        'Version': 'v1.2.0TEST'
    }

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)

    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)

    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)

    # create client and resource directly through boto3
    iamc = boto3.client('iam', region_name=my_region)
    iamr = boto3.resource('iam', region_name=my_region)

    # stub the client
    iamc_s = Stubber(iamc)
    iamr_s = Stubber(iamr.meta.client)

    iamc_s.add_response('list_access_keys', iam_keys)
    iamc_s.add_response('update_access_key', {})
    iam_keys['AccessKeyMetadata'][0]['Status'] = 'Inactive'
    iamc_s.add_response('list_access_keys', iam_keys)
    iamc_s.add_response('update_access_key', {})
    # iam_keys['AccessKeyMetadata'][0]['Status'] = 'Inactive'
    iamc_s.add_response('list_access_keys', iam_keys)

    iamc_s.activate()
    iamr_s.activate()

    # Mock the client and resource to return the clients we created
    mocker.patch('lib.awsapi_helpers.BotoSession.client', return_value=iamc)
    mocker.patch('lib.awsapi_helpers.BotoSession.resource', return_value=iamr)
    mocker.patch('lib.awsapi_helpers.AWSClient.postit', return_value=None)

    # Mock flush so we don't
    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    # Mock Notifier
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    update = mocker.patch('lib.sechub_findings.Finding.update_text')

    cis1314.lambda_handler(event, None)
    init.assert_called_with(
        'INITIAL: "Deactivate unused keys over 90 days old" remediation started'
    )
    update.assert_called_once_with(
        'FAILED: "Deactivate unused keys over 90 days old" remediation failed. Please remediate manually',
        status='FAILED')
    post_metrics.assert_called_with(post_metrics_expected_parms)
def test_multi_event_good(mocker):
    # Read test data
    event = utils.load_test_data(test_data + 'CIS_1-6-multi-select.json',
                                 my_region)

    sns_message = {
        'Note': '"Set IAM Password Policy" remediation was successful',
        'State': 'RESOLVED',
        'Account': '111111111111',
        'Remediation': 'Set IAM Password Policy',
        'AffectedObject': 'IAM Password Policy',
        'metrics_data': mocker.ANY
    }

    post_metrics_expected_parms = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/1.6',
            'type':
            '1.6 Ensure IAM password policy requires at least one lowercase letter',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'Security Hub Findings - Custom Action',
            'region': mocker.ANY,
            'status': 'RESOLVED'
        },
        'Version': 'v1.2.0TEST'
    }

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)

    # create client directly through boto3 and stub it
    iamc = boto3.client('iam')

    iamc_s = Stubber(iamc)

    # set up responses for the lambda. One for each call.
    # We expect 2 - one for each finding in this test data
    iamc_s.add_response('update_account_password_policy', {})
    iamc_s.add_response('update_account_password_policy', {})
    # Activate the stubber
    iamc_s.activate()

    # mock methods that we don't want to go through
    mocker.patch('lib.awsapi_helpers.BotoSession.client', return_value=iamc)

    # Mock Notifier's call to resolve so we can examine the parameters
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')
    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit')
    # Mock flush so it doesn't execute
    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    cis15111.lambda_handler(event, None)
    init.assert_called_with(
        'INITIAL: "Set IAM Password Policy" remediation started')
    resolve.assert_called_with(
        'RESOLVED: "Set IAM Password Policy" remediation was successful')
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
    post_metrics.assert_called_with(post_metrics_expected_parms)
def test_event_good(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis29.json', my_region)

    sns_message = {
        'Note': '"Enable VPC flow logging in all VPCs" remediation was successful',
        'State': 'RESOLVED',
        'Account': '111111111111',
        'Remediation': 'Enable VPC flow logging in all VPCs',
        'AffectedObject': 'VPC Flow Logs for VPC: vpc-d1a07fba',
        'metrics_data': {'status': 'RESOLVED'}
    }
    os.environ['AWS_SESSION_TOKEN'] = 'FAKETOKEN'
    os.environ['FLOW_LOG_ROLE_ARN'] = 'FAKELOGROLEARN'

    #--------------------------
    # Mock/stub
    #
    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    awsc = [
        boto3.client('logs'),
        boto3.client('ec2')
    ]

    def mock_select(thing1, thing2):
        if thing2 == 'logs':
            return awsc[0]
        else:
            return awsc[1]

    # Mock the boto clients and replace the BotoSession client with our stub
    awsc_s = Stubber(awsc[0])
    awsc_s.add_response(
        'create_log_group',
        {}
    )
    awsc_s.activate()

    aws2c_s = Stubber(awsc[1])
    aws2c_s.add_response(
        'create_flow_logs',
        {}
    )
    aws2c_s.add_response(
        'describe_flow_logs',
        {
            'FlowLogs': [
                {
                    'FlowLogStatus': 'ACTIVE'
                }
            ]
        }
    )
    aws2c_s.activate()

    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit', return_value=None)

    # redirect to mock_select above to return the proper stub
    mocker.patch('lib.awsapi_helpers.BotoSession.client', new=mock_select)

    # Mock notifications
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')

    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis29.lambda_handler(event, None)
    init.assert_called_once_with(
        'INITIAL: "Enable VPC flow logging in all VPCs" remediation started'
    )
    resolve.assert_called_once_with(
        'RESOLVED: "Enable VPC flow logging in all VPCs" remediation was successful'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
def test_not_remediated(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis29.json', my_region)

    os.environ['AWS_SESSION_TOKEN'] = 'FAKETOKEN'
    os.environ['FLOW_LOG_ROLE_ARN'] = 'FAKELOGROLEARN'

    #--------------------------
    # Mock/stub
    #
    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    awsc = [
        boto3.client('logs'),
        boto3.client('ec2')
    ]

    def mock_select(thing1, thing2):
        if thing2 == 'logs':
            return awsc[0]
        else:
            return awsc[1]

    awsc_s = Stubber(awsc[0])
    awsc_s.add_response(
        'create_log_group',
        {}
    )
    awsc_s.activate()

    aws2c_s = Stubber(awsc[1])
    aws2c_s.add_response(
        'create_flow_logs',
        {}
    )
    aws2c_s.add_response(
        'describe_flow_logs',
        {
            'FlowLogs': [
            ]
        }
    )
    aws2c_s.activate()

    # redirect to mock_select above to return the proper stub
    mocker.patch('lib.awsapi_helpers.BotoSession.client', new=mock_select)

    # Mock notifications
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')
    update = mocker.patch('lib.sechub_findings.Finding.update_text')

    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis29.lambda_handler(event, None)

    init.assert_called_once_with(
        'INITIAL: "Enable VPC flow logging in all VPCs" remediation started'
    )
    update.assert_called_once_with(
        'FAILED: "Enable VPC flow logging in all VPCs" remediation failed. Please remediate manually'
    )
    resolve.assert_not_called()
def test_event_good(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis23.json', my_region)

    sns_message = {
        'Note':
        '"Disable S3 public access" remediation was successfully completed',
        'State': 'RESOLVED',
        'Account': '111111111111',
        'Remediation': 'Disable S3 public access',
        'AffectedObject':
        'S3 Bucket: cloudtrail-awslogs-111111111111-kjfskljdfl',
        'metrics_data': mocker.ANY
    }

    #--------------------------
    # Mock/stub
    #

    ssm_uuid = {
        "Parameter": {
            "Name": "/Solutions/SO0111/anonymous_metrics_uuid",
            "Type": "String",
            "Value": "12345678-1234-1234-1234-123412341234",
            "Version": 1,
            "LastModifiedDate": "2021-02-25T12:58:50.591000-05:00",
            "ARN":
            "arn:aws:ssm:us-east-1:1111111111111111:parameter/Solutions/SO0111/anonymous_metrics_uuid",
            "DataType": "text"
        }
    }

    post_metrics_expected_parms = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/2.3',
            'type':
            '2.3 Ensure the S3 bucket used to store CloudTrail logs is not publicly accessible',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'Security Hub Findings - Custom Action',
            'region': mocker.ANY,
            'status': 'RESOLVED'
        },
        'Version': 'v1.2.0TEST'
    }

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    # Mock the boto client and replace the BotoSession client with our stub
    awsc = boto3.client('s3')
    awsc_s = Stubber(awsc)
    awsc_s.add_response('put_public_access_block', {})
    awsc_s.activate()
    mocker.patch('lib.awsapi_helpers.BotoSession.client', return_value=awsc)

    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit',
                       return_value=None)

    # Mock Notifier
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')

    # Prevent flushing to logs
    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis23.lambda_handler(event, None)

    init.assert_called_once_with(
        'INITIAL: "Disable S3 public access" remediation started')
    resolve.assert_called_once_with(
        'RESOLVED: "Disable S3 public access" remediation was successfully completed'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
    post_metrics.assert_called_with(post_metrics_expected_parms)
예제 #14
0
def test_event_good(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis26.json', my_region)

    sns_message = {
        'Note':
        '"Enable Access Logging on CloudTrail logs bucket" remediation was successfully invoked via AWS Systems Manager',
        'State': 'RESOLVED',
        'Account': '111111111111',
        'Remediation': 'Enable Access Logging on CloudTrail logs bucket',
        'AffectedObject':
        'CloudTrail: cloudtrail-awslogs-111111111111-cv5ddz5l-isengard-do-not-delete',
        'metrics_data': {
            'status': 'RESOLVED'
        }
    }

    #--------------------------
    # Mock/stub
    #
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    awsc = [boto3.client('ssm'), boto3.client('s3')]

    def mock_select(thing1, thing2):
        if thing2 == 'ssm':
            return awsc[0]
        elif thing2 == 's3':
            return awsc[1]
        else:
            return

    # Mock the boto client and replace the BotoSession client with our stub
    awsc_s = Stubber(awsc[0])
    awsc_s.add_response('start_automation_execution', {})
    awsc_s.activate()

    awss3_s = Stubber(awsc[1])
    awss3_s.add_response('create_bucket', {})
    awss3_s.add_response('put_bucket_encryption', {})
    awss3_s.activate()

    mocker.patch('lib.awsapi_helpers.BotoSession.client', new=mock_select)

    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit',
                       return_value=None)

    # Mock Notifier
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')

    # Prevent flushing to logs
    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis26.lambda_handler(event, None)

    init.assert_called_once_with(
        'INITIAL: "Enable Access Logging on CloudTrail logs bucket" remediation started'
    )
    resolve.assert_called_once_with(
        'RESOLVED: "Enable Access Logging on CloudTrail logs bucket" remediation was successfully invoked via AWS Systems Manager'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
def test_event_good(mocker):
    # Read test data
    event = utils.load_test_data(test_data + 'cis_1-3-iamuser1.json',
                                 my_region)

    sns_message = {
        'Note': 'Access key over 90 days old found: AKIAGHJGJFGHJFGETHFG',
        'State': 'INFO',
        'Account': '111111111111',
        'Remediation': 'Deactivate unused keys over 90 days old',
        'metrics_data': mocker.ANY,
        'AffectedObject': 'Access Key: AKIAGHJGJFGHJFGETHFG'
    }

    iam_keys = {
        "AccessKeyMetadata": [{
            "UserName": "******",
            "AccessKeyId": "AKIAADFHWEREFGFHSDDF",
            "Status": "Active",
            "CreateDate": "2015-05-22T14:43:16+00:00"
        }, {
            "UserName": "******",
            "AccessKeyId": "AKIAGHJGJFGHJFGETHFG",
            "Status": "Active",
            "CreateDate": "2020-05-15T15:20:04+00:00"
        }]
    }

    post_metrics_expected_parms = {
        'Solution': 'SO0111',
        'UUID': '12345678-1234-1234-1234-123412341234',
        'TimeStamp': mocker.ANY,
        'Data': {
            'generator_id':
            'arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/1.3',
            'type':
            '1.3 Ensure credentials unused for 90 days or greater are disabled',
            'productArn': mocker.ANY,
            'finding_triggered_by': 'Security Hub Findings - Custom Action',
            'region': mocker.ANY,
            'status': 'RESOLVED'
        },
        'Version': 'v1.2.0TEST'
    }

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)

    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)

    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    # sess = BotoSession()
    iamc = boto3.client('iam', region_name=my_region)
    iamr = boto3.resource('iam', region_name=my_region)

    iamc_s = Stubber(iamc)
    iamr_s = Stubber(iamr.meta.client)

    iamc_s.add_response('list_access_keys', iam_keys)
    iamr_s.add_response('update_access_key', {})
    iam_keys['AccessKeyMetadata'][0]['Status'] = 'Inactive'
    iamc_s.add_response('list_access_keys', iam_keys)

    iamr_s.add_response('update_access_key', {})

    iam_keys['AccessKeyMetadata'][0]['Status'] = 'Inactive'
    iamc_s.add_response('list_access_keys', iam_keys)

    iamc_s.activate()
    iamr_s.activate()

    # Replace BotoSession client/resource with our stub
    mocker.patch('lib.awsapi_helpers.BotoSession.client', return_value=iamc)
    mocker.patch('lib.awsapi_helpers.BotoSession.resource', return_value=iamr)
    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit',
                       return_value=None)

    # Mock Notifier
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')
    flag = mocker.patch('lib.sechub_findings.Finding.flag')

    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    cis1314.lambda_handler(event, None)

    flag.assert_called_once_with(
        'INITIAL: "Deactivate unused keys over 90 days old" remediation started'
    )
    resolve.assert_called_once_with(
        'RESOLVED: Remediation completed successfully, create new access keys using IAM console.'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)

    post_metrics.assert_called_with(post_metrics_expected_parms)
def test_event_good(mocker):
    # Read test data
    event = utils.load_test_data(test_data + 'cis_1-3-iamuser1.json', my_region)

    sns_message = {
        'Note': 'Access key over 90 days old found: AKIAGHJGJFGHJFGETHFG',
        'State': 'INFO',
        'Account': '111111111111',
        'Remediation': 'Deactivate unused keys over 90 days old',
        'AffectedObject': 'Access Key: AKIAGHJGJFGHJFGETHFG',
        'metrics_data': {'status': 'INFO'},
    }

    iam_keys = {
        "AccessKeyMetadata": [
            {
                "UserName": "******",
                "AccessKeyId": "AKIAADFHWEREFGFHSDDF",
                "Status": "Active",
                "CreateDate": "2015-05-22T14:43:16+00:00"
            },
            {
                "UserName": "******",
                "AccessKeyId": "AKIAGHJGJFGHJFGETHFG",
                "Status": "Active",
                "CreateDate": "2020-05-15T15:20:04+00:00"
            }
        ]
    }

    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    # sess = BotoSession()
    iamc = boto3.client('iam', region_name=my_region)
    iamr = boto3.resource('iam', region_name=my_region)

    iamc_s = Stubber(iamc)
    iamr_s = Stubber(iamr.meta.client)

    iamc_s.add_response(
        'list_access_keys',
        iam_keys
    )
    iamr_s.add_response(
        'update_access_key',
        {}
    )
    iam_keys['AccessKeyMetadata'][0]['Status'] = 'Inactive'
    iamc_s.add_response(
        'list_access_keys',
        iam_keys
    )

    iamr_s.add_response(
        'update_access_key',
        {}
    )

    iam_keys['AccessKeyMetadata'][0]['Status'] = 'Inactive'
    iamc_s.add_response(
        'list_access_keys',
        iam_keys
    )

    iamc_s.activate()
    iamr_s.activate()

    # Replace BotoSession client/resource with our stub
    mocker.patch('lib.awsapi_helpers.BotoSession.client', return_value=iamc)
    mocker.patch('lib.awsapi_helpers.BotoSession.resource', return_value=iamr)
    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit', return_value=None)

    # Mock Notifier
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')
    flag = mocker.patch('lib.sechub_findings.Finding.flag')

    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    cis1314.lambda_handler(event, None)
    flag.assert_called_once_with(
        'INITIAL: "Deactivate unused keys over 90 days old" remediation started'
    )
    resolve.assert_called_once_with(
        'RESOLVED: Remediation completed successfully, create new access keys using IAM console.'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
예제 #17
0
def test_event_good(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis43.json', my_region)

    sns_message = {
        'Note':
        '"Remove all rules from the default security group" remediation was successful',
        'State': 'RESOLVED',
        'Account': '111111111111',
        'Remediation': 'Remove all rules from the default security group',
        'AffectedObject': 'Security Group: sg-02cfbecbc814a3c24',
        'metrics_data': {
            'status': 'RESOLVED'
        }
    }

    desc_sg = {
        "SecurityGroups": [{
            "Description":
            "Default SG",
            "GroupName":
            "SC-111111111111-pp-gz465ubujkfrs-SandboxSecurityGroup-175ZDF23V5MGX",
            "IpPermissions": [{
                "FromPort": 80,
                "IpProtocol": "tcp",
                "IpRanges": [{
                    "CidrIp": "0.0.0.0/0"
                }],
                "Ipv6Ranges": [],
                "PrefixListIds": [],
                "ToPort": 80,
                "UserIdGroupPairs": []
            }, {
                "FromPort": 9000,
                "IpProtocol": "tcp",
                "IpRanges": [{
                    "CidrIp": "72.21.198.65/32"
                }],
                "Ipv6Ranges": [],
                "PrefixListIds": [],
                "ToPort": 9000,
                "UserIdGroupPairs": []
            }, {
                "FromPort": 22,
                "IpProtocol": "tcp",
                "IpRanges": [{
                    "CidrIp": "0.0.0.0/0"
                }],
                "Ipv6Ranges": [],
                "PrefixListIds": [],
                "ToPort": 22,
                "UserIdGroupPairs": []
            }],
            "OwnerId":
            "123412341234",
            "GroupId":
            "sg-006bf520b9581b2d9",
            "IpPermissionsEgress": [{
                "IpProtocol": "-1",
                "IpRanges": [{
                    "CidrIp": "0.0.0.0/0"
                }],
                "Ipv6Ranges": [],
                "PrefixListIds": [],
                "UserIdGroupPairs": []
            }],
            "Tags": [],
            "VpcId":
            "vpc-11111113"
        }]
    }

    #--------------------------
    # Mock/stub
    #
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    # Mock the boto client and replace the BotoSession client with our stub
    awsc = boto3.resource('ec2')
    awsc_s = Stubber(awsc.meta.client)
    awsc_s.add_response('describe_security_groups', desc_sg)
    awsc_s.add_response('revoke_security_group_ingress', {})
    awsc_s.add_response('revoke_security_group_egress', {})
    awsc_s.activate()
    mocker.patch('lib.awsapi_helpers.BotoSession.resource', return_value=awsc)

    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit',
                       return_value=None)

    # Mock Notifier
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')

    # Prevent flushing to logs
    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis43.lambda_handler(event, None)
    init.assert_called_once_with(
        'INITIAL: "Remove all rules from the default security group" remediation started'
    )
    resolve.assert_called_once_with(
        'RESOLVED: "Remove all rules from the default security group" remediation was successful'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
def test_event_good(mocker):
    #--------------------------
    # Test data
    #
    event = utils.load_test_data(test_data + 'cis22.json', my_region)

    sns_message = {
        'Note':
        '"Enable CloudTrail log file validation" remediation was successful',
        'State': 'RESOLVED',
        'Account': '111111111111',
        'Remediation': 'Enable CloudTrail log file validation',
        'AffectedObject': 'CloudTrail: ExampleTrail',
        'metrics_data': mocker.ANY
    }

    post_metrics_expected_parms = {
        "Solution": "SO0111",
        "UUID": "12345678-1234-1234-1234-123412341234",
        "TimeStamp": mocker.ANY,
        "Data": {
            "generator_id":
            "arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/2.2",
            "type": "2.2 Ensure CloudTrail log file validation is enabled",
            "productArn": mocker.ANY,
            "finding_triggered_by": "Security Hub Findings - Custom Action",
            "region": mocker.ANY,
            "status": "RESOLVED"
        },
        "Version": "v1.2.0TEST"
    }

    ssmc = boto3.client('ssm', region_name=my_region)
    ssmc_s = Stubber(ssmc)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_uuid)
    ssmc_s.add_response('get_parameter', mock_ssm_get_parameter_version)
    ssmc_s.activate()
    mocker.patch('lib.metrics.Metrics.connect_to_ssm', return_value=ssmc)
    post_metrics = mocker.patch('lib.metrics.Metrics.post_metrics_to_api',
                                return_value=None)

    # Mock the constructor. We don't need the session created
    mocker.patch('lib.awsapi_helpers.BotoSession.__init__', return_value=None)
    mocker.patch('lib.awsapi_helpers.AWSClient.connect', return_value=None)

    # Mock the boto client and replace the BotoSession client with our stub
    awsc = boto3.client('cloudtrail')
    awsc_s = Stubber(awsc)
    awsc_s.add_response('update_trail', {})
    awsc_s.activate()
    mocker.patch('lib.awsapi_helpers.BotoSession.client', return_value=awsc)

    sns = mocker.patch('lib.awsapi_helpers.AWSClient.postit',
                       return_value=None)

    # Mock Notifier
    init = mocker.patch('lib.sechub_findings.Finding.flag')
    resolve = mocker.patch('lib.sechub_findings.Finding.resolve')

    mocker.patch('lib.applogger.LogHandler.flush', return_value=None)

    #--------------------------
    # Run the lambda
    #
    cis22.lambda_handler(event, None)

    init.assert_called_once_with(
        'INITIAL: "Enable CloudTrail log file validation" remediation started')
    resolve.assert_called_once_with(
        'RESOLVED: "Enable CloudTrail log file validation" remediation was successful'
    )
    sns.assert_called_with('SO0111-SHARR_Topic', sns_message, my_region)
    post_metrics.assert_called_with(post_metrics_expected_parms)