Skip to content

Commit

Permalink
Added StepFunctionsStartExecutionIntegration and StepFunctionsStartSy…
Browse files Browse the repository at this point in the history
…ncExecutionIntegration.

Added unit and integration tests.
Fixed issues mentioned in the Pull-request.
Added example to README

closes aws#11947.
  • Loading branch information
Saqib Dhuka committed Oct 14, 2021
1 parent 00a8063 commit a50b049
Show file tree
Hide file tree
Showing 13 changed files with 1,014 additions and 45 deletions.
46 changes: 46 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2-integrations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- [HTTP APIs](#http-apis)
- [Lambda Integration](#lambda)
- [HTTP Proxy Integration](#http-proxy)
- [AWS Service Integration](#aws-service)
- [Private Integration](#private-integration)
- [Request Parameters](#request-parameters)
- [WebSocket APIs](#websocket-apis)
Expand Down Expand Up @@ -79,6 +80,51 @@ httpApi.addRoutes({
});
```

### AWS Service

You can integrate your HTTP API with AWS services by using first-class integrations. A first-class integration connects
an HTTP API route to an AWS service API. When a client invokes a route that's backed by a first-class integration,
API Gateway invokes an AWS service API for you. More information can be found at [Working with AWS service integrations for HTTP APIs]
(https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-aws-services.html).

The following code configures a route `POST /start` to start execution of Standard Step Functions state machine.

```ts
const httpApi = new HttpApi(stack, 'HttpApi');
const state = new StateMachine(stack, 'MyStateMachine', {
definition: Chain.start(new Pass(stack, 'Pass')),
stateMachineType: StateMachineType.STANDARD,
});
httpApi.addRoutes({
path: '/start',
methods: [ HttpMethod.POST ],
integration: new StepFunctionsStartExecutionIntegration({
stateMachine: state,
input: '$request.body',
timeout: Duration.seconds(10),
}),
});
```

The following code configures a route `POST /start` to start synchronous execution of Express Step Functions state machine.

```ts
const httpApi = new HttpApi(stack, 'HttpApi');
const state = new StateMachine(stack, 'MyStateMachine', {
definition: Chain.start(new Pass(stack, 'Pass')),
stateMachineType: StateMachineType.EXPRESS,
});
httpApi.addRoutes({
path: '/start',
methods: [ HttpMethod.POST ],
integration: new StepFunctionsStartSyncExecutionIntegration({
stateMachine: state,
input: '$request.body',
timeout: Duration.seconds(10),
}),
});
```

### Private Integration

Private integrations enable integrating an HTTP API route with private resources in a VPC, such as Application Load Balancers or
Expand Down
168 changes: 168 additions & 0 deletions packages/@aws-cdk/aws-apigatewayv2-integrations/lib/http/aws.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import * as iam from '@aws-cdk/aws-iam';
import { IStateMachine } from '@aws-cdk/aws-stepfunctions';
import { Construct } from 'constructs';
import { AwsServiceIntegration, AwsServiceIntegrationProps } from './private/integration';

/**
* The common Step Functions integration resource for HTTP API
*/
abstract class StepFunctionsIntegration extends AwsServiceIntegration {

/**
*
* @internal
*/
protected _integrationService(): string {
return 'StepFunctions';
}
}

/**
* Step Functions StartExecution integration properties
*/
export interface StepFunctionsStartExecutionIntegrationProps extends AwsServiceIntegrationProps {

/**
* The state machine to be executed
*/
readonly stateMachine: IStateMachine;

/**
* The execution name
*
* @default - undefined
*/
readonly name?: string;

/**
* The input parameters of execution
*
* @default - undefined
*/
readonly input?: any;

/**
* The region of state machine
*
* @default - undefined
*/
readonly region?: string;

/**
* Passes the AWS X-Ray trace header. The trace header can also be passed in the request payload.
*
* @default - undefined
*/
readonly traceHeader?: string;
}

/**
* The StepFunctions-StartExecution integration resource for HTTP API
*/
export class StepFunctionsStartExecutionIntegration extends StepFunctionsIntegration {

constructor(private readonly _scope: Construct, private readonly _props: StepFunctionsStartExecutionIntegrationProps) {
super(_props);
}

/**
*
* @internal
*/
protected _integrationAction(): string {
return 'StartExecution';
}

/**
*
* @internal
*/
protected _fulfillRole(credentialsRole: iam.IRole): void {
this._props.stateMachine.grantStartExecution(credentialsRole);
credentialsRole.attachInlinePolicy(
new iam.Policy(this._scope, 'AllowSfnExec', {
statements: [
new iam.PolicyStatement({
actions: ['states:StartExecution'],
effect: iam.Effect.ALLOW,
resources: [this._props.stateMachine.stateMachineArn],
}),
],
}),
);

}

/**
*
* @internal
*/
protected _buildRequestParameters(): { [key: string]: any } {
return {
StateMachineArn: this._props.stateMachine.stateMachineArn,
Name: this._props.name,
Input: this._props.input,
Region: this._props.region,
TraceHeader: this._props.traceHeader,
};
}
}

/**
* Step Functions StartSyncExecution integration properties
*/
export interface StepFunctionsStartSyncExecutionIntegrationProps extends StepFunctionsStartExecutionIntegrationProps {
}

/**
* The StepFunctions-StartExecution integration resource for HTTP API
*/
export class StepFunctionsStartSyncExecutionIntegration extends StepFunctionsIntegration {

constructor(private readonly _scope: Construct, private readonly _props: StepFunctionsStartSyncExecutionIntegrationProps) {
super(_props);
}

/**
*
* @internal
*/
protected _integrationAction(): string {
return 'StartSyncExecution';
}

/**
*
* @internal
*/
protected _fulfillRole(credentialsRole: iam.IRole): void {

this._props.stateMachine.grantExecution(credentialsRole.grantPrincipal, 'states:StartSyncExecution');
credentialsRole.attachInlinePolicy(
new iam.Policy(this._scope, 'AllowSfnSyncExec', {
statements: [
new iam.PolicyStatement({
actions: ['states:StartSyncExecution'],
effect: iam.Effect.ALLOW,
resources: [this._props.stateMachine.stateMachineArn],
}),
],
}),
);

}

/**
*
* @internal
*/
protected _buildRequestParameters(): { [key: string]: any } {
return {
StateMachineArn: this._props.stateMachine.stateMachineArn,
Name: this._props.name,
Input: this._props.input,
Region: this._props.region,
TraceHeader: this._props.traceHeader,
};
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { HttpMethod, IVpcLink, ParameterMapping } from '@aws-cdk/aws-apigatewayv2';
import { Duration } from '@aws-cdk/core';

/**
* Base options for private integration
Expand Down Expand Up @@ -32,3 +33,23 @@ export interface HttpPrivateIntegrationOptions {
*/
readonly parameterMapping?: ParameterMapping;
}

/**
* Common properties to initialize a new `HttpProxyIntegration`.
*/
export interface CommonIntegrationProps {

/**
* The description of the integration
*
* @default - undefined
*/
readonly description?: string;

/**
* Custom timeout for HTTP APIs
*
* @default - undefined
*/
readonly timeout?: Duration;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './nlb';
export * from './service-discovery';
export * from './http-proxy';
export * from './lambda';
export * from './aws';
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
IVpcLink,
} from '@aws-cdk/aws-apigatewayv2';
import * as ec2 from '@aws-cdk/aws-ec2';
import { IRole, Role, ServicePrincipal } from '@aws-cdk/aws-iam';
import { CommonIntegrationProps } from '../base-types';


/**
Expand Down Expand Up @@ -63,3 +65,65 @@ export abstract class HttpPrivateIntegration implements IHttpRouteIntegration {

public abstract bind(options: HttpRouteIntegrationBindOptions): HttpRouteIntegrationConfig;
}

/**
* Aws Service integration properties
*
* @internal
*/
export interface AwsServiceIntegrationProps extends CommonIntegrationProps {
}

/**
* The Aws Service integration resource for HTTP API
*
* @internal
*/
export abstract class AwsServiceIntegration implements IHttpRouteIntegration {

constructor(private readonly props: AwsServiceIntegrationProps) {
}

/**
*
* @internal
*/
protected abstract _fulfillRole(credentialsRole: IRole): void;

/**
*
* @internal
*/
protected abstract _buildRequestParameters(): { [key: string]: any };

/**
*
* @internal
*/
protected abstract _integrationService(): string;

/**
*
* @internal
*/
protected abstract _integrationAction(): string;

public bind(_options: HttpRouteIntegrationBindOptions): HttpRouteIntegrationConfig {

const apiGatewayIntegrationRole = new Role(_options.scope, 'ApiGatewayIntegrationRole', {
assumedBy: new ServicePrincipal('apigateway.amazonaws.com'),
});
this._fulfillRole(apiGatewayIntegrationRole);

return {
payloadFormatVersion: PayloadFormatVersion.VERSION_1_0, // 1.0 is required and is the only supported format
type: HttpIntegrationType.LAMBDA_PROXY,
subtype: `${this._integrationService()}-${this._integrationAction()}`,
credentials: apiGatewayIntegrationRole.roleArn,
timeout: this.props.timeout,
description: this.props.description,
requestParameters: this._buildRequestParameters(),
};
}

}
7 changes: 6 additions & 1 deletion packages/@aws-cdk/aws-apigatewayv2-integrations/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@
"@aws-cdk/assertions": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/cdk-integ-tools": "0.0.0",
"@aws-cdk/assert-internal": "0.0.0",
"@aws-cdk/pkglint": "0.0.0",
"@types/jest": "^26.0.24"
"@types/jest": "^26.0.24",
"@types/nodeunit": "^0.0.31",
"nodeunit": "^0.11.3"
},
"dependencies": {
"@aws-cdk/aws-apigatewayv2": "0.0.0",
Expand All @@ -83,6 +86,7 @@
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/aws-servicediscovery": "0.0.0",
"@aws-cdk/aws-stepfunctions": "0.0.0",
"@aws-cdk/core": "0.0.0",
"constructs": "^3.3.69"
},
Expand All @@ -93,6 +97,7 @@
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/aws-servicediscovery": "0.0.0",
"@aws-cdk/aws-stepfunctions": "0.0.0",
"@aws-cdk/core": "0.0.0",
"constructs": "^3.3.69"
},
Expand Down
Loading

0 comments on commit a50b049

Please sign in to comment.