简体   繁体   中英

aws eventbridge set ssm-document as target with aws-cdk python

hope I did not overlook an already existing answer.. I would like to create an aws-cdk python stack containing an event that is starting an ssm-document when triggered. I got all the wanted stuff going in my aws test account, event is triggering on the desired actions and starts the ssm-document/run command with the correct targets (ec2 instances identified by some tags). Now when it comes to Iac using aws-cdk python, I came to the boundary that it seems as if the aws_events_targets class ( https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_events_targets.html ) does not allow to set the diesired target for an event.. does anyone has a suggestion how to best work around this or the correct example for a blind man?

Use the AwsApi target and trigger the document with an API call to SSM.

In short, it is not a valid approach because ssm-document is just a set of commands, not a system(application) or computing environment.

I would decompose this process as follows:

  • You have a ssm-document which should be used by ssm/run-command. Document itself does not do anything.
  • You have an event which should trigger the execution of the document.

According to this, I would stick to the design pattern for event-based business logic execution:

Event source sends event to event Bus. Then EventBridge Rule catches it based on predefined pattern and activates Lambda which is going to execute a business logic (in our case ssm-document).

So, let's get to code:

Step 0
I assume you have AWS CLI/CDK installed, project is set and you are already logged in.

Step 1 - Declare and define Lambda and its Role

import aws_cdk.aws_iam as _iam

lambda_role = _iam.Role(self, "lambda_role", 
role_name="lambda_role",
assumed_by=_iam.ServicePrincipal("lambda.amazonaws.com"),
managed_policies=[
    _iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaBasicExecutionRole"),
    _iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSServiceRoleX"),
    _iam.ManagedPolicy.from_aws_managed_policy_name("AWSRoleY")],
inline_policies={
"My_Custom_Name_For_Inline_Policy": _iam.PolicyDocument(statements=[
    _iam.PolicyStatement(
        effect=_iam.Effect.ALLOW, 
        actions=["ssm:*"],
        resources=["RESOURCE_ARN1", "RESOURCE_ARN1"])])})

As I do not have enough information to help you correctly define the role, I proposed all possible option how you can allow your Lambda function to run ssm-document. Here are some details:

  • service-role/AWSLambdaBasicExecutionRole is mandatory
  • service-role/AWSServiceRoleX is meant for any service-based AWS managed roles. Replace it with the correct one(s) in case of need.
  • AWSRoleY is meant for general AWS-managed roles. Replace it with the correct one(s) in case of need.
  • I also added inline_policies in case you need to granularly define what exactly you want to allow your Lambda role to do.
import aws_cdk.aws_lambda as _lambda

lambda_ = _lambda.Function(self, "my_lambda", 
    function_name="my_lambda",
    architecture=_lambda.Architecture.ARM_64,
    runtime=_lambda.Runtime.PYTHON_3_9, 
    role=lambda_role, 
    log_retention=_logs.RetentionDays.THREE_MONTHS,
    timeout=cdk.Duration.minutes(3), 
    retry_attempts=0, 
    code=_lambda.Code.from_asset("./assets/lambda_code/"), 
    handler="lambda_main.lambda_handler")

Again, In this case I am lacking some information but I assume this might be a strucutre of your Lambda function:

  • As we are using Python3.9 runtime and we do not have any complicated 3rd-party dependencies - we can use ARM architecture .
  • lambda_role refers to previously defined role.
  • I also added log_retention for 3 months, removed retry_attempts and set 3 min timeout . These are optional and should be used/adjusted based on your preference.
  • code refers to block which I will provide in the next block. If you want to following the proposed structure then in the root of the project you will need to create dir called lambda_code , inside it you will script named lambda_main.py
  • The function which will be called by Lambda has default name - lambda_handler .

Lambda code which hold business logic (run ssm-document):

import boto3

_ssm = boto3.client('ssm')


def lambda_handler(event, context):
    print(event)
    response = ssm_client.send_command(
                InstanceIds=['i-01234567890'],
                DocumentName="AWS-RunShellScript",
                Parameters={'commands': ['whoami']})

    command_id = response['Command']['CommandId']
    
    return ssm_client.get_command_invocation(CommandId=command_id, InstanceId='i-01234567890')

In this example I decided to use AWS-RunShellScript document, which you should substitute with the one you need. Be default, parameters also should be changed.

Step 2 - Declare and define EventBridge Rule

import aws_cdk.aws_events as _events
import aws_cdk.aws_events_targets as _targets

# Based on CRON
_events.Rule(self, "trigger_rule_sync", 
    rule_name="my_rule_name", 
    enabled=True, 
    schedule=_events.Schedule.cron(minute="0", hour="8"),
    targets=[_targets.LambdaFunction(handler=lambda_tableau_deployment)])

# Based on EVENT PATTERN
_events.Rule(self, "trigger_rule_sync", 
    rule_name="my_rule_name", 
    enabled=True, 
    event_pattern=_events.EventPattern(
        resources=["ARN_OF_MY_CODECOMMIT_REPO"], 
        detail={"event": ["referenceUpdated"], "referenceName": ["prod", "dev"]}),
    targets=[_targets.LambdaFunction(handler=lambda_tableau_deployment)])

In this snippet I provided both triggering by schedule and triggering by event. As an event I assumed that I want to trigger my lambda when I commit something to by prod or dev branch in AWS CodeCommit. (weird, but why not?). Details of code can be found in boto3 documentation .

Step 3 - Sync, deploy and check

When everything is ready, give it a try and verify that final result matches the expected one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM