def test__retrieve_noncompliant_checks():
    # Arrange
    check_compliant = Check('TestService', '...', ComplianceStatus.Compliant)
    check_noncompliant = Check('IAM', 'No IAM users...',
                               ComplianceStatus.NonCompliant)

    assessment = Assessment('playground-dev', '123456789098')
    assessment.add_check(check_compliant)
    assessment.add_check(check_noncompliant)

    # Act
    checks = assessment.non_compliant_checks()
    # handler(event, None)

    # Assert
    assert len(checks) == 1
예제 #2
0
def inventory_wide_open_s3_buckets(regions, session=boto3) -> Check:
    check = Check('S3', 'S3 bucket wide open for the world',
                  ComplianceStatus.Compliant)

    client = session.client('s3')
    response = client.list_buckets()
    for bucket in response['Buckets']:
        bucket_name = bucket['Name']
        try:
            response = client.get_bucket_policy_status(Bucket=bucket_name)
        except ClientError as e:
            # No bucket policy exist
            continue

        policy_status = response['PolicyStatus']
        if policy_status['IsPublic']:
            response = client.get_bucket_policy(Bucket=bucket_name)
            policy_json = response['Policy']
            policy = eval(policy_json)
            for statement in policy['Statement']:
                if 'Condition' not in statement:
                    metadata = CheckMetadata('Bucket name', f'{bucket_name}')
                    check.add_metadata(metadata)
                    check.compliance_status = ComplianceStatus.NonCompliant
                    break

    return check
예제 #3
0
def inventory_ec2_wide_open_security_groups(regions, session=boto3) -> Check:
    check = Check('EC2',
                  'Security Groups should not be wide open for the world',
                  ComplianceStatus.Compliant)

    for region in regions:
        client = session.client('ec2', region)
        response = client.describe_security_groups()
        for security_group in response['SecurityGroups']:
            group_name = security_group['GroupName']
            for ip_permission in security_group['IpPermissions']:
                ip_ranges = ip_permission['IpRanges']
                for ip_range in ip_ranges:
                    cidr_ip = ip_range['CidrIp']
                    if cidr_ip == '0.0.0.0/0':
                        from_port = ip_permission['FromPort']
                        to_port = ip_permission['ToPort']
                        if from_port != 443 or to_port != 443:
                            check_metadata_1 = CheckMetadata(
                                'Security group', f'{group_name} ({region})')
                            check_metadata_2 = CheckMetadata(
                                'Port ranges',
                                f'From port: {from_port}  To port: {to_port}')
                            check.add_metadata(check_metadata_1)
                            check.add_metadata(check_metadata_2)
                            check.compliance_status = ComplianceStatus.NonCompliant

    return check
예제 #4
0
def inventory_account_mfa_on_root_user(regions, session=boto3) -> Check:
    check = Check('Account', 'MFA should be enabled on root user',
                  ComplianceStatus.Compliant)

    client = session.client('iam')
    response = client.get_account_summary()
    account_mfa_enabled = response['SummaryMap']['AccountMFAEnabled']
    if not account_mfa_enabled:
        # print('$$$ MFA on ROOT is not enabled')
        check.compliance_status = ComplianceStatus.NonCompliant

    return check
def test__create_non_compliant_assessment():
    # Arrange
    check = Check('IAM', 'No IAM users...', ComplianceStatus.NonCompliant)
    metadata = CheckMetadata(key='ResourceId', value='i-345bh34bjky56b34')
    check.add_metadata(metadata)

    assessment = Assessment('playground-dev', '123456789098')
    assessment.add_check(check)

    assessment_readable = str(assessment)
    print(assessment_readable)

    # Assert
    assert 'i-345bh34bjky56b34' in assessment_readable
예제 #6
0
def inventory_s3_as_static_website(regions, session=boto3) -> Check:
    check = Check('S3', 'S3 bucket should not be used for static hosting',
                  ComplianceStatus.Compliant)

    client = session.client('s3')
    response = client.list_buckets()
    for bucket in response['Buckets']:
        bucket_name = bucket['Name']
        try:
            response = client.get_bucket_website(Bucket=bucket_name)

            metadata = CheckMetadata('Bucket name', f'{bucket_name}')
            check.add_metadata(metadata)
            check.compliance_status = ComplianceStatus.NonCompliant
        except:
            pass

    return check
예제 #7
0
def inventory_wide_open_iam_role(regions, session=boto3) -> Check:
    check = Check('IAM', 'IAM Role wide open for the world',
                  ComplianceStatus.Compliant)

    client = session.client('iam')
    response = client.list_roles()
    roles = response['Roles']
    for role in roles:
        assume_role_policy_document = role['AssumeRolePolicyDocument']
        role_name = role['RoleName']
        statements = assume_role_policy_document['Statement']
        for statement in statements:
            principal = statement['Principal']
            if 'AWS' in principal:
                if principal['AWS'] == '*':
                    metadata = CheckMetadata('Role', f'{role_name}')
                    check.add_metadata(metadata)
                    check.compliance_status = ComplianceStatus.NonCompliant

    return check
예제 #8
0
def inventory_wide_open_sns_topics(regions, session=boto3) -> Check:
    check = Check('SNS', 'SNS topic wide open for the world',
                  ComplianceStatus.Compliant)

    for region in regions:
        client = session.client('sns', region)
        response = client.list_topics()  # NextToken='string')
        topics = response['Topics']

        for topic in topics:
            topic_arn = topic['TopicArn']
            response = client.get_topic_attributes(TopicArn=topic_arn)
            attributes = response['Attributes']
            policy_json = attributes['Policy']
            policy = eval(policy_json)
            for statement in policy['Statement']:
                if statement['Principal'] == '*':
                    metadata = CheckMetadata('SNS topic',
                                             f'{topic_arn} ({region})')
                    check.add_metadata(metadata)
                    check.compliance_status = ComplianceStatus.NonCompliant

    return check
예제 #9
0
def inventory_iam_users(regions, session=boto3) -> Check:
    check = Check('IAM', 'IAM User with old access keys (over 90 days)',
                  ComplianceStatus.Compliant)

    client = session.client('iam')
    response = client.list_users()
    users = response['Users']
    for user in users:
        user_name = user['UserName']
        response = client.list_access_keys(UserName=user_name)
        for key in response['AccessKeyMetadata']:
            created = key['CreateDate']
            access_key_id = key['AccessKeyId']
            age = datetime.datetime.now(datetime.timezone.utc) - created
            if age.days > 90:
                check_metadata_1 = CheckMetadata(
                    'User name',
                    f'{user_name} (Key Id: {access_key_id}, Key days of age: {age.days})'
                )
                check.add_metadata(check_metadata_1)
                check.compliance_status = ComplianceStatus.NonCompliant

    return check
예제 #10
0
def inventory_cloudtrail_active(regions, session=boto3) -> Check:
    check = Check(
        'CloudTrail',
        'At least one active CloudTrail trail should be present in account',
        ComplianceStatus.Compliant)

    for region in regions:
        client = session.client('cloudtrail', region)
        response = client.list_trails()
        trails = response['Trails']
        trail_on = False
        for trail in trails:
            trail_arn = trail['TrailARN']
            response = client.get_trail_status(Name=trail_arn)
            is_logging = response['IsLogging']
            if is_logging:
                trail_on = True
        if not trail_on:
            metadata = CheckMetadata('No active trail', f'{region}')
            check.add_metadata(metadata)
            check.compliance_status = ComplianceStatus.NonCompliant

    return check
예제 #11
0
def inventory_wide_open_sqs_queue(regions, session=boto3) -> Check:
    check = Check('SQS', 'SQS queue wide open for the world',
                  ComplianceStatus.Compliant)

    for region in regions:
        client = session.client('sqs', region)
        response = client.list_queues()
        if 'QueueUrls' not in response:
            return check

        for queue_url in response['QueueUrls']:
            response_policy = client.get_queue_attributes(
                QueueUrl=queue_url, AttributeNames=['Policy'])

            policy_json = response_policy['Attributes']['Policy']
            policy = eval(policy_json)
            for statement in policy['Statement']:
                if statement['Principal'] == '*':
                    metadata = CheckMetadata('SQS queue',
                                             f'{queue_url} ({region})')
                    check.add_metadata(metadata)
                    check.compliance_status = ComplianceStatus.NonCompliant

    return check