Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pipes-enrichments): support API Gateway enrichment #31794

Merged
merged 11 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions packages/@aws-cdk/aws-pipes-enrichments-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,23 @@ const pipe = new pipes.Pipe(this, 'Pipe', {
target: new SomeTarget(targetQueue),
});
```

### API Gateway (REST API)

API Gateway can be used to enrich events of a pipe.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @mazyu36 - I'm curious if you've considered ApiGatewayV2; whether or not the enrichment should cover that case as well, and if so whether that would be a separate construct or also handled by this design?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sumupitchayan

ApigatewayV2(HTTP API) cannot be used because pipes only supports Apigateway(REST API).

https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-aws-services-reference.html

The pipes documentation did not clearly state this.
Also, when I tried in the management console, I was unable to use the HTTP API.​​​​​​​​​​​​​​​​

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Can you maybe then also make this more clear in the README?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I've updated README.

Pipes only supports API Gateway REST APIs. HTTP APIs are not supported.

```ts
declare const sourceQueue: sqs.Queue;
declare const targetQueue: sqs.Queue;

declare const restApi: apigateway.RestApi;

const enrichment = new enrichments.ApiGatewayEnrichment(restApi);

const pipe = new pipes.Pipe(this, 'Pipe', {
source: new SomeSource(sourceQueue),
enrichment,
target: new SomeTarget(targetQueue),
});
```
111 changes: 111 additions & 0 deletions packages/@aws-cdk/aws-pipes-enrichments-alpha/lib/api-gateway.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { EnrichmentParametersConfig, IEnrichment, IPipe, InputTransformation } from '@aws-cdk/aws-pipes-alpha';
import { IRestApi } from 'aws-cdk-lib/aws-apigateway';
import { IRole, PolicyStatement } from 'aws-cdk-lib/aws-iam';
import { CfnPipe } from 'aws-cdk-lib/aws-pipes';

/**
* Properties for a ApiGatewayEnrichment
*/
export interface ApiGatewayEnrichmentProps {
/**
* The input transformation for the enrichment
* @see https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-pipes-input-transformation.html
* @default - None
*/
readonly inputTransformation?: InputTransformation;

/**
* The method for API Gateway resource.
*
* @default '*' - ANY
*/
readonly method?: string;

/**
* The path for the API Gateway resource.
*
* @default '/'
*/
readonly path?: string;

/**
* The deployment stage for the API Gateway resource.
*
* @default - the value of `deploymentStage.stageName` of target API Gateway resource.
*/
readonly stage?: string;

/**
* The headers that need to be sent as part of request invoking the API Gateway REST API.
*
* @default - none
*/
readonly headerParameters?: Record<string, string>;

/**
* The path parameter values used to populate the API Gateway REST API path wildcards ("*").
*
* @default - none
*/
readonly pathParameterValues?: string[];

/**
* The query string keys/values that need to be sent as part of request invoking the EventBridge API destination.
*
* @default - none
*/
readonly queryStringParameters?: Record<string, string>;
}

/**
* An API Gateway enrichment for a pipe
*/
export class ApiGatewayEnrichment implements IEnrichment {
public readonly enrichmentArn: string;

private readonly inputTransformation?: InputTransformation;
private readonly headerParameters?: Record<string, string>;
private readonly pathParameterValues?: string[];
private readonly queryStringParameters?: Record<string, string>;

constructor(private readonly restApi: IRestApi, props?: ApiGatewayEnrichmentProps) {
this.enrichmentArn = restApi.arnForExecuteApi(
props?.method,
props?.path || '/',
props?.stage || this.restApi.deploymentStage.stageName,
);
this.inputTransformation = props?.inputTransformation;
this.headerParameters = props?.headerParameters;
this.queryStringParameters = props?.queryStringParameters;
this.pathParameterValues = props?.pathParameterValues;
}

bind(pipe: IPipe): EnrichmentParametersConfig {

const httpParameters: CfnPipe.PipeEnrichmentHttpParametersProperty | undefined =
this.headerParameters ??
this.pathParameterValues ??
this.queryStringParameters
? {
headerParameters: this.headerParameters,
pathParameterValues: this.pathParameterValues,
queryStringParameters: this.queryStringParameters,
}
: undefined;

return {
enrichmentParameters: {
inputTemplate: this.inputTransformation?.bind(pipe).inputTemplate,
httpParameters,
},
};
}

grantInvoke(pipeRole: IRole): void {
pipeRole.addToPrincipalPolicy(new PolicyStatement({
resources: [this.enrichmentArn],
actions: ['execute-api:Invoke'],
}));
}
}

1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-pipes-enrichments-alpha/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './api-destination';
export * from './api-gateway';
export * from './lambda';
export * from './stepfunctions';
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Fixture with packages imported, but nothing else
import * as cdk from 'aws-cdk-lib';
import * as events from 'aws-cdk-lib/aws-events';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as stepfunctions from 'aws-cdk-lib/aws-stepfunctions';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`api-destination should grant pipe role invoke access 1`] = `
{
"MyPipeRoleCBC8E9AB": {
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "pipes.amazonaws.com",
},
},
],
"Version": "2012-10-17",
},
},
"Type": "AWS::IAM::Role",
},
"RestApiCloudWatchRoleE3ED6605": {
"DeletionPolicy": "Retain",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com",
},
},
],
"Version": "2012-10-17",
},
"ManagedPolicyArns": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition",
},
":iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs",
],
],
},
],
},
"Type": "AWS::IAM::Role",
"UpdateReplacePolicy": "Retain",
},
}
`;

exports[`api-destination should grant pipe role invoke access 2`] = `
{
"MyPipeRoleDefaultPolicy31387C20": {
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition",
},
":execute-api:",
{
"Ref": "AWS::Region",
},
":",
{
"Ref": "AWS::AccountId",
},
":",
{
"Ref": "RestApi0C43BF4B",
},
"/",
{
"Ref": "RestApiDeploymentStageprod3855DE66",
},
"/*/",
],
],
},
},
],
"Version": "2012-10-17",
},
"PolicyName": "MyPipeRoleDefaultPolicy31387C20",
"Roles": [
{
"Ref": "MyPipeRoleCBC8E9AB",
},
],
},
"Type": "AWS::IAM::Policy",
},
}
`;
Loading