基于事件的更新
通过我们的 AWS 集成,您可以根据实时事件(除标准的计划同步外)触发 AWS 资源与 Port 的同步。 因此,在创建、更新或删除资源后,您的软件目录将很快得到更新。
工作原理
许多 AWS 服务都会向AWS EventBridge 服务和账户的默认事件总线发送事件。此外,AWS CloudTrail 服务还会自动为来自大多数 AWS 服务的 API 调用发送事件。
用户可以创建一个AWS EventBridge rule ,用于消费和转换特定事件,并将其发送至目标,如AWS SQS Queue 。
The AWS exporter application 在安装过程中会创建一个 SQS 队列,并将其配置为输出程序 lambda 的事件源。
这样,您就可以设置一个事件规则,该规则会消耗总线上的任何事件,并将它们发送到 AWS 输出程序的队列中。
在到达队列之前,每个事件都必须作为事件规则的一部分进行转换,以适应出口程序的 lambda 预期事件结构。 转换的目标是将事件映射到出口程序可以处理的单个 AWS 资源。
队列中的事件会被出口程序的 lambda 自动消耗,该 lambda 会将相关 AWS 资源的更新状态与 Port 同步。
###单一事件的输入结构
AWS 输出程序的 lambda 接受具有以下结构的 JSON 事件:
resource_type
- 一个硬编码字符串,代表在 AWS Exporter 的config.json
中配置的 AWS 资源类型;region
- 从事件中获取区域的 JQ 查询,通常值为"\"<awsRegion>\""
;- action
(可选,默认为
upsert`)- 用于定义所需操作的 JQ 查询: "upsert "或 "delete "匹配资源的 Port 实体。通常基于事件名称,如下面的示例; - identifier` - 用于计算资源标识符的 JQ 查询。如果操作是 "upsert",则应是 AWS Cloud Control API 资源标识符。否则,对于 "删除 "操作,应使用Port 实体标识符。建议使用与云控制 API 资源标识符相同的Port实体标识符(如适用),这样就可以对上载和删除事件使用相同的事件规则(同时也无需使用复杂的 JQ 过滤模式)。
此类 JSON 事件的示例
{
"requestFunctionName": "<requestFunctionName>",
"responseFunctionName": "<responseFunctionName>",
"eventName": "<eventName>",
"resource_type": "AWS::Lambda::Function",
"region": "\"<awsRegion>\"",
"action": "if .eventName | startswith(\"Delete\") then \"delete\" else \"upsert\" end",
"identifier": "if .responseFunctionName != \"\" then .responseFunctionName else .requestFunctionName end"
}
AWS::Lambda::Function
)的标识符公式,可以使用以下命令:aws cloudformation describe-type --type RESOURCE --type-name AWS::Lambda::Function --query "Schema" | jq 'fromjson | .primaryIdentifier | join("|")'
# Result
"/properties/FunctionName"
从这里可以看出,lambda 函数的标识符就是函数名。
另一个例子是 AWS::ECS::Service
资源类型:
aws cloudformation describe-type --type RESOURCE --type-name AWS::ECS::Service --query "Schema" | jq 'fromjson | .primaryIdentifier | join("|")'
# Result
"/properties/ServiceArn|/properties/Cluster"
这里的公式中有两个属性: /properties/ServiceArn
和/properties/Cluster
。 当有多个属性时,标识符中的值用|
分隔。
更多信息,请阅读here 。
活动规则
定义
通过事件规则,您可以指定要消费的确切事件,并定义将修改后的事件发送到的目标(包括对输入的转换)。
在深入 diveevent rule properties 之前,这里有一个用于管理 AWS 输出程序事件规则的 "CloudFormation YAML 模板 "的完整示例:
AWSTemplateFormatVersion: "2010-09-09"
Description: The template used to create event rules for the Port AWS exporter.
Parameters:
PortAWSExporterStackName:
Description: Name of the Port AWS exporter stack name
Type: String
MinLength: 1
MaxLength: 255
AllowedPattern: "^[a-zA-Z][-a-zA-Z0-9]*$"
Default: serverlessrepo-port-aws-exporter
Resources:
EventRule0:
Type: AWS::Events::Rule
Properties:
EventBusName: default
EventPattern:
source:
- aws.lambda
detail-type:
- AWS API Call via CloudTrail
detail:
eventSource:
- lambda.amazonaws.com
eventName:
- prefix: UpdateFunctionConfiguration
- prefix: CreateFunction
- prefix: DeleteFunction
Name: port-aws-exporter-sync-lambda-trails
State: ENABLED
Targets:
- Id: "PortAWSExporterEventsQueue"
Arn:
{
"Fn::ImportValue":
{ "Fn::Sub": "${PortAWSExporterStackName}-EventsQueueARN" },
}
InputTransformer:
InputPathsMap:
awsRegion: $.detail.awsRegion
eventName: $.detail.eventName
requestFunctionName: $.detail.requestParameters.functionName
responseFunctionName: $.detail.responseElements.functionName
InputTemplate: |-
{
"resource_type": "AWS::Lambda::Function",
"requestFunctionName": "<requestFunctionName>",
"responseFunctionName": "<responseFunctionName>",
"eventName": "<eventName>",
"region": "\"<awsRegion>\"",
"identifier": "if .responseFunctionName != \"\" then .responseFunctionName else .requestFunctionName end",
"action": "if .eventName | startswith(\"Delete\") then \"delete\" else \"upsert\" end"
}
Properties
让我们回顾一下上述事件规则资源的属性。
- EventBusName "属性值为 "default",因为这是自动从各种 AWS 服务获取事件的总线:
Properties:
EventBusName: default
...
- EventPattern "属性定义了要消费的事件,包括要处理的事件源、根据事件结构应用的过滤器。在此,我们定义了一种事件模式,以消费来自 lambda 服务的 Cloudtrail API 调用;在此基础上,我们仅过滤了
UpdateFunctionConfiguration
、CreateFunction
和DeleteFunction
事件:
Properties:
EventBusName: default
EventPattern:
source:
- aws.lambda
detail-type:
- AWS API Call via CloudTrail
detail:
eventSource:
- lambda.amazonaws.com
eventName:
- prefix: UpdateFunctionConfiguration
- prefix: CreateFunction
- prefix: DeleteFunction
- 目标 "属性定义了生成事件的目标。对于 AWS 输出程序,我们希望将其自身的事件队列配置为目标:
Properties:
...
Targets:
- Id: "PortAWSExporterEventsQueue"
Arn: { "Fn::ImportValue" : {"Fn::Sub": "${PortAWSExporterStackName}-EventsQueueARN" } }
...
- 目标 "属性中的 "InputTransformer "键定义了在将事件发送到目标队列之前将应用于事件的转换;
Properties:
...
Targets:
- Id: "PortAWSExporterEventsQueue"
Arn: { "Fn::ImportValue" : {"Fn::Sub": "${PortAWSExporterStackName}-EventsQueueARN" } }
InputTransformer:
...
- 输入转换器 "中的 "InputPathsMap "键定义了要从事件中提取的字段。它被用于
JSONPath
语法来配置提取:
Properties:
...
Targets:
- Id: "PortAWSExporterEventsQueue"
Arn: { "Fn::ImportValue" : {"Fn::Sub": "${PortAWSExporterStackName}-EventsQueueARN" } }
InputTransformer:
InputPathsMap:
awsRegion: $.detail.awsRegion
eventName: $.detail.eventName
requestFunctionName: $.detail.requestParameters.functionName
responseFunctionName: $.detail.responseElements.functionName
...
例如,为 CreateFunction
lambda API 调用发送到 EventBridge 总线的事件具有以下结构:
{
...
"detail": {
...
"eventSource": "lambda.amazonaws.com",
"eventName": "CreateFunction20150331",
"awsRegion": "eu-west-1",
...
"requestParameters": {
"functionName": "test-function",
...
},
"responseElements": {
"functionName": "test-function",
...
},
...
}
}
下面示例中的 InputPathsMap
将只从 API 请求和响应中提取 awsRegion
, eventName
和 functionName
。
- InputTransformer
中的
InputTemplate键定义了将发送到目标队列的最终输入的模板,格式为输出器的 lambda[expects](#input-structure-for-a-single-event) 。该模板会被用于
InputPathsMap` 中的 Values 来渲染:
Properties:
...
Targets:
- Id: "PortAWSExporterEventsQueue"
Arn: { "Fn::ImportValue" : {"Fn::Sub": "${PortAWSExporterStackName}-EventsQueueARN" } }
InputTransformer:
InputPathsMap:
awsRegion: $.detail.awsRegion
eventName: $.detail.eventName
requestFunctionName: $.detail.requestParameters.functionName
responseFunctionName: $.detail.responseElements.functionName
InputTemplate: |-
{
"resource_type": "AWS::Lambda::Function",
"requestFunctionName": "<requestFunctionName>",
"responseFunctionName": "<responseFunctionName>",
"eventName": "<eventName>",
"region": "\"<awsRegion>\"",
"identifier": "if .responseFunctionName != \"\" then .responseFunctionName else .requestFunctionName end",
"action": "if .eventName | startswith(\"Delete\") then \"delete\" else \"upsert\" end"
}
在这里,"InputTemplate"(输入模板)接收从 "InputPathsMap"(输入路径图)中提取的信息,并构建一条消息,该消息将被发送到 SQS 队列,并被出口程序的 lambda 消耗。 消息包括:
- 硬编码资源类型(
AWS::Lambda::Function
); - 事件中的
awsRegion
字段; - JQ 查询,根据事件名称确定操作("上载 "或 "删除 "Port实体);
- 根据 API 响应或请求中的函数名计算标识符的 JQ 查询。
下一步
示例
- 有关实用配置及其相应蓝图定义,请参阅examples 页面。
- 参考事件桥规则Terraform example