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)