Menu
blog.headdesk.me
blog.headdesk.me

Dumping AWS Organization tree

Posted on 2022/05/142022/05/15

Recently, I’m tasked to transfer a set of AWS accounts to another cloud service provider. I realize there is not a simple way to capture the organizational tree structure. Knowing the tree structure is quite important in understanding the net effects of SCP. A python script is developed to solve this problem.

Initially, I used awscli and bash to traverse the tree and print out OU and account info. That is incredibly inefficient. The script was completely rewritten with python. It starts by checking the root id, then recursively traverse through the tree and print out all OU and member account info.

Source code is available on my git repo. Here is what it produces on a sandbox environment:

▶ ./aws-org-dump.py
Root  r-2le9
. xpk-mp 221414080000
. Workload ou-2le9-uibp6p5e
.. Regional-Prod ou-2le9-3l86wfde
.. Regional-Dev ou-2le9-bidgckf7
... workload1 872439010000
. Core ou-2le9-6yr1a2uf
.. Core-prod ou-2le9-patloil1
.. Core-Dev ou-2le9-scv4v7d1
... logging 958052660000

The biggest challenge for me is to extract data from the API response. AWS returns a dictionary for every boto3 call. For example, list_organizational_units_for_parent() returns the following response:

{'Roots': [{'Id': 'r-2le9', 'Arn': 'arn:aws:organizations::221414080000:root/o-fn3felbr1b/r-2le9', 'Name': 'Root', 'PolicyTypes': [{'Type': 'BACKUP_POLICY', 'Status': 'ENABLED'}, {'Type': 'TAG_POLICY', 'Status': 'ENABLED'}, {'Type': 'SERVICE_CONTROL_POLICY', 'Status': 'ENABLED'}]}], 'ResponseMetadata': {'RequestId': 'f378ed19-50ae-4114-a3f4-5a40c2c1a35b', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': 'f378ed19-50ae-4114-a3f4-5a40c2c1a35b', 'content-type': 'application/x-amz-json-1.1', 'content-length': '264', 'date': 'Sat, 14 May 2022 03:22:35 GMT'}, 'RetryAttempts': 0}}

I’m only interested in the root id. So first I need to figure out the first key in the map, which is Roots. Then I only need the first element in the list, which is another map where the value of Id can be found. For other queries, the response can be a much more complex map. To even visualize the map, try do a json.dumps() and feed the result to jq. From what I see, the response dictionary is already json-like. json.dumps() simple replaces the single quotes with double quotes. Apparently, python map uses single quote for string, while json uses double quote.

Give it a try if you also need to compile something like this.

facebookShare on Facebook
TwitterTweet

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Full text search

Recent Posts

  • Terraform and segregated permissions
  • LVM Compression and Deduplication
  • Edit gpg encrypted file with vim
  • Lelit Elizabeth PL92T Pressure Tuning
  • jq transformation
  • aws (8)
  • coffee (1)
  • headfi (1)
  • linux (6)
  • others (58)
  • security (2)
  • tech (36)
  • wordpress (2)

apache aws awscli azure backup clearlinux cloud coffee docker DOCP ec2 EL8 epyc espresso featured gpg jenkins kernel lelit linux lvm meltdown memory MFA mikrotik php python rdp Redhat RHEL roasting rpm Ryzen site-to-site snapshot spectre tech terraform tuning ubuntu ubuntu upgrade vim vpn wordpress xdotool

©2023 blog.headdesk.me | Powered by SuperbThemes & WordPress