|
| 1 | +import json |
1 | 2 | from typing import Any, List |
2 | 3 |
|
3 | | -from aws_cdk import Duration |
| 4 | +from aws_cdk import CustomResource, Duration |
4 | 5 | from aws_cdk import aws_events as events |
5 | 6 | from aws_cdk import aws_events_targets as targets |
6 | 7 | from aws_cdk import aws_iam as iam |
@@ -167,6 +168,100 @@ def __init__( |
167 | 168 | ) |
168 | 169 | ) |
169 | 170 |
|
| 171 | + # Trigger baseline immediately on deployment (fire-and-forget) |
| 172 | + trigger_lambda = lambda_.Function( |
| 173 | + self, |
| 174 | + "TriggerBaselineLambda", |
| 175 | + runtime=lambda_.Runtime.PYTHON_3_13, |
| 176 | + handler="index.handler", |
| 177 | + code=lambda_.Code.from_inline(""" |
| 178 | +import boto3 |
| 179 | +import json |
| 180 | +import urllib3 |
| 181 | +import logging |
| 182 | +
|
| 183 | +logger = logging.getLogger() |
| 184 | +logger.setLevel(logging.INFO) |
| 185 | +
|
| 186 | +sfn = boto3.client('stepfunctions') |
| 187 | +http = urllib3.PoolManager() |
| 188 | +
|
| 189 | +def send_response(event, context, status, reason=None): |
| 190 | + response_body = { |
| 191 | + 'Status': status, |
| 192 | + 'Reason': reason or f'See CloudWatch Log Stream: {context.log_stream_name}', |
| 193 | + 'PhysicalResourceId': 'baseline-trigger', |
| 194 | + 'StackId': event['StackId'], |
| 195 | + 'RequestId': event['RequestId'], |
| 196 | + 'LogicalResourceId': event['LogicalResourceId'], |
| 197 | + } |
| 198 | +
|
| 199 | + json_response = json.dumps(response_body) |
| 200 | + headers = {'content-type': '', 'content-length': str(len(json_response))} |
| 201 | +
|
| 202 | + try: |
| 203 | + http.request('PUT', event['ResponseURL'], body=json_response, headers=headers) |
| 204 | + except Exception as e: |
| 205 | + logger.error(f"Failed to send response: {e}") |
| 206 | +
|
| 207 | +def handler(event, context): |
| 208 | + try: |
| 209 | + logger.info(f"Event: {json.dumps(event)}") |
| 210 | + request_type = event['RequestType'] |
| 211 | +
|
| 212 | + if request_type in ['Create', 'Update']: |
| 213 | + state_machine_arn = event['ResourceProperties']['StateMachineArn'] |
| 214 | + monitor_types = json.loads(event['ResourceProperties']['MonitorTypes']) |
| 215 | +
|
| 216 | + for monitor_type in monitor_types: |
| 217 | + sfn.start_execution( |
| 218 | + stateMachineArn=state_machine_arn, |
| 219 | + input=json.dumps({'monitor_type': monitor_type}) |
| 220 | + ) |
| 221 | +
|
| 222 | + send_response(event, context, 'SUCCESS', 'Baseline generation triggered') |
| 223 | + elif request_type == 'Delete': |
| 224 | + send_response(event, context, 'SUCCESS', 'Nothing to delete') |
| 225 | + else: |
| 226 | + send_response(event, context, 'SUCCESS', f'No action for {request_type}') |
| 227 | +
|
| 228 | + except Exception as e: |
| 229 | + logger.error(f"Error: {e}") |
| 230 | + send_response(event, context, 'FAILED', str(e)) |
| 231 | +"""), |
| 232 | + timeout=Duration.seconds(30), |
| 233 | + ) |
| 234 | + |
| 235 | + trigger_lambda.add_to_role_policy( |
| 236 | + iam.PolicyStatement( |
| 237 | + actions=["states:StartExecution"], |
| 238 | + resources=[state_machine.state_machine_arn], |
| 239 | + ) |
| 240 | + ) |
| 241 | + |
| 242 | + CustomResource( |
| 243 | + self, |
| 244 | + "TriggerBaselineResource", |
| 245 | + service_token=trigger_lambda.function_arn, |
| 246 | + properties={ |
| 247 | + "StateMachineArn": state_machine.state_machine_arn, |
| 248 | + "MonitorTypes": json.dumps(enabled_monitors), |
| 249 | + }, |
| 250 | + ) |
| 251 | + |
| 252 | + # Add CDK-nag suppressions |
| 253 | + if trigger_lambda.role: |
| 254 | + NagSuppressions.add_resource_suppressions( |
| 255 | + trigger_lambda.role, |
| 256 | + [ |
| 257 | + { |
| 258 | + "id": "AwsSolutions-IAM4", |
| 259 | + "reason": "Lambda function uses AWS managed policy for basic execution role", |
| 260 | + }, |
| 261 | + ], |
| 262 | + apply_to_children=True, |
| 263 | + ) |
| 264 | + |
170 | 265 | # Add CDK-nag suppressions |
171 | 266 | if baselining_lambda.role: |
172 | 267 | NagSuppressions.add_resource_suppressions( |
|
0 commit comments