経緯
InspectorのWebコンソールにアクセスせずとも結果を見たい。
かつ通知は重要度が高のものに限定し大量の通知は避けたい。
標準では評価結果を通知することが出来ない為、lambdaで頑張ります。
※プログラミング素人の為、参考にさせて頂いた方とほぼ同じです。
Inspector
InspectorはEC2の脆弱性を評価し、結果をレポートにまとめてくれる素晴らしいサービスです。
メールの通知に必要な3つのJSON
inspectorからSNS連携すればよいのかと思っていましたが、違いました。
検知された脆弱性の詳細を得るには3つのJSONファイルを順番に参照する必要があります。
- 「実行完了」時に受信できるJSON
{
"template": "arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:target/x-xxxxxxxx/template/x-xxxxxxxx",
"findingsCount": "{arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:rulespackage/x-xxxxxxxxxx, arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:rulespackage/x-xxxxxxxxxx, arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:rulespackage/x-xxxxxxxxxx, arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:rulespackage/x-xxxxxxxxxx, arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:rulespackage/x-xxxxxxxxxx}",
"run": "arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:target/x-xxxxxxxx/template/x-xxxxxxxx/run/x-xxxxxxxx",
"event": "ASSESSMENT_RUN_COMPLETED",
"target": "arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:target/x-xxxxxxxx"
}
- 上記のrunに記載されてあるArnから拾える「評価結果」一覧
※検知された脆弱性の数で以下arnの件数は増減します。
{
"findingArns": [
"arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:target/x-xxxxxxxx/template/x-xxxxxxxx/run/x-xxxxxxxx/finding/x-xxxxxxxx",
"arn:aws:inspector:ap-northeast-1:xxxxxxxxxxxx:target/x-xxxxxxxx/template/x-xxxxxxxx/run/x-xxxxxxxx/finding/x-xxxxxxxx",
]
}
- 「評価結果」のArnから拾える脆弱性の詳細
{
"findings": [
{
"assetType": "ec2-instance",
"confidence": 10,
"numericSeverity": 9.0,
"description": "During key agreement in a TLS handshake using a DH(E) based ciphersuite a malicious server can send a very large prime value to the client. This will cause the client to spend an unreasonably long period of time generating a key for this prime resulting in a hang until the client has finished. This could be exploited in a Denial Of Service attack. Fixed in OpenSSL 1.1.0i-dev (Affected 1.1.0-1.1.0h). Fixed in OpenSSL 1.0.2p-dev (Affected 1.0.2-1.0.2o).",
"service": "Inspector",
"title": "Instance i-xxxxxxxxxxxxxxxxx is vulnerable to CVE-2018-0732",
"assetAttributes": {
"amiId": "ami-xxxxxxxxxxxxxxxxx",
"hostname": "ec2-xx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com",
},
"recommendation": "Use your Operating System's update feature to update package openssl-1:1.0.2k-12.amzn2.0.3, openssl-libs-1:1.0.2k-12.amzn2.0.3. For more information see [https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-0732](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-0732)",
"id": "CVE-2018-0732",
"severity": "High"
}
]
}
Lambda(Python3.6)
import json
import boto3
TOPIC_ARN = 'SNSトピックのArn'
def mail(subject, msg):
client = boto3.client('sns')
request = {
'TopicArn': TOPIC_ARN,
'Message': msg,
'Subject': subject
}
response = client.publish(**request)
return response
# 評価結果
def get_findingArns(assessmentRunArn):
client = boto3.client('inspector')
findingArns = []
nextToken = ""
while(True):
if(nextToken != ""):
response = client.list_findings(
assessmentRunArns=[
assessmentRunArn,
],
maxResults=500,
nextToken=nextToken
)
else:
response = client.list_findings(
assessmentRunArns=[
assessmentRunArn,
],
maxResults=500
)
if("nextToken" not in response):
for arn in response["findingArns"]:
findingArns.append(arn)
break
else:
for arn in response["findingArns"]:
findingArns.append(arn)
nextToken = response["nextToken"]
return findingArns
# main
def lambda_handler(event, context):
try:
client = boto3.client('inspector')
# RunArn
obj = event["Records"][0]["Sns"]["Message"]
obj = json.loads(obj)
assessmentRunArn = obj["run"]
assessmentTemplateArn = assessmentRunArn.rsplit("/", 2)[0]
# findingArns
findingArns = get_findingArns(assessmentRunArn)
size = 100
output = ""
describe_findings = []
findingArns_split = [findingArns[x:x + size] for x in range(0, len(findingArns), size)]
for findingArns_100 in findingArns_split:
describe_findings = describe_findings + client.describe_findings(findingArns=findingArns_100, locale='EN_US')["findings"]
# 脆弱性の詳細内の"severity" = "High"である条件に合致した内容から以下の項目抜粋
for finding in describe_findings:
if finding["severity"] == "High":
title = finding["title"]
amiId = finding["assetAttributes"]["amiId"]
ec2name = finding["assetAttributes"]["hostname"]
cveid = finding["id"]
severity = finding["severity"]
recommendation = finding["recommendation"]
output = output + '【' + str(title) + '】' + \
'\n ami Id :' + str(amiId) + \
'\n ec2 name :' + str(ec2name) + \
'\n vulnerability id :' + str(cveid) + \
'\n severity :' + str(severity) + \
'\n recommendation :' + str(recommendation) + \
'\n inspector arn :' + finding["arn"] + '\n \n'
else:
pass
# アラート
if(output != ""):
mail('Inspector alert', output)
else:
output = "Nothing to alert."
mail('Inspector alert', output)
return output
except:
import traceback
output = traceback.format_exc()
mail('Inspector error', output + "\n\n" + json.dumps(event, indent=4))
return output
Lambdaの必要なPolicy
- AmazonInspectorReadOnlyAccess
- "sns:Publish"
通知内容
まとめ
当初SNS連携では詳細が得られなかった為、無理なのだと思いましたが、
様々な方のナレッジのお陰で実装することができました。
内容は薄いですが、誰かの参考になれば幸いです。
参考リンク
Inspectorの実行結果をCSVファイルとして出力する
Amazon Inspector の評価結果詳細を自動通知できるか調べてみた
Amazon Inspectorの脆弱性診断結果の差分を通知する