ä»åã¯ãååæçš¿ãããOSãããé©çšãèªååãããåŸãçµæãã¡ãŒã«ã«éç¥ãããæ¹æ³ããAWS CDKã§å®è£
ããæ¹æ³ããŸãšããŸããã AWS Systems Manager ã® Patch Manager ã§ OS ãããé©çšãèªååããŠã¿ã AWS Systems Manager ã§ãããé©çšãèªååããæ¹æ³ããŸãšããŠã¿ãŸããã blog.usize-tech.com 2025.01.22 OSãããé©çšçµæãã¡ãŒã«éç¥ããŠã¿ã Amazon CloudWatch Logs ã«åºåããããã°ãããæå®ããä»»æã®æååãããªã¬ãŒã« Amazon SNS çµç±ã§é©çšçµæãã¡ãŒã«ã§éç¥ããŸãã blog.usize-tech.com 2025.02.07 ã¯ããã« ååã®èšäºã§ã¯AWSãããžã¡ã³ãã³ã³ãœãŒã«ã䜿ã£ãŠæåã§OSãããé©çšã®èªååã·ã¹ãã ãæ§ç¯ããŸããã ä»åã¯ãåãã·ã¹ãã ãAWS CDKïŒCloud Development KitïŒã䜿ã£ãŠã³ãŒãåããInfrastructure as CodeïŒIaCïŒãšããŠç®¡çã§ããããã«ããŠãããŸãã ä»åäœæãããªãœãŒã¹ SNSãããã¯: ã¡ãŒã«éç¥çš IAMããŒã«: SSMå®è¡çšãšLambdaå®è¡çš ãããããŒã¹ã©ã€ã³: Windows Server 2022çš ã¡ã³ããã³ã¹ãŠã£ã³ããŠ: æ¯æç¬¬1æææ¥ã«å®è¡ Lambda颿°: ãããçµæè§£æãšSNSéä¿¡ CloudWatchãã°ã°ã«ãŒã: ãããå®è¡ãã°ä¿åçš ãµãã¹ã¯ãªãã·ã§ã³ãã£ã«ã¿ãŒ: Lambdaèµ·åããªã¬ãŒ AWS CDK ãœãŒã¹ã³ãŒã lib/patch-automation-stack.ts ãã以äžã®ããã«å®è£
ããŸãã æåã«åã³ã³ããŒãã³ãæ¯ã«è©³çްã解説ããæåŸã«ãœãŒã¹ã³ãŒãããŸãšããŠèšèŒããŸãã ãŸããCDKã§ã¯ååã®èªåèšå®ãgrantã¡ãœãããªã©äŸ¿å©ãªæ©èœããããŸãããå®éã®æ¡ä»¶ã§ã¯æ§ã
ãªãªãœãŒã¹ã«ååãèšå®ããå¿
èŠããã£ãããååãå®çŸ©ã§ããããã«å®è£
ãããŠããŸãã SNSãããã¯ãšã¡ãŒã«éç¥èšå® // ãããéç¥çšSNSãããã¯ã®äœæ const patchtopic = new sns.Topic(this, 'PatchNotificationTopic', { topicName: 'sns-patch-notification', displayName: 'ãããé©çšçµæéç¥' }); // SNSãããã¯ã«éç¥å
ã¡ãŒã«ã¢ãã¬ã¹ãèšå® patchtopic.addSubscription( new subscriptions.EmailSubscription('your-email@example.com')ãããããããã//å®éã®ã¡ãŒã«ã¢ãã¬ã¹ãžå€æŽ ); ãã€ã³ã: EmailSubscription ã§éç¥å
ã¡ãŒã«ã¢ãã¬ã¹ãèšå® å®éã®ã¡ãŒã«ã¢ãã¬ã¹ã«å€æŽããå¿
èŠããããŸã IAMããŒã«ã®èšå® // SSM Run Commandå®è¡çšã®IAMããŒã« const ssmRunCommandRole = new iam.Role(this, 'SSMRunCommandRole', { assumedBy: new iam.ServicePrincipal('ssm.amazonaws.com'), roleName: 'SSMRunCommandRole', managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonSSMMaintenanceWindowRole'), iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'), ], description: 'Role for SSM Run Command execution' }); // Lambda颿°ã®IAMããŒã«äœæ const lambdaPatchRole = new iam.Role(this, 'LambdaPatchRole', { roleName: 'LambdaPatchRole', assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), description: 'Lambda execution role for patch notification', managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole') ] }); ãã// Lambda颿°ã«SNSã®æš©éãä»äž new iam.Policy(this, 'LambdaPatchSnsPolicy', { policyName: 'LambdaPatchSnsPolicy', roles: [lambdaPatchRole], statements: [ new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['sns:Publish'], resources: ['*'] }) ] }); ãã€ã³ã: SSMããŒã« : ã¡ã³ããã³ã¹ãŠã£ã³ããŠã§ã®ãããé©çšå®è¡ã«å¿
èŠãªæš©é AmazonSSMMaintenanceWindowRole : ã¡ã³ããã³ã¹ãŠã£ã³ããŠå°çšæš©é AmazonSSMManagedInstanceCore : SSMåºæ¬éä¿¡æš©é LambdaããŒã« : CloudWatch Logsã¢ã¯ã»ã¹ãšSNSçºè¡æš©é AWSLambdaBasicExecutionRole : Lambdaåºæ¬å®è¡æš©é ã«ã¹ã¿ã ããªã·ãŒã§SNSçºè¡æš©éã远å ãããããŒã¹ã©ã€ã³ã®èšå® new ssm.CfnPatchBaseline(this, 'WindowsPatchBaseline', { operatingSystem: 'WINDOWS', name: 'winsv-baseline', approvalRules: { patchRules: [{ approveAfterDays: 0, // ãªãªãŒã¹ãã0æ¥åŸã«æ¿èª complianceLevel: 'CRITICAL', // ã³ã³ãã©ã€ã¢ã³ã¹ã¬ãã«ïŒéèŠ enableNonSecurity: false, // ã»ãã¥ãªãã£ãããã®ã¿ã察象 patchFilterGroup: { patchFilters: [ { key: 'PRODUCT', values: ['WindowsServer2022']ããã // WindowsSrver2022ã§èšå® }, { key: 'CLASSIFICATION', // Windowsã®æŽæ°ããã°ã©ã åé¡ values: ['CriticalUpdates', 'SecurityUpdates'] // éèŠãªæŽæ°ããã°ã©ã ,ã»ãã¥ãªãã£æŽæ°ããã°ã©ã }, { key: 'MSRC_SEVERITY', // Microsoftãå®ããéèŠåºŠ values: ['Critical','Important'] // èŽåœçãªåé¡ãä¿®æ£,éèŠãªåé¡ãä¿®æ£ } ] } }] }, patchGroups: ['winsv-patch-group'] // 察象ãããã°ã«ãŒã }); ãã€ã³ã: operatingSystem : 察象OSïŒWINDOWSãAMAZON_LINUXãUBUNTUçïŒ approveAfterDays: 0 : ãªãªãŒã¹çŽåŸãããããé©çšå¯èœïŒæ¬çªã§ã¯7-30æ¥ãæšå¥šïŒ enableNonSecurity: false : ã»ãã¥ãªãã£ãããã®ã¿ã«éå® ãã£ã«ã¿ãŒæ¡ä»¶ : PRODUCT : 察象Windows補å CLASSIFICATION : ãããã®åé¡ MSRC_SEVERITY : Microsoftãå®ããéèŠåºŠ ã¡ã³ããã³ã¹ãŠã£ã³ããŠã®èšå® const patchMaintenanceWindow = new ssm.CfnMaintenanceWindow(this, 'PatchMaintenanceWindow', { name: 'monthly-patch-maintenance-window', schedule: 'cron(0 16 ? * MON#1 *)', duration: 2, cutoff: 0, allowUnassociatedTargets: false, scheduleTimezone: 'Asia/Tokyo' }); ã¹ã±ãžã¥ãŒã«èšå®ã¯çŸåšä»¥äžã®ããã«èšå®ããŠããŸãã®ã§ãèŠä»¶ã«å¿ããŠä¿®æ£ããŠãã ããã cron(0 16 ? * MON#1 *) : JSTæéã§ç¬¬1æææ¥16:00 duration: 2 : 2æéã®ã¡ã³ããã³ã¹æ scheduleTimezone: 'Asia/Tokyo' : æ¥æ¬æéã§ç®¡ç ãããé©çšå¯Ÿè±¡ã®èšå® const patchTarget = new ssm.CfnMaintenanceWindowTarget(this, 'PatchTarget', { windowId: patchMaintenanceWindow.ref, targets: [{ key: 'tag:PatchGroup', values: ['winsv-patch-group'] }], resourceType: 'INSTANCE', ownerInformation: 'Patch管ç察象ã€ã³ã¹ã¿ã³ã¹' }); ãã€ã³ã: targets: ã§ãããé©çšå¯Ÿè±¡ã€ã³ã¹ã¿ã³ã¹ãèšå® äºåã«EC2ã€ã³ã¹ã¿ã³ã¹ã§ã¿ã°ã®èšå®ãå¿
èŠ ä»åã®å Žåå¿
èŠãªã¿ã°èšå® -ã ããŒ: `PatchGroup`ã – å€: `winsv-patch-group` RunCommandã¿ã¹ã¯ã®äœæ // ãããé©çšã¿ã¹ã¯ã®äœæ const patchExecutionTask = new ssm.CfnMaintenanceWindowTask(this, 'PatchExecutionTask', { // åºæ¬èšå® windowId: patchMaintenanceWindow.ref, // ã¡ã³ããã³ã¹ãŠã£ã³ããŠã®åç
§ taskArn: 'AWS-RunPatchBaseline', // å®è¡ããSSMããã¥ã¡ã³ã taskType: 'RUN_COMMAND', // ã¿ã¹ã¯ã¿ã€ãïŒRunCommand name: 'SecurityPatchInstallation', // ã¿ã¹ã¯å description: 'ã»ãã¥ãªãã£ãããã®èªåã€ã³ã¹ããŒã«ãšåèµ·å', // ã¿ã¹ã¯ã®èª¬æ priority: 1, // ã¿ã¹ã¯ã®åªå
床ïŒ1ãæé«ïŒ maxConcurrency: '1', // åæå®è¡æ°ïŒ1å°ãã€é 次å®è¡ maxErrors: '0', // ãšã©ãŒèš±å®¹æ°ïŒ0ïŒ1å°ã§ããšã©ãŒãªãåæ¢ïŒ serviceRoleArn: ssmRunCommandRole.roleArn, ã// SSMå®è¡çšIAMããŒã« targets: [{ key: 'WindowTargetIds', // ã¿ãŒã²ããæå®æ¹æ³ values: [patchTarget.ref] // äºåã«å®çŸ©ããã¿ãŒã²ãããåç
§ }], taskInvocationParameters: { maintenanceWindowRunCommandParameters: { documentVersion: '$LATEST', // ææ°ããŒãžã§ã³ã®ããã¥ã¡ã³ããäœ¿çš parameters: { Operation: ['Install'], // æäœïŒãããã®ã€ã³ã¹ããŒã«å®è¡ RebootOption: ['RebootIfNeeded'], // å¿
èŠã«å¿ããŠèªååèµ·å SnapshotId: ['{{WINDOW_EXECUTION_ID}}'] // å®è¡IDãã¹ãããã·ã§ããIDãšããŠèšé² }, timeoutSeconds: 600, // ã¿ã€ã ã¢ãŠãïŒå¿
èŠã«å¿ããŠä¿®æ£ïŒ cloudWatchOutputConfig: { cloudWatchLogGroupName: 'aws-ssm-patch-execution-logs', // CloudWatch Logsã°ã«ãŒãå cloudWatchOutputEnabled: true // CloudWatch Logsåºåãæå¹å } } } }); ãã€ã³ã: taskArn : ‘AWS-RunPatchBaseline’ã§ãããé©çšãå®è¡ priority : 1ãæé«åªå
床 maxConcurrency : åæå®è¡æ°å¶åŸ¡ïŒ’1’=é æ¬¡ã’50%’=åæ°åæïŒ maxErrors : ãšã©ãŒèš±å®¹æ°ïŒ’0’=1å°ã§ããšã©ãŒãªãåæ¢ïŒ éèŠãã©ã¡ãŒã¿ : Operation: ['Install'] : ããããå®éã«ã€ã³ã¹ããŒã« RebootOption: ['RebootIfNeeded'] : å¿
èŠæã®ã¿åèµ·å SnapshotId : å®è¡å±¥æŽã®è¿œè·¡çš Lambda颿°äœæ // Lambda颿°äœæ const patchNotificationLambda = new lambda.Function(this, 'PatchNotificationFunction', { functionName: 'lmd-patch-send-sns', // 颿°å runtime: lambda.Runtime.PYTHON_3_13, // å®è¡ç°å¢ïŒPython 3.13 handler: 'index.lambda_handler', // ãšã³ããªãŒãã€ã³ã code: lambda.Code.fromAsset( // ãœãŒã¹ã³ãŒãã®å Žæ path.join(__dirname, 'lambda') ), role: lambdaPatchRole, // Lambdaå®è¡æIAMããŒã« environment: { // ç°å¢å€æ° SNS_TOPIC_ARN: patchtopic.topicArn, // SNSãããã¯ã®ARN ALARM_SUBJECT: 'ãããé©çšçµæéç¥' // ã¡ãŒã«ã®ä»¶å }, timeout: cdk.Duration.seconds(600), // å®è¡ã¿ã€ã ã¢ãŠã memorySize: 128, // ã¡ã¢ãªå²ãåœãŠïŒMBïŒ }); ãã€ã³ã: runtime : Python 3.13 code : lib/lambda ãã£ã¬ã¯ããªããã³ãŒãèªã¿èŸŒã¿ environment : SNSãããã¯ARNãšã¡ãŒã«ä»¶åãç°å¢å€æ°ã§èšå® timeout : 600ç§ memorySize : 128MB 颿°äœæ import logging import json import base64 import gzip import boto3 import os logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): # CloudWatchLogsããã®ããŒã¿ã¯base64ãšã³ã³ãŒããããŠããã®ã§ãã³ãŒã decoded_data = base64.b64decode(event['awslogs']['data']) # ãã€ããªã«å§çž®ãããŠããããå±é json_data = json.loads(gzip.decompress(decoded_data)) logger.info("EVENT: " + json.dumps(json_data)) # ãã°ããŒã¿ååŸ log = json_data['logEvents'][0]['message'] instanceid_position = log.find('PatchGroup') instanceidtmp = log[:instanceid_position] instanceid = instanceidtmp.replace('Patch Summary for ','') print(instanceid) result_position = log.find('Results') result = log[result_position:] print(result) patchGroup_start = log.find('PatchGroup') patchGroup_end = log.find('BaselineId') patchGrouptmp = log[patchGroup_start:patchGroup_end] patchGroup = patchGrouptmp.replace('PatchGroup : ','') print(patchGroup) messagetmp = """ ãããé©çšçµæãéç¥ããŸãã 察象ã€ã³ã¹ã¿ã³ã¹ã»é©çšçµæã¯äžèšãšãªããŸãã ã察象ã€ã³ã¹ã¿ã³ã¹{0} ããããã°ã«ãŒã {1} ãé©çšçµæ {2} """ message = messagetmp.format(instanceid,patchGroup,result) print(message) try: sns = boto3.client('sns') #SNS Publish publishResponse = sns.publish( TopicArn = os.environ['SNS_TOPIC_ARN'], Message = message, Subject = os.environ['ALARM_SUBJECT'] ) except Exception as e: print(e) ãã€ã³ã: lib/lambda/index.py ã«Pythonã³ãŒããé
眮ããŸã ãã°ã°ã«ãŒãèšå® // ããããã°çšã®CloudWatchãã°ã°ã«ãŒãäœæ const patchloggroup = new logs.LogGroup(this, 'PatchLogGroup', { logGroupName: 'aws-ssm-patch-execution-logs', // ãããé©çšãã°ã°ã«ãŒã retention: logs.RetentionDays.ONE_YEAR, // ä¿ææé: 1幎é removalPolicy: cdk.RemovalPolicy.RETAIN // ã¹ã¿ãã¯å逿ã«åé€ãããªã }); new logs.SubscriptionFilter(this, 'PatchSummarySubscription', { // ãµãã¹ã¯ãªãã·ã§ã³ãã£ã«ã¿ãŒã®èšå®ïŒLambda颿°ã®èµ·åããªã¬ãŒïŒ logGroup: patchloggroup, // ç£èŠå¯Ÿè±¡ã®ãã°ã°ã«ãŒã destination: new destinations.LambdaDestination(patchNotificationLambda), // éä¿¡å
filterPattern: logs.FilterPattern.literal('Patch Summary'), // ãã£ã«ã¿ãŒæ¡ä»¶ filterName: 'PatchNotification' // ãã£ã«ã¿ãŒå }); } ãã€ã³ã: logGroupName: ã¯RunCommandã¿ã¹ã¯ã®äœæã§æå®ãããã°ã°ã«ãŒãåãšåããã ä¿ç®¡æéã¯èŠä»¶ã«åãããŠä¿®æ£ãã ä»åå®è£
ããã¹ã¿ãã¯ãã¡ã€ã«ãŸãšã import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as ssm from 'aws-cdk-lib/aws-ssm'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as logs from 'aws-cdk-lib/aws-logs'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as sns from 'aws-cdk-lib/aws-sns'; import * as subscriptions from 'aws-cdk-lib/aws-sns-subscriptions'; import * as path from 'path'; import * as destinations from 'aws-cdk-lib/aws-logs-destinations'; export class PatchAutomationStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // ãããéç¥çšSNSãããã¯ã®äœæ const patchtopic = new sns.Topic(this, 'PatchNotificationTopic', { topicName: 'sns-patch-notification', displayName: 'ãããé©çšçµæéç¥' }); // SNSãããã¯ã«éç¥å
ã¡ãŒã«ã¢ãã¬ã¹ãèšå® patchtopic.addSubscription( new subscriptions.EmailSubscription('your-email@example.com') // ãããå®éã®ã¡ãŒã«ã¢ãã¬ã¹ã«å€æŽ ); // SSM Run Commandå®è¡çšã®IAMããŒã« const ssmRunCommandRole = new iam.Role(this, 'SSMRunCommandRole', { roleName: 'SSMRunCommandRole', assumedBy: new iam.ServicePrincipal('ssm.amazonaws.com'), managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonSSMMaintenanceWindowRole'), iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'), ], description: 'Role for SSM Run Command execution' }); // Lambda颿°ã®IAMããŒã«äœæ const lambdaPatchRole = new iam.Role(this, 'LambdaPatchRole', { roleName: 'LambdaPatchRole', assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), description: 'Lambda execution role for patch notification', managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole') ] }); // Lambda颿°ã«SNSã®æš©éãä»äž new iam.Policy(this, 'LambdaPatchSnsPolicy', { policyName: 'LambdaPatchSnsPolicy', roles: [lambdaPatchRole], statements: [ new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['sns:Publish'], resources: ['*'] }) ] }); // ãããããŒã¹ã©ã€ã³ã®äœæ new ssm.CfnPatchBaseline(this, 'WindowsPatchBaseline', { operatingSystem: 'WINDOWS', name: 'winsv-baseline', approvalRules: { patchRules: [{ approveAfterDays: 0, // ãªãªãŒã¹ãã0æ¥åŸã«æ¿èª complianceLevel: 'CRITICAL', // ã³ã³ãã©ã€ã¢ã³ã¹ã¬ãã«ïŒéèŠ enableNonSecurity: false, // ã»ãã¥ãªãã£ãããã®ã¿ã察象 patchFilterGroup: { patchFilters: [ { key: 'PRODUCT', values: ['WindowsServer2022'] // WindowsServer2022ã§èšå® }, { key: 'CLASSIFICATION', values: ['CriticalUpdates', 'SecurityUpdates'] }, { key: 'MSRC_SEVERITY', values: ['Critical', 'Important'] } ] } }] }, patchGroups: ['winsv-patch-group'] }); // ã¡ã³ããã³ã¹ãŠã£ã³ããŠã®äœæ const patchMaintenanceWindow = new ssm.CfnMaintenanceWindow(this, 'PatchMaintenanceWindow', { name: 'monthly-patch-maintenance-window', schedule: 'cron(0 16 ? * MON#1 *)', // æ¯æç¬¬1æææ¥ JST 16:00 duration: 2, // å®è¡å¯èœæéïŒ2æé cutoff: 0, // æ°èŠã¿ã¹ã¯éå§ã®ç· åæé allowUnassociatedTargets: false, // é¢é£ä»ããããã¿ãŒã²ããã®ã¿å®è¡ scheduleTimezone: 'Asia/Tokyo' // ã¹ã±ãžã¥ãŒã«ã®ã¿ã€ã ãŸãŒã³ }); // ãããé©çšå¯Ÿè±¡ã®èšå® const patchTarget = new ssm.CfnMaintenanceWindowTarget(this, 'PatchTarget', { windowId: patchMaintenanceWindow.ref, // ã¡ã³ããã³ã¹ãŠã£ã³ããŠã®åç
§ targets: [{ key: 'tag:PatchGroup', // ã¿ã°ã«ããå¯Ÿè±¡éžæ values: ['winsv-patch-group'] // 察象ãšããã¿ã°å€ }], resourceType: 'INSTANCE', // 察象ãªãœãŒã¹çš®å¥ïŒEC2ã€ã³ã¹ã¿ã³ã¹ ownerInformation: 'Patch管ç察象ã€ã³ã¹ã¿ã³ã¹' // 管ççšã¡ã¢ }); // ãããé©çšã¿ã¹ã¯ã®äœæ const patchExecutionTask = new ssm.CfnMaintenanceWindowTask(this, 'PatchExecutionTask', { // åºæ¬èšå® windowId: patchMaintenanceWindow.ref, // ã¡ã³ããã³ã¹ãŠã£ã³ããŠã®åç
§ taskArn: 'AWS-RunPatchBaseline', // å®è¡ããSSMããã¥ã¡ã³ã taskType: 'RUN_COMMAND', // ã¿ã¹ã¯ã¿ã€ãïŒRunCommand name: 'SecurityPatchInstallation', // ã¿ã¹ã¯å description: 'ã»ãã¥ãªãã£ãããã®èªåã€ã³ã¹ããŒã«ãšåèµ·å', // ã¿ã¹ã¯ã®èª¬æ priority: 1, // ã¿ã¹ã¯ã®åªå
床ïŒ1ãæé«ïŒ maxConcurrency: '1', // åæå®è¡æ°ïŒ1å°ãã€é 次å®è¡ maxErrors: '0', // ãšã©ãŒèš±å®¹æ°ïŒ0ïŒ1å°ã§ããšã©ãŒãªãåæ¢ïŒ serviceRoleArn: ssmRunCommandRole.roleArn, ããã // SSMå®è¡çšIAMããŒã« targets: [{ key: 'WindowTargetIds', // ã¿ãŒã²ããæå®æ¹æ³ values: [patchTarget.ref] // äºåã«å®çŸ©ããã¿ãŒã²ãããåç
§ }], taskInvocationParameters: { maintenanceWindowRunCommandParameters: { documentVersion: '$LATEST', // ææ°ããŒãžã§ã³ã®ããã¥ã¡ã³ããäœ¿çš parameters: { Operation: ['Install'], // æäœïŒãããã®ã€ã³ã¹ããŒã«å®è¡ RebootOption: ['RebootIfNeeded'], // å¿
èŠã«å¿ããŠèªååèµ·å SnapshotId: ['{{WINDOW_EXECUTION_ID}}'] // å®è¡IDãã¹ãããã·ã§ããIDãšããŠèšé² }, timeoutSeconds: 600, // ã¿ã€ã ã¢ãŠãïŒå¿
èŠã«å¿ããŠä¿®æ£ïŒ cloudWatchOutputConfig: { cloudWatchLogGroupName: 'aws-ssm-patch-execution-logs', // CloudWatch Logsã°ã«ãŒãå cloudWatchOutputEnabled: true // CloudWatch Logsåºåãæå¹å } } } }); // Lambda颿°äœæ const patchNotificationLambda = new lambda.Function(this, 'PatchNotificationFunction', { functionName: 'lmd-patch-send-sns', // 颿°å runtime: lambda.Runtime.PYTHON_3_13, // å®è¡ç°å¢ïŒPython 3.13 handler: 'index.lambda_handler', // ãšã³ããªãŒãã€ã³ã code: lambda.Code.fromAsset( // ãœãŒã¹ã³ãŒãã®å Žæ path.join(__dirname, 'lambda') ), role: lambdaPatchRole, // Lambdaå®è¡æIAMããŒã« environment: { // ç°å¢å€æ° SNS_TOPIC_ARN: patchtopic.topicArn, // SNSãããã¯ã®ARN ALARM_SUBJECT: 'ãããé©çšçµæéç¥' // ã¡ãŒã«ã®ä»¶å }, timeout: cdk.Duration.seconds(600), // å®è¡ã¿ã€ã ã¢ãŠã memorySize: 128, // ã¡ã¢ãªå²ãåœãŠïŒMBïŒ description: 'ãããé©çšçµæãè§£æããŠSNSéç¥ãéä¿¡ãã颿°' // 颿°ã®èª¬æ }); // ããããã°çšã®CloudWatchãã°ã°ã«ãŒãäœæ const patchloggroup = new logs.LogGroup(this, 'PatchLogGroup', { logGroupName: 'aws-ssm-patch-execution-logs', // ãããé©çšãã°ã°ã«ãŒã retention: logs.RetentionDays.ONE_YEAR, // ä¿ææé: 1幎é removalPolicy: cdk.RemovalPolicy.RETAIIN // ã¹ã¿ãã¯å逿ã«åé€ãããªã }); // ãµãã¹ã¯ãªãã·ã§ã³ãã£ã«ã¿ãŒã®èšå®ïŒLambda颿°ã®èµ·åããªã¬ãŒïŒ new logs.SubscriptionFilter(this, 'PatchSummarySubscription', { logGroup: patchloggroup, // ç£èŠå¯Ÿè±¡ã®ãã°ã°ã«ãŒã destination: new destinations.LambdaDestination(patchNotificationLambda), // éä¿¡å
filterPattern: logs.FilterPattern.literal('Patch Summary'), // ãã£ã«ã¿ãŒæ¡ä»¶ filterName: 'PatchNotification' // ãã£ã«ã¿ãŒå }); } } ãŸãšã ä»åã¯ããããèªåé©çšããã¡ãŒã«éç¥ãŸã§ãAWS CDKã§ã¢ãžã¥ãŒã«åããŠã¿ãŸããã çããã®ã圹ã«ç«ãŠã°å¹žãã§ãã