2023. 3. 21. 18:41ใAWS
AWS Health Dashboard๋?
AWS ์๋น์ค๋ AWS ๊ณ์ ์ ์ํฅ์ ์ฃผ๋ ์ด๋ฒคํธ๋ฅผ ์๋ ค์ค๋ค.
AWS Health Dashboard๋ ๋ชจ๋ AWS ๊ณ ๊ฐ์ด ์ด๊ธฐ ์ค์ ๋ฐ ๋น์ฉ ์์ด ์ด์ฉํ ์ ์๋ค.
Account health/Organization health๋ PHD(Personal Health Dashboard)๋ผ๊ณ ๋ ํ๋ค. Service Health Dashboard์์๋ ์ผ๋ฐ์ ์ธ AWS ์๋น์ค ์ํ๋ฅผ ํ์ธํ ์ ์๊ณ , Personal Health Dashboard์์๋ ๊ตฌ์ฑ๋ ํน์ AWS ํ๊ฒฝ์ ๋ํด ๋ถ๋ช ํ ์๋ฆผ์ ๋ฏธ๋ฆฌ ์ ๊ณตํ๋ค.
โ๏ธ To-Be Architecture
AWS Health์์ ์๋ ค์ฃผ๋ ์๋ฆผ์ ๋์น์ง ์๋๋ก Amazon EventBridge, AWS Lambda๋ฅผ ํตํด ์ด๋ฒคํธ ์ ๋ณด๋ฅผ Airtable์ ์ ์ฅํ์ฌ ์ผ์ ์๊ฐํ ๋ฐ ๊ด๋ฆฌํด ๋ณด์!
AWS Health์์ event๊ฐ ๋ฐ์ํ๋ฉด python์ผ๋ก ์์ฑ๋ Lambda ํจ์๊ฐ ์คํ๋๋๋ก EventBridge๋ฅผ ๊ตฌ์ฑํ๋ค. Lambda ํจ์๋ Airtable์ API๋ฅผ ์ด์ฉํ์ฌ Health event ์ ๋ณด๋ฅผ Airtable์ ํ ์ด๋ธ์ ์ ์ฅํ๋ค.
1. Airtable ๊ตฌ์ฑ
- Name (Single line text)
- createdAt (Created time)
- Account (Single line text)
- Service (Single line text)
- eventTypeCategory (Single select [accountNotification, issue, scheduledChange])
- description (Long text)
- startTime (Date)
- endTime (Date)
- affectedEntities (Single line text)
AWS Health์์ ๋ฐ์ํ ์ด๋ฒคํธ๋ฅผ Airtable์ ์ ์ฅํ๊ธฐ ์ํด ์์ ๊ฐ์ด base๋ฅผ ๊ตฌ์ฑํ์๋ค.
์ base์ ์ด๋ฒคํธ ๊ด๋ จ ๋ ์ฝ๋๋ฅผ ๋ฑ๋กํ๊ธฐ ์ํด Airtable์์ ์ ๊ณตํ๋ ์๋ API๋ฅผ ์ด์ฉํ ๊ฒ์ด๋ค.
⇒ [Airtable Developers Web API Docs] Create records
์ธ์ฆ์ ์ํ access token ๋ฐ๊ธ์ ๋ค์์ ์ฐธ์กฐํ์.
⇒ [Airtable Developers Web API Docs] Personal access tokens
์ก์ธ์ค ํ ํฐ, base ID, ํ ์ด๋ธ๋ช ์ ํ์ธํ์.
2. AWS Secrets Manager ๊ตฌ์ฑ
Lambda์ hard-coding์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ฒ์ ํผํ๊ธฐ ์ํด AWS Secrets Manager๋ฅผ ์ด์ฉํด ๋ณด์.
1์์ ํ์ธํ Access Token, Base ID, ํ ์ด๋ธ๋ช ์ AWS Secrets Manager๋ฅผ ํตํด ์ ์ฅํ๋ค.
Secret ์์ฑ์ ์๋ฃํ๋ฉด AWS๋ ํด๋น Secret์ ์ ์ฅ๋ ๊ฐ์ ๋ถ๋ฌ์ค๋ ์ฝ๋๋ ์ ๊ณตํด ์ค๋ค. 3์์๋ ์๋ ์ฝ๋๋ฅผ ์ด์ฉํ์ฌ Lambda ํจ์๋ฅผ ๊ตฌ์ฑํ ๊ฒ์ด๋ค.
3. Lambda ํจ์ ๊ตฌ์ฑ
3-1. lambda_function.py
์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ ํจ์ ์ฝ๋์ ๋ฉ์๋
# lambda_function.py
import create_records
def lambda_handler(event, context):
return create_records.create_records(event)
3-2. create_records.py
Airtable API๋ฅผ ์ด์ฉํ์ฌ ์ํ๋ base์ ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค. Airtable API๋ฅผ ์ด์ฉํ๊ธฐ ์ํด requests ๋ชจ๋์ ์ด์ฉํ๋ค. request ๋ชจ๋์ Lambda์ ์ ๋ก๋ํ๊ธฐ ์ํด ์๋ ๋งํฌ๋ฅผ ์ฐธ์กฐํ์๋ค.
⇒ AWS Docs: .zip ํ์ผ ์์นด์ด๋ธ๋ฅผ ์ฌ์ฉํ์ฌ Python Lambda ํจ์ ๋ฐฐํฌ
# create_records.py
import requests
import json
import get_secret
def create_records(event):
endTime = event["detail"].get("endTime")
affectedEntities = None
if event["detail"].get("affectedEntities"):
affectedEntities = event["detail"]["affectedEntities"][0]["entityValue"]
fields = {
"Name": event["detail"]["eventTypeCode"],
"Account": event["account"],
"Service": event["detail"]["service"],
"eventTypeCategory": event["detail"]["eventTypeCategory"],
"description": event["detail"]["eventDescription"][0]["latestDescription"],
"startTime": event["detail"]["startTime"],
"endTime": endTime,
"affectedEntities": affectedEntities
}
secrets = json.loads(get_secret.get_secret())
url = f"<https://api.airtable.com/v0/{secrets['baseID']}/{secrets['tableName']}>"
authToken = secrets["authToken"]
headers = {
'Authorization': 'Bearer ' + authToken,
'Content-Type': 'application/json'
}
payload = {
"records":[
{
"fields": fields
}
]
}
res = requests.post(url, headers=headers, json=payload)
return(res.text)
3-3. get_secret.py
boto3์ ์ด์ฉํ์ฌ AWS Secrets Manager์ ์ ์ฅํ ๊ฐ์ ๊ฐ์ ธ์จ๋ค.
# get_secret.py
import boto3
from botocore.exceptions import ClientError
def get_secret():
secret_name = "hyeonju-airtable-secrets"
region_name = "ap-northeast-2"
# Create a Secrets Manager client
session = boto3.session.Session()
client = session.client(
service_name='secretsmanager',
region_name=region_name
)
try:
get_secret_value_response = client.get_secret_value(
SecretId=secret_name
)
except ClientError as e:
raise e
# Decrypts secret using the associated KMS key.
secret = get_secret_value_response['SecretString']
return secret
4. IAM Policy ์ถ๊ฐ
Secrets Manager์ ์ ์ฅ๋ ๊ฐ์ ์กฐํํ๊ธฐ ์ํด Lambda์ ์ฐ๊ฒฐ๋์ด ์๋ IAM Role์ secretsmanager:GetSecretValue๋ฅผ ํ์ฉํ๋ Policy๋ฅผ ์ถ๊ฐํ๋ค.
(Lambda ํจ์์ ์ฐ๊ฒฐ๋์ด ์๋ Execution Role์ [AWS Lambda ์ฝ์ > Configuration ํญ > Permissions ์น์ ]์์ ํ์ธํ ์ ์๋ค.)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:ap-northeast-2:############:secret:{ secret-name }-######"
}
]
}
5. ์ค๊ฐ ์ ๊ฒ
{
"version": "0",
"id": "1######-0###-2###-2d84-#########",
"detail-type": "AWS Health Event",
"source": "aws.health",
"account": "#########",
"time": "2022-11-02T07:30:00Z",
"region": "ap-northeast-2",
"resources": [
"##############"
],
"detail": {
"eventArn": "arn:aws:health:ap-northeast-2::event/CLOUDFORMATION/AWS_CLOUDFORMATION_OPERATIONAL_NOTIFICATION/AWS_CLOUDFORMATION_OPERATIONAL_NOTIFICATION_##############################",
"service": "CLOUDFORMATION",
"eventTypeCode": "AWS_CLOUDFORMATION_OPERATIONAL_NOTIFICATION",
"eventTypeCategory": "accountNotification",
"startTime": "Wed, 2 Nov 2022 07:30:00 GMT",
"eventDescription": [
{
"language": "en_US",
"latestDescription": "English follows Korean | ํ๊ตญ์ด๋ฒ์ ๋ค์ ์์ด๋ฒ์ ์ด ์์ต๋๋ค \\n\\n์์ฒด ๊ด๋ฆฌํ AWS CloudFormation StackSets ๋ก์ ์จ๋ณด๋ฉ์ ๊ฐ์ํํ๊ธฐ ์ํด ๋ฐฑ์๋ ๊ถํ ์ ์ฑ
์ ์
๋ฐ์ดํธํ์ต๋๋ค. 2022๋
10์ 31์ผ๋ถํฐ ์์ฒด ๊ด๋ฆฌํ StackSets ๋ฅผ ์ฌ์ฉ ์์ํ๊ธฐ ์ํ ์ ์ ์กฐ๊ฑด์ผ๋ก AWSCloudFormationStackSetExecutionRole ๋ด sns* ๊ถํ์ด ๋ ์ด์ ํ์ํ์ง ์์ต๋๋ค.\\n\\nSNS ์์์ ์ฌ์ฉํ ๊ณํ์ด ์์ผ์ ๊ณ ๊ฐ์ AWSCloudFormationStackSetExecutionRole ์์ ๊ธฐ์กด sns* ๊ถํ์ ์ ๊ฑฐํด๋ ๋ฌด๋ฐฉํฉ๋๋ค. ์ด ๊ถํ์ Amazon SNS ์์์ ํ๋ก๋น์ ๋ํ ๋๋ง ํ์ํฉ๋๋ค.\\n\\nStackSets๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ํด๋น ๊ณ์ ๋ด ์ฌ์ฉ์ ๋ง์ถคํ ๊ด๋ฆฌ์ ์ญํ ์ ์์๋ฐ์ ์ ์๋ AWSCloudFormationStacksetExecutionRole์ด๋ผ๋ ์๋น์ค ์ญํ ์ ์์ฑํด์ผ ํฉ๋๋ค. ์ด์ ์๋ StackSets๊ฐ ์ฌ์ฉ์๋ฅผ ๋์ ํ์ฌ ์์์ ๊ด๋ฆฌํ๊ณ ํ๋ก๋น์ ๋ํ ์ ์๋๋ก ํ๊ธฐ ์ํด AWS CloudFormationStackSetExecutionRole์ ๋ํ sns: *, s3: * ๋ฐ cloudformation: * ๊ถํ์ ์ ๊ณตํด์ผ ํ์ต๋๋ค. ์ด์ ๋ StackSets๊ฐ ์๋ํ๊ธฐ ์ํด AWSCloudFormationStackSetExecutionRole๋ด sns: * ๊ถํ์ด ๋ ์ด์ ํ์์กฐ๊ฑด์ด ์๋๋๋ค. AWSCloudFormationStackSetExecutionRole์๋ ์ฌ์ ํ s3: * ๋ฐ cloudformation: * ๊ถํ์ด ํ์ํ ์ ์ฐธ๊ณ ๋ถํ๋๋ฆฝ๋๋ค.\\n\\n์ฌ์ฉ์ ์ค๋ช
์ [1] ์์ StackSets์ ์์ฒด ๊ด๋ฆฌํ ๊ถํ์ ๋ถ์ฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์ธํ ์์๋ณด์ค ์ ์์ต๋๋ค.\\n\\n์ง๋ฌธ์ด๋ ์ฐ๋ ค ์ฌํญ์ด ์๋ ๊ฒฝ์ฐ, AWS Support [2] ์ ๋ฌธ์ํด์ฃผ์๊ธฐ ๋ฐ๋๋๋ค.\\n\\n[1] <https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-prereqs-self-managed.html\\n[2]> <https://aws.amazon.com/support\\n\\n---\\n\\nWe> have updated our back-end permissions policy to simplify on-boarding to self-managed AWS CloudFormation StackSets. Starting October 31, 2022, AWS CloudFormation StackSets no longer requires sns* permissions in AWSCloudFormationStackSetExecutionRole as a prerequisite for getting started with self-managed StackSets.\\n\\nCustomers not planning to use any SNS resources can safely remove their existing sns* permissions from their AWSCloudFormationStackSetExecutionRole. These are only required when provisioning Amazon SNS resources.\\n\\nStackSets requires you to create a service role named AWSCloudFormationStackSetExecutionRole that trusts the customized administration role for each target account. Previously, you needed to provide sns:*, s3:*, and cloudformation:* permissions to AWSCloudFormationStackSetExecutionRole as prerequisites to allow StackSets to manage and provision resources on your behalf. Now, StackSets has removed the explicit need for sns:* permissions as prerequisites in AWSCloudFormationStackSetExecutionRole. Please note, you will still need to provide s3:* and cloudformation:* permissions in AWSCloudFormationStackSetExecutionRole.\\n\\nLearn more about how to grant self-managed permissions for StackSets in the User Guide [1].\\n\\nIf you have any questions or concerns, please reach out to AWS Support [2].\\n\\n[1] <https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-prereqs-self-managed.html\\n[2]> <https://aws.amazon.com/support>"
}
],
"affectedEntities": [
{
"entityValue": "##############"
}
]
}
}
AWS Health Event์ ํ์์ ์์ ๊ฐ๋ค.
3์์ ๊ตฌ์ฑํ Lambda ํจ์๋ฅผ ํ ์คํธํด ๋ณด์. Test event์ Event JSON์ ์ ๋ด์ฉ์ ๋ฃ๊ณ test๋ฅผ ์ํํ์ ๋, ๋ชฉํ๋ก ํ๋ base์ ๋ฐ์ดํฐ๊ฐ ์ ์ ๋ ฅ๋๋ฉด ์ฑ๊ณต. ๋ง์ฝ ์๋ฌ๊ฐ ๋ฐ์ํ๊ฑฐ๋ ๋ฐ์ดํฐ๊ฐ ์ ๋ ฅ๋์ง ์์ ๊ฒฝ์ฐ, 1๋ฒ๋ถํฐ ๋์๊ฐ ๋ค์ ์ดํด๋ณด์.
6. EventBridge Rule ์์ฑ
โ ๏ธ ์ฃผ์ โ ๏ธ
EventBrdige Rule์ด ์์ฑ๋ ๋ฆฌ์ ์ ๋ํ aws health event๋ง ์ ์ฉ์ด ๋๋ค.
์ฌ๋ฌ ๋ฆฌ์ ์ Health Event๋ฅผ Airtable๋ก ๋ฐ์๋ณด๊ณ ์ถ์ ๊ฒฝ์ฐ, ๊ฐ ๋ฆฌ์ ์์ ์๋์ ๊ฐ์ EventBridge Rule์ ์์ฑํ์.
- Rule type: Rule with an event pattern (standard rule)
- Event source: AWS events or EventBridge partner events
- Event pattern: Health์์ ๋ฐ์ํ๋ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ ์์ ํ๊ณ ์ถ๊ธฐ ๋๋ฌธ์ ์๋์ ๊ฐ์ Event pattern์ ์ค์ ํ๋ค.
{
"source": ["aws.health"]
}
- Target: 3์์ ์์ฑํ Lambda function์ arn ์ ๋ ฅ
EventBridge๋ฅผ ์์ ๊ฐ์ด ์ค์ ํ๋ฉด Lambda Console์์ ์์ ๊ฐ์ด EventBridge๊ฐ ํธ๋ฆฌ๊ฑฐ ์์ค๋ก ์ถ๊ฐ๋์์ ํ์ธํ ์ ์๋ค.
7. ํ์ธ
AWS Health Dashboard > Event log์์ ํ์ธ๋๋ ์ ๋ณด๊ฐ Airtable ํ ์ด๋ธ์ ์ ์ ์ฅ๋๋์ง ํ์ธํด ๋ณด์.