AWS
파이썬 이용한 AWS Security Group 보안 (특정 포트에 0.0.0.0/0 대역 오픈)
Always-Try
2021. 11. 22. 02:19
아래 블로그를 참고하여 AWS 시큐리티 그룹의 인바운드에 80, 443, 8080 이외의 포트를 0.0.0.0/0 대역의 IP에 오픈했을 때, SLACK으로 알림을 전달하는 기능을 구현했다. (테스트는 필자의 개인 AWS 계정 및 개인 SLACK에서 진행)
https://techblog.woowahan.com/2665/
import json
import os
import requests
HOOK_URL = "https://hooks.slack.com/services/삭제"
event = {
"eventVersion": "1.08",
"userIdentity": {
"type": "Root",
"principalId": "삭제",
"arn": "arn:aws:iam::삭제:root",
"accountId": "삭제",
"accessKeyId": "삭제",
"sessionContext": {
"sessionIssuer": {},
"webIdFederationData": {},
"attributes": {
"creationDate": "2021-11-21T03:48:46Z",
"mfaAuthenticated": "true"
}
}
},
"eventTime": "2021-11-21T09:36:59Z",
"eventSource": "ec2.amazonaws.com",
"eventName": "AuthorizeSecurityGroupIngress",
"awsRegion": "ap-northeast-2",
"sourceIPAddress": "삭제",
"userAgent": "EC2ConsoleFrontend, aws-internal/3 aws-sdk-java/1.12.100 Linux/5.4.156-94.273.amzn2int.x86_64 OpenJDK_64-Bit_Server_VM/25.312-b07 java/1.8.0_312 vendor/Oracle_Corporation cfg/retry-mode/standard",
"requestParameters": {
"groupId": "sg-0662dbe79f96335ef",
"ipPermissions": {
"items": [
{
"ipProtocol": "tcp",
"fromPort": 44,
"toPort": 44,
"groups": {},
"ipRanges": {
"items": [
{
"cidrIp": "0.0.0.0/0",
"description": "test"
}
]
},
"ipv6Ranges": {},
"prefixListIds": {}
}
]
}
},
"responseElements": {
"requestId": "f96a54fa-1e3a-40a4-b15b-f86179c0c7b0",
"_return": True,
"securityGroupRuleSet": {
"items": [
{
"groupOwnerId": "354913817145",
"groupId": "sg-0662dbe79f96335ef",
"securityGroupRuleId": "sgr-031a7a52442ddd4a4",
"description": "test",
"isEgress": False,
"ipProtocol": "tcp",
"fromPort": 44,
"toPort": 44,
"cidrIpv4": "0.0.0.0/0"
}
]
}
},
"requestID": "f96a54fa-1e3a-40a4-b15b-f86179c0c7b0",
"eventID": "e1b65529-91d1-4c00-8ed5-ea866e3ddac1",
"readOnly": False,
"eventType": "AwsApiCall",
"managementEvent": True,
"recipientAccountId": "354913817145",
"eventCategory": "Management"
}
event2 = {
"eventVersion": "1.08",
"userIdentity": {
"type": "IAMUser",
"principalId": "삭제",
"arn": "arn:aws:iam::삭제:user/삭제",
"accountId": "삭제",
"accessKeyId": "삭제",
"userName": "삭제",
"sessionContext": {
"sessionIssuer": {},
"webIdFederationData": {},
"attributes": {
"creationDate": "2021-11-21T10:39:50Z",
"mfaAuthenticated": "false"
}
}
},
"eventTime": "2021-11-21T10:42:10Z",
"eventSource": "ec2.amazonaws.com",
"eventName": "AuthorizeSecurityGroupIngress",
"awsRegion": "ap-northeast-2",
"sourceIPAddress": "삭제",
"userAgent": "EC2ConsoleFrontend, aws-internal/3 aws-sdk-java/1.12.100 Linux/5.4.156-94.273.amzn2int.x86_64 OpenJDK_64-Bit_Server_VM/25.312-b07 java/1.8.0_312 vendor/Oracle_Corporation cfg/retry-mode/standard",
"requestParameters": {
"groupId": "sg-0662dbe79f96335ef",
"ipPermissions": {
"items": [
{
"ipProtocol": "tcp",
"fromPort": 6767,
"toPort": 6767,
"groups": {},
"ipRanges": {
"items": [
{
"cidrIp": "0.0.0.0/0",
"description": "test22"
}
]
},
"ipv6Ranges": {},
"prefixListIds": {}
}
]
}
},
"responseElements": {
"requestId": "ae46129c-4fac-4617-bf68-e8f93ecf9921",
"_return": True,
"securityGroupRuleSet": {
"items": [
{
"groupOwnerId": "354913817145",
"groupId": "sg-0662dbe79f96335ef",
"securityGroupRuleId": "sgr-0a0e715d099eb7f14",
"description": "test22",
"isEgress": False,
"ipProtocol": "tcp",
"fromPort": 6767,
"toPort": 6767,
"cidrIpv4": "0.0.0.0/0"
}
]
}
},
"requestID": "ae46129c-4fac-4617-bf68-e8f93ecf9921",
"eventID": "a2dc7f85-86a1-410f-8503-f94922f8334e",
"readOnly": False,
"eventType": "AwsApiCall",
"managementEvent": True,
"recipientAccountId": "354913817145",
"eventCategory": "Management"
}
def Send_Message(slack_message):
req = requests.post(HOOK_URL, data = json.dumps(slack_message), headers={'Content-Type': 'application/json'})
def event_set(event):
data = event
accountId = (data['userIdentity']['accountId'])
sourceIP = (data['sourceIPAddress'])
awsRegion = (data['awsRegion'])
eventTime =(data['eventTime'])
groupId = (data['requestParameters']['groupId'])
principalId = (data['userIdentity']['principalId'])
arn = (data['userIdentity']['arn'])
port = (data['requestParameters']['ipPermissions']['items'][0]['toPort'])
protocol = (data['requestParameters']['ipPermissions']['items'][0]['ipProtocol'])
ipv4 = (data['requestParameters']['ipPermissions']['items'][0]['ipRanges']['items'][0]['cidrIp'])
ipv6 = (data['requestParameters']['ipPermissions']['items'][0]['ipv6Ranges'])
try:
description = (data['requestParameters']['ipPermissions']['items'][0]['ipRanges']['items'][0]['description'])
except KeyError as e:
description = "None"
IP_Port_Checker(data, arn, principalId, accountId, sourceIP, awsRegion, eventTime, groupId, protocol, port, description, ipv4, ipv6)
def IP_Port_Checker(data, arn, principalId, accountId, sourceIP, awsRegion, eventTime, groupId, protocol, port, description, ipv4, ipv6):
# if 'oneid' in arn:
# Username = principalId.split(':')[1]
# else:
username = arn.split('/')[1]
#notice = ("<@>님, 계정 리전의 에 대해 삭제 혹은 출발지 지정 바랍니다." .format(Username, accountId_list.accountId_find(accountId), awsRegion, groupId))
if (port not in [80, 443, 8080]):
if (ipv4 == '0.0.0.0/0' or ipv6 =='::/0' in ipv4):
srcip = 'ANY(0.0.0.0/0)'
Message_data = {
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "AWS SecurityGroup Notice",
"emoji": True
}
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": f"*SecurityGroupID*\n<https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-2#SecurityGroup:groupId={groupId}|{groupId}>"
},
{
"type": "mrkdwn",
"text": f"*UserID*\n{username}"
}
]
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": f"*Information*\n {srcip} -> {port}"
},
{
"type": "mrkdwn",
"text": f"*Protocol*\n{protocol}"
}
]
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": f"*CreateTime*\n{eventTime}"
},
{
"type": "mrkdwn",
"text": f"*Description*\n{description}"
}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Notice*"
}
},
{
"type": "section",
"text": {
"type": "plain_text",
"text": f"누구누구님, AWS {awsRegion} 리전 {groupId}에 대해 삭제 혹은 출발지 지정 부탁 드립니다. 별도 사유가 있는 경우 '완료' 이모지 부탁 드립니다."
}
}
]
}
Send_Message(Message_data)
else:
pass
else:
pass
def lambda_handler(event):
event_set(event)
if __name__ == "__main__":
lambda_handler(event2)