-
Notifications
You must be signed in to change notification settings - Fork 28
/
lambda_handler.py
145 lines (119 loc) · 5.62 KB
/
lambda_handler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import boto3
import fnmatch
import json
import logging
import os
import sys
class Setup:
def __init__(self, logging):
# parameters
self.logging = logging
# variables
self.client = boto3.client('cloudformation')
def create_stacks(self, stack_sub_dir):
"""
Parse a directory and create the CloudFormation Stacks it contains.
"""
existing_stacks = self.get_current_stacks()
path = 'auto-remediate-setup/data/%s' % stack_sub_dir
print(existing_stacks)
for file in os.listdir(path):
if fnmatch.fnmatch(file, '*.json'):
stack_name = file.replace('.json', '')
template_body = None
with open(os.path.join(path, file)) as stack:
template_body = str(stack.read())
if stack_name not in existing_stacks:
# TODO Check if Stack deployment has been set to False
try:
self.client.create_stack(
StackName=stack_name,
TemplateBody=template_body,
OnFailure='DELETE',
EnableTerminationProtection=True)
self.logging.info("Creating CloudFormation Stack '%s'." % stack_name)
except:
self.logging.error("Could not create CloudFormation Stack '%s'." % stack_name)
self.logging.error(sys.exc_info())
continue
else:
# TODO If Stack deployment has been set to False, delete stack
self.logging.debug("Cloud Formation Stack '%s' already exists." % stack_name)
def get_current_stacks(self):
"""
Retrieve a list of all CloudFormation Stacks
currently deployed your AWS accont and region.
"""
try:
resources = self.client.list_stacks().get('StackSummaries')
except:
self.logging.error(sys.exc_info())
return None
existing_stacks = []
for resource in resources:
if resource.get('StackStatus') not in ('DELETE_COMPLETE'):
existing_stacks.append(resource.get('StackName'))
return existing_stacks
def setup_dynamodb(self):
"""
Inserts all the default settings into a DynamoDB table.
"""
try:
client = boto3.client('dynamodb')
settings_data = open('auto-remediate-setup/data/auto-remediate-settings.json')
settings_json = json.loads(settings_data.read())
update_settings = False
# get current settings version
current_version = client.get_item(
TableName=os.environ['SETTINGSTABLE'],
Key={'key': {'S': 'version'}},
ConsistentRead=True)
# get new settings version
new_version = float(settings_json[0].get('value', {}).get('N', 0.0))
# check if settings exist and if they're older than current settings
if 'Item' in current_version:
current_version = float(current_version.get('Item').get('value').get('N'))
if current_version < new_version:
update_settings = True
self.logging.info("Existing settings with version %s are "
"being updated to version %s in DynamoDB Table '%s'." % (str(current_version),
str(new_version),
os.environ['SETTINGSTABLE']))
else:
self.logging.debug("Existing settings are at the lastest
"version %s in DynamoDB Table '%s'." % (str(current_version),
os.environ['SETTINGSTABLE']))
else:
update_settings = True
self.logging.info("Settings are being inserted into DynamoDB "
"Table '%s' for the first time." % os.environ['SETTINGSTABLE'])
if update_settings:
for setting in settings_json:
try:
client.put_item(
TableName=os.environ['SETTINGSTABLE'],
Item=setting)
except:
self.logging.error(sys.exc_info())
continue
settings_data.close()
except:
self.logging.error(sys.exc_info())
def lambda_handler(event, context):
loggger = logging.getLogger()
if loggger.handlers:
for handler in loggger.handlers:
loggger.removeHandler(handler)
# change logging levels for boto and others
logging.getLogger('boto3').setLevel(logging.ERROR)
logging.getLogger('botocore').setLevel(logging.ERROR)
logging.getLogger('urllib3').setLevel(logging.ERROR)
# set logging format
logging.basicConfig(format="[%(levelname)s] %(message)s (%(filename)s, %(funcName)s(), line %(lineno)d)",
level=os.environ.get('LOGLEVEL', 'WARNING').upper())
# instantiate class
setup = Setup(logging)
# run functions
setup.setup_dynamodb()
setup.create_stacks('config_rules')
setup.create_stacks('custom_rules')