Amazon SNS 주제와 함께 EventBridge 를 사용하여 Security Hub 결과에 대한 사용자 지정된 이메일 알림을 설정하려면 어떻게 해야 하나요?

최종 업데이트 날짜: 2022년 1월 11일

Amazon EventBridge와 Amazon Simple Notification Service(Amazon SNS) 주제를 사용하여 Security Hub 결과에 대한 사용자 지정된 이메일 알림을 설정하고자 합니다.

간략한 설명

다음 해결 방법은 Security Hub 알림을 수신하도록 SNS로 EventBridge를 구성하는 방법을 보여줍니다. EventBridge 규칙에 따라 Amazon SNS는 이벤트 발생 시 주제를 구독한 이메일 주소로 알림을 보냅니다. 생성된 메시지는 서식으로 인해 읽기가 어렵습니다. 하지만 AWS Lambda 함수를 포함하면 SNS 구독자에게 보내기 전에 서식이 개선된 사용자 지정 알림 메시지가 생성됩니다.

사용자 지정된 이메일 알림을 만들려면 다음을 수행합니다.

1.    다음 EventBridge 규칙 대상을 생성합니다.
SNS 주제 및 이메일 구독.
Lambda 함수.

2.    EventBridge 규칙을 생성합니다.

3.    사용자 지정 알림을 수신합니다.

중요: 다음 해결 방법에서는 사용자 지정에 AWS Security Hub 이벤트와 Lambda 함수를 사용합니다. 관련 비용에 대한 자세한 내용은 AWS Security Hub 요금 AWS Lambda 요금을 참조하십시오.

해결 방법

SNS 주제 및 구독 생성

1.    Amazon SNS 콘솔을 엽니다.

2.    탐색 창에서 주제를 선택합니다.

3.    주제 생성을 선택하십시오.

4.    세부 정보 섹션에서 유형에 대해 표준을 선택합니다.

5.    이름에 주제 이름을 입력합니다.

6.    [주제 생성]을 선택합니다.

7.    생성된 주제에서 [구독 생성]을 선택합니다.

8.    [주제 ARN]의 경우 자동으로 채워지지 않았다면 생성한 주제의 Amazon 리소스 이름(ARN)을 선택합니다.

9.    [프로토콜]에 [이메일]을 입력합니다.

10.    [엔드포인트]에 SNS 알림을 받으려는 이메일 주소를 입력합니다.

11.    [구독 생성]을 선택합니다.

중요: 구독을 [PendingConfirmation] 상태에서 [Confirmed] 상태로 전환하려면 구독자에게 전송된 확인 이메일에서 구독을 확인해야 합니다.

참고: (선택 사항) 인증된 구독을 생성하여 주제에 대한 구독 취소 작업을 방지할 수 있습니다.

Lambda 함수 생성

JSON 콘텐츠에서 원하는 정보를 추출하고 Amazon SNS에 사용자 지정된 메시지를 게시하는 Lambda 함수를 생성합니다.

1.    Lambda 콘솔을 엽니다.

2.    탐색 창에서 함수를 선택합니다.

3.    [함수 생성]을 선택합니다.

4.    새로 작성을 선택합니다.

5.    함수 이름에 함수 이름을 입력합니다.

6.    [런타임]을 선택한 다음 [Python 3.9]를 선택합니다.

7.    [아키텍처]의 경우 [x86_64]를 선택합니다.

8.    [기본 실행 역할 변경]을 확장합니다.

9.    [실행 역할]에 대해 [AWS 정책 템플릿에서 새 역할 생성]을 선택합니다.

10.    역할 이름에 해당 역할의 이름을 입력합니다.

11.    [정책 템플릿]의 경우 [Amazon SNS 게시 정책]을 선택합니다.

12.    [함수 생성]을 선택합니다.

13.    함수가 생성된 후 코드 소스(Code source) 섹션에 다음 코드를 붙여넣습니다. 

import json
import boto3

sns = boto3.client('sns')

def lambda_handler(event, context):
    
    #Extract details from JSON event
    detailType= event["detail-type"]
    region = event["region"]
    accountId = event["account"] 
    
    #Security Hub Insight Results
    if (detailType == "Security Hub Insight Results"):
        
        action = event["detail"]["actionDescription"]
        
        message = "Alert: %s in %s for account: %s\n Action description: %s" % (detailType, region,accountId,action)
    
    elif  ("Security Hub Findings" in detailType):
        
        finding = event["detail"]["findings"][0] 
        findingTime = finding["FirstObservedAt"]
        findingType = finding["Types"][0]
        findingDescription = finding["Description"]
        remediation = finding["Remediation"]["Recommendation"]["Text"]
        
        #Security Hub Findings - Custom finding
        if(detailType == "Security Hub Findings - Custom"):
            complianceStatus = finding["Compliance"]["Status"]
            severity = finding["Severity"]["Label"]
            remediationUrl = finding["Remediation"]["Recommendation"]["Url"]
            
            message = "Alert: %s in %s for account: %s\n\nFinding regarding: [%s] %s\n Severity: %s\nDescription: %s\nFirst observed at: %s\n%s: %s" % (detailType, region, accountId, complianceStatus, findingType, 
            severity, findingDescription, findingTime, remediation, remediationUrl)
        
        #Security Hub Findings - Imported finding
        else:
            message = "Alert: %s in %s for account: %s\n\nFinding regarding: %s\nFirst observed at: %s\nRemediation recommendation: %s" % (detailType, region, accountId, findingDescription,findingTime, remediation)
    
    #AWS API Call via CloudTrail finding
    elif (detailType == "AWS API Call via CloudTrail"):
        
        time = event["detail"]["eventTime"]
        eventName = event["detail"]["eventName"]
        requestParameters = event["detail"]["requestParameters"]
        
        message = "Alert: %s in %s for account: %s at time: %s\n\n Event: %s \n Request parameters: %s" % (detailType, region, accountId, time, eventName, requestParameters)
        
        
    #If the event doesn't match any of the above, return the event    
    else:
        message = str(event)
    
    response = sns.publish(
            TopicArn = "arn:aws:sns:eu-west-x:xxxxxxxxxxxx:test",
            Message = message
            )
    
    return {
      'statusCode': 200,
      'body': json.dumps('Success!')
}

참고: 앞의 코드는 모든 Security Hub 알림 메시지를 사용자 지정하고 서식을 재지정합니다. TopicArn("arn:aws:sns:REGION:ACCOUNT_ID:SecurityHubFindings")을 주제 ARN으로 바꿉니다. eu-west-x:xxxxxxxxxxxx를 계정 ID로 바꿉니다. 

14.    함수 코드를 저장하려면 [배포]를 선택합니다.

이 함수는 기본 Security Hub 이벤트를 가져와 읽기 쉬운 서식으로 서식을 다시 지정합니다. 다음은 예제 메시지입니다.

예제 1: Security Hub 인사이트 결과

기본값:

{"version": "0", "id": "ac844908-d14e-05b1-4b7b-836d85110e26", "detail-type": "Security Hub Insight Results", "source": "aws.securityhub", "account": "123456789012", "time": "2019-04-11T21:31:57Z", "region": "us-east-1", "resources": ["arn:aws:securityhub:us-east-1:123456789012:action/custom/slackMessaging"], "detail": {"actionName": "SendToSlack", "actionDescription": "Send Findings to Slack", "insightName": "5. AWS users with the most suspicious activity", "insightArn": "arn:aws:securityhub:::insight/securityhub/default/9", "resultType": "ResourceAwsIamAccessKeyUserName", "insightResults": [{"Admin": 7}, {"DenySlr_UI_User": 1}]}}

사용자 지정:

Alert: Security Hub Insight Results in us-east-1 for account: 123456789012
Action description: Send Findings to Slack

예제 2: Security Hub 결과 - 사용자 지정 작업

기본값:

{ "version": "0", "id": "e215f5c7-a866-e0cd-6d11-fc7ecf97e381", "detail-type": "Security Hub Findings - Custom Action", "source": "aws.securityhub", "account": "123456789012", "time": "2019-04-11T22:06:13Z", "region": "us-east-1", "resources": ["arn:aws:securityhub:us-east-1:123456789012:action/custom/slackMessaging"], "detail": { "actionName": "SendToSlack", "actionDescription": "Send Findings to Slack", "findings": [{ "SchemaVersion": "2018-10-08", "Id": "arn:aws:securityhub:us-east-1:123456789012:subscription/cis-aws-foundations-benchmark/v/1.2.0/1.12/finding/17932c44-6d58-4b3c", "ProductArn": "arn:aws:securityhub:us-east-1::product/aws/securityhub", "GeneratorId": "arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/1.12", "AwsAccountId": "123456789012", "Types": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"], "FirstObservedAt": "2018-12-02T05:06:34.874Z", "LastObservedAt": "2019-04-11T18:07:10.995Z", "CreatedAt": "2018-12-02T05:06:34.874Z", "UpdatedAt": "2019-04-11T18:26:20.631Z", "Severity": { "Product": 0, "Normalized": 0 }, "Title": "1.12 Ensure no root account access key exists", "Description": "The root account is the most privileged user in an AWS account...", "Remediation": { "Recommendation": { "Text": "For directions on how to fix this issue, please consult the AWS Security Hub CIS documentation.", "Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards.html#securityhub-standards-checks-1.12" } }, "ProductFields": { "StandardsGuideArn": "arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0", "StandardsGuideSubscriptionArn": "arn:aws:securityhub:us-east-1:123456789012:subscription/cis-aws-foundations-benchmark/v/1.2.0", "RuleId": "1.12", "RecommendationUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards.html#securityhub-standards-checks-1.12", "RecordState": "ACTIVE", "aws/securityhub/FindingId": "arn:aws:securityhub:us-east-1::product/aws/securityhub/arn:aws:securityhub:us-east-1:123456789012:subscription/cis-aws-foundations-benchmark/v/1.2.0/1.12/finding/17932c44-6d58-4b3c", "aws/securityhub/SeverityLabel": "INFORMATIONAL", "aws/securityhub/ProductName": "Security Hub", "aws/securityhub/CompanyName": "AWS" }, "Resources": [{ "Type": "AwsAccount", "Id": "AWS::::Account:123456789012", "Partition": "aws", "Region": "us-east-1" }], "Compliance": { "Status": "PASSED" }, "RecordState": "ACTIVE", "WorkflowState": "NEW" }, { "SchemaVersion": "2018-10-08", "Id": "arn:aws:securityhub:us-east-1:123456789012:subscription/cis-aws-foundations-benchmark/v/1.2.0/2.8/finding/5d6b42d8-122b-4cdf-8498-e045752e170c", "ProductArn": "arn:aws:securityhub:us-east-1::product/aws/securityhub", "GeneratorId": "arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0/rule/2.8", "AwsAccountId": "123456789012", "Types": ["Software and Configuration Checks/Industry and Regulatory Standards/CIS AWS Foundations Benchmark"], "FirstObservedAt": "2019-01-05T05:21:44.990Z", "LastObservedAt": "2019-04-11T18:26:12.510Z", "CreatedAt": "2019-01-05T05:21:44.990Z", "UpdatedAt": "2019-04-11T18:26:12.510Z", "Severity": { "Product": 0, "Normalized": 0 }, "Title": "2.8 Ensure rotation for customer created CMKs is enabled", "Description": "AWS Key Management Service (KMS) allows customers to rotate the backing key...", "Remediation": { "Recommendation": { "Text": "For directions on how to fix this issue, please consult the AWS Security Hub CIS documentation.", "Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards.html#securityhub-standards-checks-2.8" } }, "ProductFields": { "StandardsGuideArn": "arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.2.0", "StandardsGuideSubscriptionArn": "arn:aws:securityhub:us-east-1:123456789012:subscription/cis-aws-foundations-benchmark/v/1.2.0", "RuleId": "2.8", "RecommendationUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/securityhub-standards.html#securityhub-standards-checks-2.8", "RecordState": "ACTIVE", "aws/securityhub/FindingId": "arn:aws:securityhub:us-east-1::product/aws/securityhub/arn:aws:securityhub:us-east-1:123456789012:subscription/cis-aws-foundations-benchmark/v/1.2.0/2.8/finding/5d6b42d8-122b-4cdf-8498-e045752e170c", "aws/securityhub/SeverityLabel": "INFORMATIONAL", "aws/securityhub/ProductName": "Security Hub", "aws/securityhub/CompanyName": "AWS" }, "Resources": [{ "Type": "AwsAccount", "Id": "AWS::::Account:123456789012", "Partition": "aws", "Region": "us-east-1" }], "Compliance": { "Status": "PASSED" }, "RecordState": "ACTIVE", "WorkflowState": "NEW" }] } }

사용자 지정:

Alert: Security Hub Findings - Custom Action in us-east-1 for account: 123456789012

Finding regarding: The root account is the most privileged user in an AWS account...
First observed at: 2018-12-02T05:06:34.874Z
Remediation recommendation: For directions on how to fix this issue, please consult the AWS Security Hub CIS documentation.

예제 3: Security Hub 결과 - 가져옴

기본값:

{ "version": "0", "id": "8e5622f9-d81c-4d81-612a-9319e7ee2506", "detail-type": "Security Hub Findings - Imported", "source": "aws.securityhub", "account": "123456789012", "time": "2019-04-11T21:52:17Z", "region": "us-west-2", "resources": ["arn:aws:securityhub:us-west-2::product/aws/macie/arn:aws:macie:us-west-2:123456789012:integtest/trigger/6294d71b927c41cbab915159a8f326a3/alert/f2893b211841"], "detail": { "findings": [{ "SchemaVersion": "2018-10-08", "Id": "arn:aws:macie:us-west-2:123456789012:integtest/trigger/6214d71b927c41cbab015159a8f316a3/alert/f2893b211841467198cc1201e9031ee4", "ProductArn": "arn:aws:securityhub:us-west-2::product/aws/macie", "GeneratorId": "arn:aws:macie:us-west-2:123456789012:integtest/trigger/6214d71b927c41cbab015159a8f316a3", "AwsAccountId": "123456789012", "Types": ["Sensitive Data Identifications/Passwords/Google Suite Two-factor backup codes in S3"], "FirstObservedAt": "2019-04-11T21:52:15.900Z", "LastObservedAt": "2019-04-11T21:52:15.900Z", "CreatedAt": "2019-04-11T21:52:15.900Z", "UpdatedAt": "2019-04-11T21:52:15.900Z", "Severity": { "Product": 6, "Normalized": 15 }, "Confidence": 5, "Title": "Google Suite Two-Factor Backup Codes uploaded to S3", "Description": "Google Suite two-factor backup codes uploaded to S3....", "Remediation": { "Recommendation": { "Text": "v2 Release" } }, "ProductFields": { "rule-arn": "arn:aws:macie:us-west-2:123456789012:trigger/6214d71b927c41cbab015159a8f316a3", "tags:0": "DATA_COMPLIANCE", "tags:1": "BASIC_ALERT", "themes:0/theme": "google_two_factor_backup", "themes:0/count": "1", "dlpRisk:0/risk": "8", "dlpRisk:0/count": "1", "owner:0/name": "vchin", "owner:0/count": "1", "aws/securityhub/FindingId": "arn:aws:securityhub:us-west-2::product/aws/macie/arn:aws:macie:us-west-2:123456789012:integtest/trigger/6214d71b927c41cbab015159a8f316a3/alert/f2893b211841467198cc1201e9031ee4", "aws/securityhub/SeverityLabel": "LOW", "aws/securityhub/ProductName": "Macie", "aws/securityhub/CompanyName": "Amazon" }, "Resources": [{ "Type": "AwsS3Bucket", "Id": "arn:aws:s3:::test-bucket-12", "Partition": "aws", "Region": "us-west-2" }], "RecordState": "ACTIVE", "WorkflowState": "NEW" }] } }

사용자 지정:

Alert: Security Hub Findings - Imported in us-west-2 for account: 123456789012

Finding regarding: Google Suite two-factor backup codes uploaded to S3....
First observed at: 2019-04-11T21:52:15.900Z
Remediation recommendation: v2 Release

예제 4 - CloudTrail을 통한 AWS API 호출

기본값:

{"version": "0", "id": "b34c4525-95f0-8dd1-cd9e-9fc5be10039e", "detail-type": "AWS API Call via CloudTrail", "source": "aws.securityhub", "account": "123456789012", "time": "2021-12-10T10:47:54Z", "region": "eu-west-1", "resources": [], "detail": {"eventVersion": "1.08", "userIdentity": {"type": "AssumedRole", "principalId": "AROATGMYP4FKHTE5RKJC3", "arn": "arn:aws:sts::123456789012", "accountId": "123456789012", "accessKeyId": "ASIATGMYXXFKNHWOYQF7", "sessionContext": {"sessionIssuer": {"type": "Role", "principalId": "AROATGMYP4FKHX5RKJC3", "arn": "arn:aws:iam::123456789012:role/Admin", "accountId": "123456789012", "userName": "Admin"}, "webIdFederationData": {}, "attributes": {"creationDate": "2021-12-10T10:08:16Z", "mfaAuthenticated": "false"}}}, "eventTime": "2021-12-10T10:47:54Z", "eventSource": "securityhub.amazonaws.com", "eventName": "BatchUpdateFindings", "awsRegion": "eu-west-1", "sourceIPAddress": "54.240.197.20", "userAgent": "aws-internal/3 aws-sdk-java/1.12.112 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": {"Workflow": {"Status": "NEW"}, "FindingIdentifiers": [{"Id": "arn:aws:securityhub:eu-west-1:123456789012:subscription/cis-aws-foundations-benchmark/v/1.2.0/2.5/finding/2fd7f0dd-1088-44c5-bbe1-9c8a0ddce035", "ProductArn": "arn:aws:securityhub:eu-west-1::product/aws/securityhub"}]}, "responseElements": {"UnprocessedFindings": [], "ProcessedFindings": [{"Id": "arn:aws:securityhub:eu-west-1:123456789012:subscription/cis-aws-foundations-benchmark/v/1.2.0/2.5/finding/2fd7f0dd-1088-44c5-bbe1-9c8a0ddce035", "ProductArn": "arn:aws:securityhub:eu-west-1::product/aws/securityhub"}]}, "requestID": "fd52e76e-282f-47c7-a7bc-b9a1e1ca2cdd", "eventID": "433b8e9c-cf08-4909-adf7-ea0c548459ad", "readOnly": "False", "eventType": "AwsApiCall", "managementEvent": "True", "recipientAccountId": "123456789012", "eventCategory": "Management"}}

사용자 지정:

Alert: AWS API Call via CloudTrail in eu-west-1 for account: 123456789012 at time: 2021-12-10T10:47:32Z

Event: BatchUpdateFindings
Request parameters: {'Workflow': {'Status': 'NOTIFIED'}, 'FindingIdentifiers': [{'Id': 'arn:aws:securityhub:eu-west-x:xxxxxxxxxxxx:subscription/cis-aws-foundations-benchmark/v/1.2.0/2.5/finding/2fd7f0dd-1088-44c5-bbe1-9c8a0ddce035', 'ProductArn': 'arn:aws:securityhub:eu-west-1::product/aws/securityhub'}]}

참고: 사용 사례에 더욱 적합하도록 각 Security Hub 결과 유형에 대한 메시지를 편집할 수 있습니다.

EventBridge 규칙 생성 및 구성

1.    EventBridge 콘솔을 엽니다.

2.    [규칙 생성]을 선택합니다.

3.    규칙의 [이름]을 입력합니다. [설명]을 입력할 수도 있습니다(선택 사항).

4.    [패턴 정의]에서 [이벤트 패턴]을 선택합니다.

5.    이벤트 일치 패턴(Event matching pattern)에서 서비스별 사전 정의된 패턴(Pre-defined pattern by service)을 선택합니다.

6.    [서비스 공급자]에서 [AWS]를 선택합니다.

7.    [서비스 이름]에서 [Security Hub]를 선택합니다.

8.    [이벤트 유형]에서 [모든 이벤트]를 선택합니다.

참고: 모든 이벤트가 아닌 특정 이벤트에 대한 알림을 구성할 수도 있습니다. Lambda 함수는 모든 이벤트를 더 읽기 쉬운 서식으로 다시 서식을 지정하도록 구성됩니다.

9.    [이벤트 버스 선택] 섹션에서 [AWS 기본 이벤트 버스]를 선택합니다.

10.    [대상 선택]의 [대상] 메뉴에서 [Lambda 대상]을 선택합니다.

11.    이전에 생성한 Lambda 함수를 선택합니다.

사용자 지정 알림 수신

구성된 이벤트 중 하나가 발생하면 no-reply@sns.amazonaws.com의 이메일을 통해 사용자 지정 알림을 수신합니다.