Skip to content

Commit a19cb57

Browse files
feat(core): Script for generating config rules configuration for acce… (aws-samples#530)
* feat(core): Script for generating config rules configuration for accelerator * Update README.md Co-authored-by: Brian969 <[email protected]>
1 parent e4d6a72 commit a19cb57

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
## AWS Config Rules Configuration generator script
2+
3+
This script take an AWS Conformance pack template (cloudformation yaml/json) found [here](https://docs.aws.amazon.com/config/latest/developerguide/conformancepack-sample-templates.html) as input and generates a configuration file containing the corresponding config rules and parameters formatted for consumption by the AWS Secure Environment Accelerator.
4+
5+
### Usage
6+
7+
```
8+
usage: generate-config-rules.py [-h] --path PATH [--outputFormat {json,yaml}]
9+
[--inputFormat {json,yaml}]
10+
```
11+
12+
### Example
13+
14+
```
15+
python generate-config-rules.py --path=/Users/Desktop/config --outputFormat=yaml
16+
```
17+
18+
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import yaml
2+
import argparse
3+
import json
4+
import os
5+
6+
7+
pseudo_params = ['AWS::AccountId', 'AWS::NotificationARNs', 'AWS::Partition',
8+
'AWS::Region', 'AWS::StackId', 'AWS::StackName', 'AWS::URLSuffix']
9+
none_param = 'AWS::NoValue'
10+
rules = []
11+
ruleNames = []
12+
13+
def generate_config(input_path, input_format, output_format):
14+
files = (file for file in os.listdir(input_path)
15+
if os.path.isfile(os.path.join(input_path, file)))
16+
for file_name in files:
17+
if not file_name.endswith(input_format):
18+
continue
19+
with open(os.path.join(input_path, file_name)) as f:
20+
if input_format == 'yaml':
21+
data = yaml.load(f, Loader=yaml.FullLoader)
22+
generate_config_impl(data)
23+
24+
with open(os.path.join(input_path, 'output', 'accel-config-rules.' + output_format), 'w') as writefile:
25+
print("Created Config Rules configuration in : %s" %
26+
os.path.join(input_path, 'output', 'accel-config-rules.' + output_format))
27+
if output_format == 'json':
28+
json.dump(rules, writefile, indent=2)
29+
print(json.dumps(ruleNames))
30+
else:
31+
yaml.dump(rules, writefile, indent=2)
32+
print(yaml.dump(ruleNames))
33+
34+
35+
def generate_config_impl(data):
36+
parameters = data.get("Parameters", [])
37+
resources = data.get("Resources", {})
38+
for name, props in resources.items():
39+
rule = {}
40+
if props['Type'] != "AWS::Config::ConfigRule":
41+
continue
42+
if not props["Properties"]["Source"] or props["Properties"]["Source"]["Owner"] != 'AWS':
43+
continue
44+
rule['name'] = props["Properties"]["Source"]["SourceIdentifier"]
45+
ruleNames.append(props["Properties"]["Source"]["SourceIdentifier"])
46+
for param_name, value in props["Properties"].get("InputParameters", {}).items():
47+
if 'parameters' not in rule:
48+
rule['parameters'] = {}
49+
if not isinstance(value, dict):
50+
rule['parameters'][param_name] = value
51+
else:
52+
if 'Ref' in value:
53+
if parameters.get(value['Ref']) and parameters.get(value['Ref']).get('Default'):
54+
rule['parameters'][param_name] = parameters[value['Ref']]['Default']
55+
elif 'Fn::If' in value:
56+
true_val = value['Fn::If'][1]
57+
false_val = value['Fn::If'][2] if len(
58+
value['Fn::If']) > 2 else None
59+
if isinstance(true_val, dict) and 'Ref' in true_val:
60+
if parameters.get(true_val['Ref']):
61+
if true_val['Ref'] in pseudo_params:
62+
rule['parameters'][param_name] = true_val['Ref']
63+
elif parameters.get(true_val['Ref']).get('Default'):
64+
rule['parameters'][param_name] = parameters[true_val['Ref']]['Default']
65+
elif isinstance(true_val, str):
66+
rule['parameters'][param_name] = true_val
67+
elif isinstance(false_val, dict):
68+
if parameters.get(false_val['Ref']):
69+
if false_val['Ref'] in pseudo_params:
70+
rule['parameters'][param_name] = false_val['Ref']
71+
elif parameters.get(false_val['Ref']).get('Default'):
72+
rule['parameters'][param_name] = parameters[false_val['Ref']]['Default']
73+
elif isinstance(false_val, str):
74+
rule['parameters'][param_name] = false_val
75+
if param_name not in rule["parameters"]:
76+
rule['parameters'][param_name] = "${REPLACE::%s}" % param_name
77+
rules.append(rule)
78+
return
79+
80+
81+
if __name__ == "__main__":
82+
parser = argparse.ArgumentParser(description='Generate Config Options')
83+
parser.add_argument('--path', required=True,
84+
help='Input File path', default=os.path.expanduser('~'))
85+
parser.add_argument('--outputFormat', required=False,
86+
choices=['json', 'yaml'], help='json/yaml', default='json')
87+
parser.add_argument('--inputFormat', required=False,
88+
choices=['json', 'yaml'], help='json/yaml', default='yaml')
89+
args = parser.parse_args()
90+
if not os.path.exists(os.path.join(args.path, 'output')):
91+
os.mkdir(os.path.join(args.path, 'output'))
92+
generate_config(args.path, args.inputFormat, args.outputFormat)

0 commit comments

Comments
 (0)