Skip to content

Instantly share code, notes, and snippets.

@nitrocode
Last active April 27, 2020 20:18
Show Gist options
  • Save nitrocode/4820ba57f3bf5ef4d4254738496fc79c to your computer and use it in GitHub Desktop.
Save nitrocode/4820ba57f3bf5ef4d4254738496fc79c to your computer and use it in GitHub Desktop.
Policy reordering

Find Terraform Changes in JSON

Currently only finds terraform plan changes

terraform plan -out=terraform.tfplan
terraform show -no-color -json terraform.tfplan > terraform.tfplan.json
python find-tf-changes.py terraform.tfplan.json

Would be nice to bake this directly into Terraform or into Landscape

#!/usr/bin/env python3
# This only checks for terraform policy changes
# Usage:
#
# terraform plan -out=terraform.tfplan
# terraform show -no-color -json terraform.tfplan > terraform.tfplan.json
# python find-tfpolicy-changes.py terraform.tfplan.json
#
import json
import sys
with open(sys.argv[1], "rb") as f:
data = json.loads(f.read())
for resource in data['resource_changes']:
before_policy = resource['change']['before'].get('policy')
after_policy = resource['change']['after'].get('policy')
if not before_policy or not after_policy:
continue
before_policy = json.loads(before_policy)
after_policy = json.loads(after_policy)
for idx in range(len(before_policy['Statement'])):
before_statement = before_policy['Statement']
after_statement = after_policy['Statement']
if before_statement == after_statement:
continue
for key in before_statement[idx].keys():
if before_statement[idx][key] == after_statement[idx][key]:
continue
if not key.lower() in ['principal', 'action']:
continue
end_resource = []
try:
after_principals = after_statement[idx][key]['AWS']
before_principals = before_statement[idx][key]['AWS']
end_resource = ['Principal', 'AWS']
except TypeError:
after_principals = after_statement[idx][key]
before_principals = before_statement[idx][key]
end_resource = ['Action']
# remove duplicates and only find differences using set logic
changes_after = list(set(after_principals) - set(before_principals))
changes_before = list(set(before_principals) - set(after_principals))
if len(changes_after) == 0 and len(changes_before) == 0:
continue
if len(changes_after) > 0:
changes = changes_after
else:
changes = changes_before
print(
f"{resource['address']}.policy.Statement[{idx}]."
f"{'.'.join(end_resource)}"
)
if len(changes) == 0:
continue
for change in changes:
if change in before_principals:
print('- {}'.format(change))
elif change in after_principals:
print('+ {}'.format(change))
@dharamsk
Copy link

I adapted your solution to apply to gcp and any other resource types. It's janky, but unblocks us from using 0.12.
https://gist.github.com/dharamsk/3ed613389876e049a5c0a04c5772c073

Thanks!

@nitrocode
Copy link
Author

Nice work. Glad I could help get you started 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment