Skip to content

Commit 8d37b46

Browse files
[NDR-316] Now scans for account IDs. Can replace with aliases.
1 parent f053293 commit 8d37b46

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

scripts/export_role_policies.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
"""
2+
23
Generate a JSON dump of IAM permissions for a given role.
4+
Anything that looks like an account ID (12 digit number) will cause the script to fail,
5+
to prevent committing sensitive information to a repo.
6+
7+
Sensitive account IDs can be found/replaced with aliases using the command line arguments.
8+
The replaced values will be in the format ${alias}.
9+
10+
Usage:
11+
python export_role_policies.py <role_name> [<find>=<replace> ...]
12+
313
"""
414

515
import json
616
import re
17+
import sys
718

819
from argparse import ArgumentParser
920
from collections import defaultdict
@@ -42,7 +53,7 @@ def get_attached_role_policy(client, policy_arn):
4253
return version_response['PolicyVersion']['Document']['Statement']
4354

4455

45-
def main(account, role):
56+
def main(role, aliases):
4657
client = boto3.client('iam')
4758
policy_map = defaultdict(lambda: defaultdict(dict))
4859

@@ -51,20 +62,35 @@ def main(account, role):
5162
permissions = get_role_policy(client, role, policy_name)
5263
policy_map['inline'][policy_name] = permissions
5364

54-
# # Get attached policies for the role
65+
# Get attached policies for the role
5566
for attached_policy in list_attached_role_policies(client, role):
5667
policy_name = attached_policy['PolicyName']
5768
policy_arn = attached_policy['PolicyArn']
5869
permissions = get_attached_role_policy(client, policy_arn)
5970
policy_map['attached'][policy_name] = permissions
6071

6172
json_text = json.dumps(policy_map, indent=2)
62-
print(re.sub(account, "${account_id}", json_text))
73+
for search, replace in aliases.items():
74+
json_text = re.sub(search, f"${{{replace}}}", json_text)
75+
76+
# Fail on anything that looks like an account ID
77+
# e.g. :123456789012:
78+
matches = set(re.findall(r"\D(\d{12})\D", json_text))
79+
if matches:
80+
print("Warning! Found potential account IDs in policies.\n"
81+
"These should be replaced with an alias before committing to a repo:\n"
82+
f"{', '.join(matches)}",
83+
file=sys.stderr)
84+
sys.exit(1)
85+
86+
print(json_text)
6387

6488

6589
if __name__ == "__main__":
6690
parser = ArgumentParser(description="Export IAM policies for a given role and account")
67-
parser.add_argument("account", help="Account ID to replace in output with ${account_id}")
6891
parser.add_argument("role", help="Role to export")
92+
parser.add_argument("aliases", nargs='*',
93+
help="A list of aliases to apply. E.g. 123456789012=prod_account")
6994
args = parser.parse_args()
70-
main(args.account, args.role)
95+
alias_map = {alias.split('=')[0]: alias.split('=')[1] for alias in args.aliases}
96+
main(args.role, alias_map)

0 commit comments

Comments
 (0)