Skip to content

Commit 09052c2

Browse files
authored
feat(pipes-enrichments): support API Gateway enrichment (#31794)
### Issue # (if applicable) Closes #29384 ### Reason for this change To support Amazon API Gateway enrichment for EventBridge pipes. ### Description of changes Add `ApiGatewayEnrichment` construct. ### Description of how you validated changes Add unit tests and integ test. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 408b20f commit 09052c2

16 files changed

+40690
-0
lines changed

packages/@aws-cdk/aws-pipes-enrichments-alpha/README.md

+20
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,23 @@ const pipe = new pipes.Pipe(this, 'Pipe', {
8888
target: new SomeTarget(targetQueue),
8989
});
9090
```
91+
92+
### API Gateway (REST API)
93+
94+
API Gateway can be used to enrich events of a pipe.
95+
Pipes only supports API Gateway REST APIs. HTTP APIs are not supported.
96+
97+
```ts
98+
declare const sourceQueue: sqs.Queue;
99+
declare const targetQueue: sqs.Queue;
100+
101+
declare const restApi: apigateway.RestApi;
102+
103+
const enrichment = new enrichments.ApiGatewayEnrichment(restApi);
104+
105+
const pipe = new pipes.Pipe(this, 'Pipe', {
106+
source: new SomeSource(sourceQueue),
107+
enrichment,
108+
target: new SomeTarget(targetQueue),
109+
});
110+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { EnrichmentParametersConfig, IEnrichment, IPipe, InputTransformation } from '@aws-cdk/aws-pipes-alpha';
2+
import { IRestApi } from 'aws-cdk-lib/aws-apigateway';
3+
import { IRole, PolicyStatement } from 'aws-cdk-lib/aws-iam';
4+
import { CfnPipe } from 'aws-cdk-lib/aws-pipes';
5+
6+
/**
7+
* Properties for a ApiGatewayEnrichment
8+
*/
9+
export interface ApiGatewayEnrichmentProps {
10+
/**
11+
* The input transformation for the enrichment
12+
* @see https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-input-transformation.html
13+
* @default - None
14+
*/
15+
readonly inputTransformation?: InputTransformation;
16+
17+
/**
18+
* The method for API Gateway resource.
19+
*
20+
* @default '*' - ANY
21+
*/
22+
readonly method?: string;
23+
24+
/**
25+
* The path for the API Gateway resource.
26+
*
27+
* @default '/'
28+
*/
29+
readonly path?: string;
30+
31+
/**
32+
* The deployment stage for the API Gateway resource.
33+
*
34+
* @default - the value of `deploymentStage.stageName` of target API Gateway resource.
35+
*/
36+
readonly stage?: string;
37+
38+
/**
39+
* The headers that need to be sent as part of request invoking the API Gateway REST API.
40+
*
41+
* @default - none
42+
*/
43+
readonly headerParameters?: Record<string, string>;
44+
45+
/**
46+
* The path parameter values used to populate the API Gateway REST API path wildcards ("*").
47+
*
48+
* @default - none
49+
*/
50+
readonly pathParameterValues?: string[];
51+
52+
/**
53+
* The query string keys/values that need to be sent as part of request invoking the EventBridge API destination.
54+
*
55+
* @default - none
56+
*/
57+
readonly queryStringParameters?: Record<string, string>;
58+
}
59+
60+
/**
61+
* An API Gateway enrichment for a pipe
62+
*/
63+
export class ApiGatewayEnrichment implements IEnrichment {
64+
public readonly enrichmentArn: string;
65+
66+
private readonly inputTransformation?: InputTransformation;
67+
private readonly headerParameters?: Record<string, string>;
68+
private readonly pathParameterValues?: string[];
69+
private readonly queryStringParameters?: Record<string, string>;
70+
71+
constructor(private readonly restApi: IRestApi, props?: ApiGatewayEnrichmentProps) {
72+
this.enrichmentArn = restApi.arnForExecuteApi(
73+
props?.method,
74+
props?.path || '/',
75+
props?.stage || this.restApi.deploymentStage.stageName,
76+
);
77+
this.inputTransformation = props?.inputTransformation;
78+
this.headerParameters = props?.headerParameters;
79+
this.queryStringParameters = props?.queryStringParameters;
80+
this.pathParameterValues = props?.pathParameterValues;
81+
}
82+
83+
bind(pipe: IPipe): EnrichmentParametersConfig {
84+
85+
const httpParameters: CfnPipe.PipeEnrichmentHttpParametersProperty | undefined =
86+
this.headerParameters ??
87+
this.pathParameterValues ??
88+
this.queryStringParameters
89+
? {
90+
headerParameters: this.headerParameters,
91+
pathParameterValues: this.pathParameterValues,
92+
queryStringParameters: this.queryStringParameters,
93+
}
94+
: undefined;
95+
96+
return {
97+
enrichmentParameters: {
98+
inputTemplate: this.inputTransformation?.bind(pipe).inputTemplate,
99+
httpParameters,
100+
},
101+
};
102+
}
103+
104+
grantInvoke(pipeRole: IRole): void {
105+
pipeRole.addToPrincipalPolicy(new PolicyStatement({
106+
resources: [this.enrichmentArn],
107+
actions: ['execute-api:Invoke'],
108+
}));
109+
}
110+
}
111+
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './api-destination';
2+
export * from './api-gateway';
23
export * from './lambda';
34
export * from './stepfunctions';

packages/@aws-cdk/aws-pipes-enrichments-alpha/rosetta/default.ts-fixture

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Fixture with packages imported, but nothing else
22
import * as cdk from 'aws-cdk-lib';
33
import * as events from 'aws-cdk-lib/aws-events';
4+
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
45
import * as sqs from 'aws-cdk-lib/aws-sqs';
56
import * as lambda from 'aws-cdk-lib/aws-lambda';
67
import * as stepfunctions from 'aws-cdk-lib/aws-stepfunctions';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`api-destination should grant pipe role invoke access 1`] = `
4+
{
5+
"MyPipeRoleCBC8E9AB": {
6+
"Properties": {
7+
"AssumeRolePolicyDocument": {
8+
"Statement": [
9+
{
10+
"Action": "sts:AssumeRole",
11+
"Effect": "Allow",
12+
"Principal": {
13+
"Service": "pipes.amazonaws.com",
14+
},
15+
},
16+
],
17+
"Version": "2012-10-17",
18+
},
19+
},
20+
"Type": "AWS::IAM::Role",
21+
},
22+
"RestApiCloudWatchRoleE3ED6605": {
23+
"DeletionPolicy": "Retain",
24+
"Properties": {
25+
"AssumeRolePolicyDocument": {
26+
"Statement": [
27+
{
28+
"Action": "sts:AssumeRole",
29+
"Effect": "Allow",
30+
"Principal": {
31+
"Service": "apigateway.amazonaws.com",
32+
},
33+
},
34+
],
35+
"Version": "2012-10-17",
36+
},
37+
"ManagedPolicyArns": [
38+
{
39+
"Fn::Join": [
40+
"",
41+
[
42+
"arn:",
43+
{
44+
"Ref": "AWS::Partition",
45+
},
46+
":iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs",
47+
],
48+
],
49+
},
50+
],
51+
},
52+
"Type": "AWS::IAM::Role",
53+
"UpdateReplacePolicy": "Retain",
54+
},
55+
}
56+
`;
57+
58+
exports[`api-destination should grant pipe role invoke access 2`] = `
59+
{
60+
"MyPipeRoleDefaultPolicy31387C20": {
61+
"Properties": {
62+
"PolicyDocument": {
63+
"Statement": [
64+
{
65+
"Action": "execute-api:Invoke",
66+
"Effect": "Allow",
67+
"Resource": {
68+
"Fn::Join": [
69+
"",
70+
[
71+
"arn:",
72+
{
73+
"Ref": "AWS::Partition",
74+
},
75+
":execute-api:",
76+
{
77+
"Ref": "AWS::Region",
78+
},
79+
":",
80+
{
81+
"Ref": "AWS::AccountId",
82+
},
83+
":",
84+
{
85+
"Ref": "RestApi0C43BF4B",
86+
},
87+
"/",
88+
{
89+
"Ref": "RestApiDeploymentStageprod3855DE66",
90+
},
91+
"/*/",
92+
],
93+
],
94+
},
95+
},
96+
],
97+
"Version": "2012-10-17",
98+
},
99+
"PolicyName": "MyPipeRoleDefaultPolicy31387C20",
100+
"Roles": [
101+
{
102+
"Ref": "MyPipeRoleCBC8E9AB",
103+
},
104+
],
105+
},
106+
"Type": "AWS::IAM::Policy",
107+
},
108+
}
109+
`;

0 commit comments

Comments
 (0)