diff --git a/sam/monitor-lambda/README.md b/sam/monitor-lambda/README.md index e69de29b..a4b23c20 100644 --- a/sam/monitor-lambda/README.md +++ b/sam/monitor-lambda/README.md @@ -0,0 +1,11 @@ +## 目的 +- Lambda監視に必要な`CloudwatchLogs SubscriptionFilter`と`Cloudwatch Alarm`をTerraformで管理しているが、追加や削除対応を開発チーム内で完結させるためLambdaでの管理に移行する。 + - コミュニケーションコストの削減により、双方でより重要なタスクへ時間を割くことができる。 + +## 処理内容 +- 作成時 + - `CloudwatchLogs SubscriptionFilter`と`Cloudwatch Alarm`の既存リソースとconfig内のjsonのキー(lambda関数名)を比較し、差分のみにフィルターしてリソースを作成する。 + +## 懸念点 +- 削除対応時にどうするか + - 別プロジェクトで管理する diff --git a/sam/monitor-lambda/config/mapping.json b/sam/monitor-lambda/config/mapping.json new file mode 100644 index 00000000..7362f369 --- /dev/null +++ b/sam/monitor-lambda/config/mapping.json @@ -0,0 +1,6 @@ +{ + "account_mapping": { + "685339645368": "master", + "650251692423": "development" + } +} diff --git a/sam/monitor-lambda/config/master/lambda.json b/sam/monitor-lambda/config/master/lambda.json new file mode 100644 index 00000000..69b07f09 --- /dev/null +++ b/sam/monitor-lambda/config/master/lambda.json @@ -0,0 +1,5 @@ +{ + "lambda": { + "monitor-waf-regionallimit":{"filter_pattern": "?ERROR ?Exception"} + } +} diff --git a/sam/monitor-lambda/samconfig.toml b/sam/monitor-lambda/config/master/samconfig.toml similarity index 70% rename from sam/monitor-lambda/samconfig.toml rename to sam/monitor-lambda/config/master/samconfig.toml index 7624354e..f7a17bfb 100644 --- a/sam/monitor-lambda/samconfig.toml +++ b/sam/monitor-lambda/config/master/samconfig.toml @@ -4,7 +4,7 @@ version = 0.1 [default] [default.global.parameters] -stack_name = "monitor-lambda" +stack_name = "add-monitor-lambda-resources" [default.build.parameters] cached = true @@ -14,9 +14,14 @@ parallel = true lint = true [default.deploy.parameters] -capabilities = "CAPABILITY_IAM" +capabilities = "CAPABILITY_NAMED_IAM" confirm_changeset = true -resolve_s3 = true +resolve_s3 = false +s3_bucket = "sam-deploy-685339645368" +s3_prefix = "add-monitor-lambda-resources" +region = "ap-northeast-1" +disable_rollback = true +image_repositories = [] [default.package.parameters] resolve_s3 = true diff --git a/sam/monitor-lambda/config/master/template.yaml b/sam/monitor-lambda/config/master/template.yaml new file mode 100644 index 00000000..b9bea7d1 --- /dev/null +++ b/sam/monitor-lambda/config/master/template.yaml @@ -0,0 +1,116 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: Monitor Lambda + +Parameters: + Env: + Type: String + +Globals: + Function: + CodeUri: ../../function/ + Runtime: python3.12 + Architectures: + - arm64 + LoggingConfig: + LogFormat: JSON + Environment: + Variables: + ACCOUNT_ID: !Ref AWS::AccountId + FUNCTION_ARN: + DEFAULT_REGION: !Ref AWS::Region + + +Resources: +########################################################### +# Lambda +########################################################### + AddMonitorLambdaFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: add-monitor-lambda-resources + Handler: handler.lambda_habdler + Role: !GetAtt LambdaExecutionRole.Arn + MemorySize: 256 + Timeout: 600 + Environment: + Variables: + DEFAULT_REGION: !Ref AWS::Region + SSM_PARAMETER_NAME: !GetAtt SlackWebhookParameter.Name + +########################################################### +# CloudWatch Logs +########################################################### + MonitorECSCapacityProviderLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub /aws/lambda/${AddMonitorLambdaFunction} + RetentionInDays: 14 + +########################################################## +# SSM ParameterStore +########################################################## + SlackWebhookParameter: + Type: AWS::SSM::Parameter + Properties: + Name: /serverless/monitor-ecs-capaciry-provider/SLACK_WEBHOOK_URL + Type: String # CloudFromationでは、SecureStringがサポートされていないため。 + Value: '画面上で設定する' + +########################################################## +# IAM +########################################################## + LambdaExecutionRole: + Type: AWS::IAM::Role + Properties: + RoleName: monitor-ecs-lambda-execution-role + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + + Policies: + - PolicyName: logs_policy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Resource: !Sub 'arn:aws:logs:${DEFAULT_REGION}:${AWS::AccountId}:log-group:*:*' + + - PolicyName: ssm_policy + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - ssm:GetParameter + Resource: !Sub 'arn:aws:ssm:${DEFAULT_REGION}:${AWS::AccountId}:*' + + - PolicyName: add_cloudwatch_logs_subscription_filter + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - logs:PutSubscriptionFilter + - logs:DeleteSubscriptionFilter + - logs:DescribeSubscriptionFilters + Resource: !Sub 'arn:aws:logs:${DEFAULT_REGION}:${AWS::AccountId}:log-group:*:*' + + - PolicyName: add_cloudwatch_logs_subscription_filter + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - cloudwatch:PutMetricAlarm + - cloudwatch:DescribeAlarms + - cloudwatch:DeleteAlarms + Resource: !Sub 'arn:aws:cloudwatch:${DEFAULT_REGION}:${AWS::AccountId}:alarm:*' diff --git a/sam/monitor-lambda/events/event.json b/sam/monitor-lambda/events/event.json deleted file mode 100644 index a6197dea..00000000 --- a/sam/monitor-lambda/events/event.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "body": "{\"message\": \"hello world\"}", - "resource": "/hello", - "path": "/hello", - "httpMethod": "GET", - "isBase64Encoded": false, - "queryStringParameters": { - "foo": "bar" - }, - "pathParameters": { - "proxy": "/path/to/resource" - }, - "stageVariables": { - "baz": "qux" - }, - "headers": { - "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", - "Accept-Encoding": "gzip, deflate, sdch", - "Accept-Language": "en-US,en;q=0.8", - "Cache-Control": "max-age=0", - "CloudFront-Forwarded-Proto": "https", - "CloudFront-Is-Desktop-Viewer": "true", - "CloudFront-Is-Mobile-Viewer": "false", - "CloudFront-Is-SmartTV-Viewer": "false", - "CloudFront-Is-Tablet-Viewer": "false", - "CloudFront-Viewer-Country": "US", - "Host": "1234567890.execute-api.us-east-1.amazonaws.com", - "Upgrade-Insecure-Requests": "1", - "User-Agent": "Custom User Agent String", - "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", - "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", - "X-Forwarded-For": "127.0.0.1, 127.0.0.2", - "X-Forwarded-Port": "443", - "X-Forwarded-Proto": "https" - }, - "requestContext": { - "accountId": "123456789012", - "resourceId": "123456", - "stage": "prod", - "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", - "requestTime": "09/Apr/2015:12:34:56 +0000", - "requestTimeEpoch": 1428582896000, - "identity": { - "cognitoIdentityPoolId": null, - "accountId": null, - "cognitoIdentityId": null, - "caller": null, - "accessKey": null, - "sourceIp": "127.0.0.1", - "cognitoAuthenticationType": null, - "cognitoAuthenticationProvider": null, - "userArn": null, - "userAgent": "Custom User Agent String", - "user": null - }, - "path": "/prod/hello", - "resourcePath": "/hello", - "httpMethod": "POST", - "apiId": "1234567890", - "protocol": "HTTP/1.1" - } -} diff --git a/sam/monitor-lambda/__init__.py b/sam/monitor-lambda/function/__init__.py similarity index 100% rename from sam/monitor-lambda/__init__.py rename to sam/monitor-lambda/function/__init__.py diff --git a/sam/monitor-lambda/function/add_resources.py b/sam/monitor-lambda/function/add_resources.py new file mode 100644 index 00000000..dfcbb431 --- /dev/null +++ b/sam/monitor-lambda/function/add_resources.py @@ -0,0 +1,3 @@ +import boto3 + +# diff --git a/sam/monitor-lambda/hello_world/__init__.py b/sam/monitor-lambda/function/handler.py similarity index 100% rename from sam/monitor-lambda/hello_world/__init__.py rename to sam/monitor-lambda/function/handler.py diff --git a/sam/monitor-lambda/function/notify_slack.py b/sam/monitor-lambda/function/notify_slack.py new file mode 100644 index 00000000..e69de29b diff --git a/sam/monitor-lambda/function/setting.py b/sam/monitor-lambda/function/setting.py new file mode 100644 index 00000000..34c37642 --- /dev/null +++ b/sam/monitor-lambda/function/setting.py @@ -0,0 +1,45 @@ +"""This module sets up the configuration.""" + +import datetime +import json +import os +from pathlib import Path + +# environment variables +DEFAULT_REGION = os.environ.get("AWS_REGION") +SSM_PARAMETER_NAME = os.environ.get("SSM_PARAMETER_NAME") +# ACCOUNT_ID = os.environ.get("ACCOUNT_ID") +ACCOUNT_ID = "685339645368" + +print(ACCOUNT_ID) + +# setting.pyの絶対パスを取得 +current_file = Path(__file__).resolve() +print(current_file) + +# setting.pyのディレクトリ(function/)を取得 +current_dir = current_file.parent +print(current_dir) + +# 親ディレクトリ(プロジェクトルート)に移動してからconfigディレクトリに移動 +config_dir = current_dir.parent / "config" +print(config_dir) + +# アカウント名の取得 +with open(f"{config_dir}/mapping.json") as f: + config = json.load(f) +print(config) +ACCOUNT_NAME = config["account_mapping"].get(str(ACCOUNT_ID)) +print(ACCOUNT_NAME) + +# lambda関数名を設定しているjsonファイルの読み込み +with open(f"{config_dir}/{ACCOUNT_NAME}/lambda.json") as f: + functions = json.load(f) +FUNCTIONS = functions["lambda"] +print(FUNCTIONS) + + +# Get date for slack notification +today = datetime.datetime.now() +weekday = today.strftime("%a") +day_format = today.strftime("%Y/%-m/%-d") + f"({weekday})" diff --git a/sam/monitor-lambda/hello_world/app.py b/sam/monitor-lambda/hello_world/app.py deleted file mode 100644 index 139af7d4..00000000 --- a/sam/monitor-lambda/hello_world/app.py +++ /dev/null @@ -1,44 +0,0 @@ -import json - -# import requests - - -def lambda_handler(event, context): - """Sample pure Lambda function - - Parameters - ---------- - event: dict, required - API Gateway Lambda Proxy Input Format - - Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format - - context: object, required - Lambda Context runtime methods and attributes - - Context doc: https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html - - Returns - ------ - API Gateway Lambda Proxy Output Format: dict - - Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html - """ - - # try: - # ip = requests.get("http://checkip.amazonaws.com/") - # except requests.RequestException as e: - # # Send some context about this error to Lambda Logs - # print(e) - - # raise e - - return { - "statusCode": 200, - "body": json.dumps( - { - "message": "hello world", - # "location": ip.text.replace("\n", "") - } - ), - } diff --git a/sam/monitor-lambda/hello_world/requirements.txt b/sam/monitor-lambda/hello_world/requirements.txt deleted file mode 100644 index f2293605..00000000 --- a/sam/monitor-lambda/hello_world/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -requests diff --git a/sam/monitor-lambda/template.yaml b/sam/monitor-lambda/template.yaml deleted file mode 100644 index 02ccce07..00000000 --- a/sam/monitor-lambda/template.yaml +++ /dev/null @@ -1,61 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: > - monitor-lambda - - Sample SAM Template for monitor-lambda - -# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst -Globals: - Function: - Timeout: 3 - MemorySize: 128 - - Tracing: Active - # You can add LoggingConfig parameters such as the Logformat, Log Group, and SystemLogLevel or ApplicationLogLevel. Learn more here https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-loggingconfig. - LoggingConfig: - LogFormat: JSON - Api: - TracingEnabled: true -Resources: - HelloWorldFunction: - Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction - Properties: - CodeUri: hello_world/ - Handler: app.lambda_handler - Runtime: python3.9 - Architectures: - - x86_64 - Events: - HelloWorld: - Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api - Properties: - Path: /hello - Method: get - - ApplicationResourceGroup: - Type: AWS::ResourceGroups::Group - Properties: - Name: - Fn::Sub: ApplicationInsights-SAM-${AWS::StackName} - ResourceQuery: - Type: CLOUDFORMATION_STACK_1_0 - ApplicationInsightsMonitoring: - Type: AWS::ApplicationInsights::Application - Properties: - ResourceGroupName: - Ref: ApplicationResourceGroup - AutoConfigurationEnabled: 'true' -Outputs: - # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function - # Find out more about other implicit resources you can reference within SAM - # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api - HelloWorldApi: - Description: API Gateway endpoint URL for Prod stage for Hello World function - Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" - HelloWorldFunction: - Description: Hello World Lambda Function ARN - Value: !GetAtt HelloWorldFunction.Arn - HelloWorldFunctionIamRole: - Description: Implicit IAM Role created for Hello World function - Value: !GetAtt HelloWorldFunctionRole.Arn