Repository: Netflix/consoleme
File: consoleme/celery_tasks/celery_tasks.py (Python)

Code before:
    cloudtrail_errors = {}
    cloudtrail_errors_j = red.get(
        config.get(
            "celery.cache_cloudtrail_errors_by_arn.redis_key",
            "CLOUDTRAIL_ERRORS_BY_ARN",
        )
    )

    if cloudtrail_errors_j:
        cloudtrail_errors = json.loads(cloudtrail_errors_j)

    s3_error_topic = config.get("redis.s3_errors", "S3_ERRORS")
    all_s3_errors = red.get(s3_error_topic)
    s3_errors = {}
    if all_s3_errors:
        s3_errors = json.loads(all_s3_errors)

    allowed_tags = config.get("roles.allowed_tags", {})
    allowed_arns = config.get("roles.allowed_arns", [])
    for arn, role_details_j in all_iam_roles.items():
        role_details = ujson.loads(role_details_j)

        allowed = True

        actual_tags = {k: v for d in role_details.get("Tags") for k, v in d.items()} # Convert List[Dicts] to 1 Dict
        if allowed_tags and not allowed_tags.items() <= actual_tags.items():
            allowed = False

        if allowed_arns and arn not in allowed_arns:
            allowed = False

        if not allowed:
            continue

        error_count = cloudtrail_errors.get(arn, 0)
        s3_errors_for_arn = s3_errors.get(arn, [])
        for error in s3_errors_for_arn:
            error_count += int(error.get("count"))

        account_id = arn.split(":")[4]
        account_name = accounts_d.get(str(account_id), "Unknown")
        resource_id = role_details.get("resourceId")
        items.append(
            {
                "account_id": account_id,
                "account_name": account_name,
                "arn": arn,
                "technology": "AWS::IAM::Role",
                "templated": red.hget(
                    config.get("templated_roles.redis_key", "TEMPLATED_ROLES_v2"),
                    arn.lower(),

Review comment (suggestion):
@rms1000watt 
From my understanding of this line: 
1. If ALL tags present in allowed_tags should also be present in the role's tags (i.e. if allowed_tags has multiply key-value pairs, it is an AND requirement for the allowed tags)
2. The role is allowed to have other tags, other than in the allowed list?

Is that correct?
If so, may want to add a comment before this line 😄 

Code after:

    cloudtrail_errors = {}
    cloudtrail_errors_j = red.get(
        config.get(
            "celery.cache_cloudtrail_errors_by_arn.redis_key",
            "CLOUDTRAIL_ERRORS_BY_ARN",
        )
    )

    if cloudtrail_errors_j:
        cloudtrail_errors = json.loads(cloudtrail_errors_j)

    s3_error_topic = config.get("redis.s3_errors", "S3_ERRORS")
    all_s3_errors = red.get(s3_error_topic)
    s3_errors = {}
    if all_s3_errors:
        s3_errors = json.loads(all_s3_errors)

    for arn, role_details_j in all_iam_roles.items():
        role_details = ujson.loads(role_details_j)
        role_details_policy = ujson.loads(role_details.get("policy", {}))
        role_tags = role_details_policy.get("Tags", {})

        if not allowed_to_sync_role(arn, role_tags):
            continue

        error_count = cloudtrail_errors.get(arn, 0)
        s3_errors_for_arn = s3_errors.get(arn, [])
        for error in s3_errors_for_arn:
            error_count += int(error.get("count"))

        account_id = arn.split(":")[4]
        account_name = accounts_d.get(str(account_id), "Unknown")
        resource_id = role_details.get("resourceId")
        items.append(
            {
                "account_id": account_id,
                "account_name": account_name,
                "arn": arn,
                "technology": "AWS::IAM::Role",
                "templated": red.hget(
                    config.get("templated_roles.redis_key", "TEMPLATED_ROLES_v2"),
                    arn.lower(),
                ),
                "errors": error_count,
                "config_history_url": async_to_sync(
                    get_aws_config_history_url_for_resource
                )(account_id, resource_id, arn, "AWS::IAM::Role"),
            }
        )