From 5372a84e0ae19754b980f3716d7e38e6222c4397 Mon Sep 17 00:00:00 2001 From: Ben Jones Date: Mon, 27 Feb 2023 09:58:08 -0500 Subject: [PATCH] Adding better support for AWS China and GovCloud --- commands/collect.py | 3 ++- commands/iam_report.py | 11 ++++++++++- commands/weboftrust.py | 40 ++++++++++++++++++++++++++++++++++------ shared/common.py | 19 ++++++++++++++----- shared/iam_audit.py | 13 +++++++++++-- 5 files changed, 71 insertions(+), 15 deletions(-) diff --git a/commands/collect.py b/commands/collect.py index 073914f4e..0e25351e6 100644 --- a/commands/collect.py +++ b/commands/collect.py @@ -337,7 +337,8 @@ def collect(arguments): if runner["Service"] in universal_services: if region["RegionName"] != default_region: continue - elif region["RegionName"] not in session.get_available_regions( + # GovCloud doesn't seem to have this mapping in boto3 + elif "gov" not in region["RegionName"] and region["RegionName"] not in session.get_available_regions( runner["Service"] ): print( diff --git a/commands/iam_report.py b/commands/iam_report.py index 0edd5c3aa..2c55f8569 100644 --- a/commands/iam_report.py +++ b/commands/iam_report.py @@ -365,6 +365,15 @@ def iam_report(accounts, config, args): principal_stats = {} json_account_auth_details = None + # Identify the default region used by global services such as IAM + default_region = os.environ.get("AWS_REGION", "us-east-1") + if "gov-" in default_region: + default_region = "us-gov-west-1" + elif "cn-" in default_region: + default_region = "cn-north-1" + else: + default_region = "us-east-1" + # Ensure only one account is given if len(accounts) > 1: raise Exception("This command only works with one account at a time") @@ -399,7 +408,7 @@ def iam_report(accounts, config, args): for region_json in get_regions(account): region = Region(account, region_json) - if region.name == "us-east-1": + if region.name == default_region: json_account_auth_details = query_aws( region.account, "iam-get-account-authorization-details", region ) diff --git a/commands/weboftrust.py b/commands/weboftrust.py index d5391803f..a790740ea 100644 --- a/commands/weboftrust.py +++ b/commands/weboftrust.py @@ -172,15 +172,26 @@ def get_direct_connects(account, nodes, connections): def get_iam_trusts(account, nodes, connections, connections_to_get): + + # Identify the default region used by global services such as IAM + default_region = os.environ.get("AWS_REGION", "us-east-1") + if "gov-" in default_region: + default_region = "us-gov-west-1" + elif "cn-" in default_region: + default_region = "cn-north-1" + else: + default_region = "us-east-1" + + # Get IAM iam = query_aws( account, "iam-get-account-authorization-details", - Region(account, {"RegionName": "us-east-1"}), + Region(account, {"RegionName": default_region}), ) saml_providers = query_aws( - account, "iam-list-saml-providers", Region(account, {"RegionName": "us-east-1"}) + account, "iam-list-saml-providers", Region(account, {"RegionName": default_region) )["SAMLProviderList"] for role in pyjq.all(".RoleDetailList[]", iam): @@ -356,8 +367,17 @@ def get_iam_trusts(account, nodes, connections, connections_to_get): def get_s3_trusts(account, nodes, connections): - policy_dir = "./account-data/{}/us-east-1/s3-get-bucket-policy/".format( - account.name + # Identify the default region used by global services such as IAM + default_region = os.environ.get("AWS_REGION", "us-east-1") + if "gov-" in default_region: + default_region = "us-gov-west-1" + elif "cn-" in default_region: + default_region = "cn-north-1" + else: + default_region = "us-east-1" + + policy_dir = "./account-data/{}/{}/s3-get-bucket-policy/".format( + account.name, default_region ) for s3_policy_file in [ f @@ -446,14 +466,22 @@ def get_nodes_and_connections(account_data, nodes, connections, args): def weboftrust(args, accounts, config): """Collect the data and write it to a file""" + # Identify the default region used by global services such as IAM + default_region = os.environ.get("AWS_REGION", "us-east-1") + if "gov-" in default_region: + default_region = "us-gov-west-1" + elif "cn-" in default_region: + default_region = "cn-north-1" + else: + default_region = "us-east-1" nodes = {} connections = {} for account in accounts: # Check if the account data exists if not path.exists( - "./account-data/{}/us-east-1/iam-get-account-authorization-details.json".format( - account["name"] + "./account-data/{}/{}/iam-get-account-authorization-details.json".format( + account["name"], default_region ) ): print("INFO: Skipping account {}".format(account["name"])) diff --git a/shared/common.py b/shared/common.py index f10338361..8afe21e79 100644 --- a/shared/common.py +++ b/shared/common.py @@ -327,13 +327,22 @@ def get_account_stats(account, all_resources=False): return stats -def get_us_east_1(account): +def get_default_region(account): + # Identify the default region used by global services such as IAM + default_region = os.environ.get("AWS_REGION", "us-east-1") + if "gov-" in default_region: + default_region = "us-gov-west-1" + elif "cn-" in default_region: + default_region = "cn-north-1" + else: + default_region = "us-east-1" + for region_json in get_regions(account): region = Region(account, region_json) - if region.name == "us-east-1": + if region.name == default_region: return region - raise InvalidAccountData("us-east-1 not found in {}".format(account.name)) + raise InvalidAccountData("default_region not found in {}".format(account.name)) def iso_date(d): @@ -354,7 +363,7 @@ def get_collection_date(account): account = Account(None, account) account_struct = account json_blob = query_aws( - account_struct, "iam-get-credential-report", get_us_east_1(account_struct) + account_struct, "iam-get-credential-report", get_default_region(account_struct) ) if not json_blob: raise InvalidAccountData( @@ -368,7 +377,7 @@ def get_collection_date(account): def get_access_advisor_active_counts(account, max_age=90): - region = get_us_east_1(account) + region = get_default_region(account) json_account_auth_details = query_aws( region.account, "iam-get-account-authorization-details", region diff --git a/shared/iam_audit.py b/shared/iam_audit.py index a9a33c714..b5933d461 100644 --- a/shared/iam_audit.py +++ b/shared/iam_audit.py @@ -146,7 +146,7 @@ def find_admins(accounts, args, findings): admins = [] for account in accounts: account = Account(None, account) - region = get_us_east_1(account) + region = get_default_region(account) admins.extend( find_admins_in_account( region, findings, privs_to_look_for, include_restricted @@ -159,6 +159,15 @@ def find_admins(accounts, args, findings): def find_admins_in_account( region, findings, privs_to_look_for=None, include_restricted=False ): + # Identify the default region used by global services such as IAM + default_region = os.environ.get("AWS_REGION", "us-east-1") + if "gov-" in default_region: + default_region = "us-gov-west-1" + elif "cn-" in default_region: + default_region = "cn-north-1" + else: + default_region = "us-east-1" + if privs_to_look_for is None: privs_to_look_for = [ "iam:PutRolePolicy", @@ -182,7 +191,7 @@ def find_admins_in_account( try: file_name = "account-data/{}/{}/{}".format( - account.name, "us-east-1", "iam-get-account-authorization-details.json" + account.name, default_region, "iam-get-account-authorization-details.json" ) iam = json.load(open(file_name)) except: