简体   繁体   English

是否可以从 EventBridge 事件数据中提取“instanceId”并将其用作目标值?

[英]Is it possible to extract "instanceId" from EventBridge event data, and use it as Target Value?

I was able to setup AutoScaling events as rules in EventBridge to trigger SSM Commands, but I've noticed that with my chosen Target Value the event is passed to all my active EC2 Instances.我能够在 EventBridge 中将 AutoScaling 事件设置为规则以触发 SSM 命令,但我注意到,使用我选择的目标值,事件被传递到我所有活动的 EC2 实例。 My Target key is a tag shared by those instances, so my mistake makes sense now.我的 Target 键是这些实例共享的标签,所以我的错误现在是有道理的。

I'm pretty new to EventBridge, so I was wondering if there's a way to actually target the instance that triggered the AutoScaling event (as in extracting the "InstanceId" that's present in the event data and use that as my new Target Value).我是 EventBridge 的新手,所以我想知道是否有一种方法可以实际定位触发 AutoScaling 事件的实例(如提取事件数据中存在的“InstanceId”并将其用作我的新目标值)。 I saw the Input Transformer, but I think that just transforms the event data to pass to the target.我看到了 Input Transformer,但我认为它只是转换事件数据以传递给目标。

Thanks!谢谢!

EDIT - help with js code for Lambda + SSM RunCommand编辑 - 帮助 Lambda + SSM RunCommand 的 js 代码

I realize I can achieve this by setting EventBridge to invoke a Lambda function instead of the SSM RunCommand directly.我意识到我可以通过将 EventBridge 设置为调用Lambda function 而不是直接调用SSM RunCommand来实现这一点。 Can anyone help with the javaScript code to call a shell command on the ec2 instance specified in the event data ( event.detail.EC2InstanceId )?任何人都可以帮助 javaScript 代码在事件数据( event.detail.EC2InstanceId )中指定的 ec2 实例上调用 shell 命令吗? I can't seem to find a relevant and up-to-date base template online, and I'm not familiar enough with js or Lambda. Any help is greatly appreciated!我似乎无法在网上找到相关的和最新的基础模板,而且我对js或Lambda不够熟悉。非常感谢任何帮助! Thanks谢谢

Sample of Event data , as per aws docs事件数据样本,根据aws 文档

{
  "version": "0",
  "id": "12345678-1234-1234-1234-123456789012",
  "detail-type": "EC2 Instance Launch Successful",
  "source": "aws.autoscaling",
  "account": "123456789012",
  "time": "yyyy-mm-ddThh:mm:ssZ",
  "region": "us-west-2",
  "resources": [
      "auto-scaling-group-arn",
      "instance-arn"
  ],
  "detail": {
      "StatusCode": "InProgress",
      "Description": "Launching a new EC2 instance: i-12345678",
      "AutoScalingGroupName": "my-auto-scaling-group",
      "ActivityId": "87654321-4321-4321-4321-210987654321",
      "Details": {
          "Availability Zone": "us-west-2b",
          "Subnet ID": "subnet-12345678"
      },
      "RequestId": "12345678-1234-1234-1234-123456789012",
      "StatusMessage": "",
      "EndTime": "yyyy-mm-ddThh:mm:ssZ",
      "EC2InstanceId": "i-1234567890abcdef0",
      "StartTime": "yyyy-mm-ddThh:mm:ssZ",
      "Cause": "description-text"
  }
}

Edit 2 - my Lambda code so far编辑 2 - 到目前为止我的 Lambda 代码

'use strict'

const ssm = new (require('aws-sdk/clients/ssm'))()

exports.handler = async (event) => {
    const instanceId = event.detail.EC2InstanceId
    var params = {
        DocumentName: "AWS-RunShellScript",
        InstanceIds: [ instanceId ],
        TimeoutSeconds: 30,
        Parameters: {
          commands: ["/path/to/my/ec2/script.sh"],
          workingDirectory: [],
          executionTimeout: ["15"]
        }
    };

    const data = await ssm.sendCommand(params).promise()
    const response = {
        statusCode: 200,
        body: "Run Command success",
    };
    return response;
}

Yes, but through Lambda是的,但是通过 Lambda

EventBridge -> Lambda (using SSM api) -> EC2 EventBridge -> Lambda(使用 SSM api) -> EC2

Thank you @Sándor Bakos for helping me out,!谢谢@Sándor Bakos 帮助我,! My JavaScript ended up not working for some reason, so I ended up just using part of the python codelinked in the comments.我的 JavaScript 由于某种原因最终无法正常工作,所以我最终只使用了评论中链接的部分 python 代码。

1. add ssm:SendCommand permission: 1.添加ssm:SendCommand权限:

After I let Lambda create a basic role during function creation, I added an inline policy to allow Systems Manager's SendCommand.在创建 function 期间让 Lambda 创建基本角色后,我添加了一个内联策略以允许 Systems Manager 的 SendCommand。 This needs access to your documents/* , instances/* and managed-instances/*这需要访问您的documents/*instances/*managed-instances/*

2. code - python 3.9 2.代码 - python 3.9

import boto3
import botocore
import time

def lambda_handler(event=None, context=None):
    try:
        client = boto3.client('ssm')
    
        instance_id = event['detail']['EC2InstanceId']
        command = '/path/to/my/script.sh'
        
        client.send_command(
            InstanceIds = [ instance_id ],
            DocumentName = 'AWS-RunShellScript',
            Parameters = {
                'commands': [ command ],
                'executionTimeout': [ '60' ]
            }
        )

You can do this without using lambda, as I just did, by using eventbridge's input transformers.您可以在不使用 lambda 的情况下执行此操作,就像我刚才所做的那样,通过使用 eventbridge 的输入转换器。

I specified a new automation document that called the document I was trying to use (AWS-ApplyAnsiblePlaybooks).我指定了一个新的自动化文档,它调用了我尝试使用的文档 (AWS-ApplyAnsiblePlaybooks)。

My document called out the InstanceId as a parameter and is passed this by the input transformer from EventBridge.我的文档调用了 InstanceId 作为参数,并由来自 EventBridge 的输入转换器传递。 I had to pass the event into lambda just to see how to parse the JSON event object to get the desired instance ID - this ended up being我不得不将事件传递到 lambda 只是为了看看如何解析 JSON 事件 object 以获得所需的实例 ID - 这最终是

$.detail.EC2InstanceID 

(it was coming from an autoscaling group). (它来自一个自动缩放组)。

I then passed it into a template that was used for the runbook然后我将它传递到用于运行手册的模板中

{"InstanceId":[<instance>]}

This template was read in my runbook as a parameter.该模板在我的运行手册中作为参数读取。

This was the SSM playbook inputs I used to run the AWS-ApplyAnsiblePlaybook Document, I just mapped each parameter to the specified parameters in the nested playbook:这是我用来运行 AWS-ApplyAnsiblePlaybook 文档的 SSM 剧本输入,我只是将每个参数映射到嵌套剧本中的指定参数:

 "inputs": {
      "InstanceIds": ["{{ InstanceId }}"],
      "DocumentName": "AWS-ApplyAnsiblePlaybooks",
      "Parameters": {
        "SourceType": "S3",
        "SourceInfo": {"path": "https://testansiblebucketab.s3.amazonaws.com/"},
        "InstallDependencies": "True",
        "PlaybookFile": "ansible-test.yml",
        "ExtraVariables": "SSM=True",
        "Check": "False",
        "Verbose": "-v",
        "TimeoutSeconds": "3600"
      }

See the document below for reference.请参阅下面的文档以供参考。 They used a document that was already set up to receive the variable他们使用了一个已经设置好的文档来接收变量

https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-tutorial-eventbridge-input-transformers.html https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-tutorial-eventbridge-input-transformers.html

This is the full automation playbook I used, most of the parameters are defaults from the nested playbook:这是我使用的全自动化剧本,大部分参数都是嵌套剧本的默认值:

 {
"description": "Runs Ansible Playbook on Launch Success Instances",
"schemaVersion": "0.3",
"assumeRole": "<Place your automation role ARN here>",
"parameters": {
  "InstanceId": {
    "type": "String",
    "description": "(Required) The ID of the Amazon EC2 instance."
  }
},
"mainSteps": [
  {
    "name": "RunAnsiblePlaybook",
    "action": "aws:runCommand",
    "inputs": {
      "InstanceIds": ["{{ InstanceId }}"],
      "DocumentName": "AWS-ApplyAnsiblePlaybooks",
      "Parameters": {
        "SourceType": "S3",
        "SourceInfo": {"path": "https://testansiblebucketab.s3.amazonaws.com/"},
        "InstallDependencies": "True",
        "PlaybookFile": "ansible-test.yml",
        "ExtraVariables": "SSM=True",
        "Check": "False",
        "Verbose": "-v",
        "TimeoutSeconds": "3600"
      }
    }
  }
]

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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