Skip to content

get a report of all enabled/not enabled SCPs across accounts in an organization

0

Customer is looking for a way to create a report of all enabled as well as not enabled SCPs across all the accounts in an organization. There isn't any way to get a consolidated view of this in console as of now.

Only way i see is write some code using AWS organizations sdk and get this report which would involve iterating till the parent hierarchy up to the root for each account to get all the SCPs applied directly or inherited from parent OUs.

  • please accept the answer if it was helpful

1 Answer
0

To generate a report of all enabled and not enabled Service Control Policies (SCPs) across all accounts in an AWS Organization, you indeed need to use the AWS Organizations SDK. Here's a Python script using Boto3 that iterates through your organization's accounts and organizational units (OUs) to gather information about the SCPs applied.

import boto3
import csv

org_client = boto3.client('organizations')

def list_organizational_units(parent_id):
    ous = []
    paginator = org_client.get_paginator('list_organizational_units_for_parent')
    for page in paginator.paginate(ParentId=parent_id):
        ous.extend(page['OrganizationalUnits'])
    return ous

def list_accounts_for_ou(ou_id):
    accounts = []
    paginator = org_client.get_paginator('list_accounts_for_parent')
    for page in paginator.paginate(ParentId=ou_id):
        accounts.extend(page['Accounts'])
    return accounts

def list_scps_for_target(target_id):
    scps = []
    paginator = org_client.get_paginator('list_policies_for_target')
    for page in paginator.paginate(TargetId=target_id, Filter='SERVICE_CONTROL_POLICY'):
        scps.extend(page['Policies'])
    return scps

def get_scps_status(scp_ids):
    scp_status = {}
    for scp_id in scp_ids:
        response = org_client.describe_policy(PolicyId=scp_id)
        scp_status[scp_id] = response['Policy']['PolicySummary']['AwsManaged']
    return scp_status

def main():
    root_id = org_client.list_roots()['Roots'][0]['Id']
    all_ous = list_organizational_units(root_id)
    all_accounts = []
    for ou in all_ous:
        accounts = list_accounts_for_ou(ou['Id'])
        all_accounts.extend(accounts)

    scp_report = []
    for account in all_accounts:
        scps = list_scps_for_target(account['Id'])
        scp_ids = [scp['Id'] for scp in scps]
        scp_status = get_scps_status(scp_ids)
        for scp in scps:
            scp_report.append({
                'AccountId': account['Id'],
                'AccountName': account['Name'],
                'SCPName': scp['Name'],
                'SCPId': scp['Id'],
                'Enabled': scp['Status'] == 'ENABLED',
                'AwsManaged': scp_status[scp['Id']]
            })

    # Write the report to a CSV file
    with open('scp_report.csv', 'w', newline='') as csvfile:
        fieldnames = ['AccountId', 'AccountName', 'SCPName', 'SCPId', 'Enabled', 'AwsManaged']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()
        for row in scp_report:
            writer.writerow(row)

if __name__ == '__main__':
    main()

EXPERT
answered a year ago
  • I think that'll work, but with any substantial number of accounts, repeatedly calling get_scps_status() for the same SCP policy IDs over and over again may waste a lot of time. It'd be more efficient to enumerate all the SCPs once at the start, store the status by policy ID in a dictionary, and use the dictionary for hyper-quick lookups when receiving the SCP policy IDs attached to individual accounts in the all_accounts for loop.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.