Für die cloudxs GmbH haben wir eine Multi Account AWS Umgebung via AWS Control Tower aufgebaut. Der Vorteil von Control Tower ist, dass man Leitplanken (Guardrails) auf die neu erstellten Accounts anwenden und durchsetzen kann. Somit hat man einen grossen Teil der Cloud Governance erschlagen. Es gibt Guardrails die eine Aktion verhindern und es gibt Guardrails die einen Verstoss nur alarmieren. Die Alarmierung wird über AWS SNS (Simple Notification Service) gemacht, der wiederum eine E-Mail an den Security Verantwortlichen schickt. Mehr über den AWS Control Tower kommt in einem weiteren Blog Eintrag.
Nun wollten wir aber eine automatische Message Card in unserem Office 365 Teams Channel haben, damit wir auch dort bei Verstössen alarmiert werden. Dies haben wir via einer AWS Lambda Funktion die von der SNS Notifikation getriggert wird erreicht. Die Lambda Funktion ist ein Python Skript, dass den Office 365 Channel Webhook aufruft und die Message Card mit den entsprechenden Informationen erstellt.
Der Python Code in der Lambda Funktion sieht folgendermassen aus:
lambda_handler(event, context):
#Start Log Eintrag
logger.info("Event: " + str(event))
#Die SNS Meldung aus der event Variablen lesen
message = json.loads(event['Records'][0]['Sns']['Message'])
logger.info("Message: " + str(message))
#Die Daten für die Message Card generieren
detailtype = message['detail-type']
resourceId = message['detail']['resourceId']
awsRegion = message['detail']['awsRegion']
awsAccountId = message['detail']['awsAccountId']
configRuleName = message['detail']['configRuleName']
messageType = message['detail']['messageType']
complianceType = message['detail']['newEvaluationResult']['complianceType']
resultRecordedTime= message['detail']['newEvaluationResult']['resultRecordedTime']
#Die Farbe der Message Card anhand des Compiance Typ setzen
color = "ff9103"
if complianceType == "NON_COMPLIANT":
color = "ff0c00"
elif complianceType == "COMPLIANT":
color = "2eff00"
#Message Card Daten zusammenstellen
data = {
"colour": color,
"title": "**%s**" % detailtype,
"text": "**Resscoure ID:** %s \n
**AWS Region:** %s \n
**AWS Account ID:** %s \n
**Config Rule Name:** %s \n
**Message Type:** %s \n
**Compliance Type:** %s \n
**Result Record Time:** %s" %
(resourceId,
awsRegion,
awsAccountId,
configRuleName.replace("_","\_"),
messageType,
complianceType.replace("_","\_")
resultRecordedTime)
}
#Message Card zusammen stellen
message = {
"@context": "https://schema.org/extensions",
"@type": "MessageCard",
"themeColor": data["colour"],
"title": data["title"],
"text": data["text"]
}
#Message Card an Microsoft Teams Channel senden
req = Request(HOOK_URL, json.dumps(message).encode('utf-8'))
try:
response = urlopen(req)
response.read()
logger.info("Message posted")
except HTTPError as e:
logger.error("Request failed: %d %s", e.code, e.reason)
except URLError as e:
logger.error("Server connection failed: %s", e.reason)
Der Webhook wird via Environment Variable mitgegeben. Dieser kann, wenn gewünscht, auch verschlüsselt im AWS Secrets Manager hinterlegt werden und direkt im Python Code geholt werden. Dies bietet den grössten Schutz weil die Passwörter so nicht im Code ersichtlich sind. Die Environment Variablen Ansicht bietet auch eine Verschlüsselung an, somit sieht man die Werte ebenfalls nicht im Klartext.
Der Webhook wird im Microsoft Teams Channel erstellt.
Dann nach «Incoming Webhook» suchen und diesen konfigurieren. Am Ende sollte dann bei einer Guardrail Verletzung oder Berichtigung eine neue Message Card erstellt werden.