AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: An Amazon API Gateway REST API that integrates with a Kinesis Data Stream. Resources: KinesisStream: Type: AWS::Kinesis::Stream Properties: ShardCount: 1 APIGatewayRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Action: - 'sts:AssumeRole' Effect: Allow Principal: Service: - apigateway.amazonaws.com Policies: - PolicyName: APIGatewayKinesisPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - 'kinesis:PutRecord' - 'kinesis:PutRecords' - 'kinesis:GetShardIterator' - 'kinesis:GetRecords' Resource: !Sub - '${varStreamArn}*' - varStreamArn: !GetAtt KinesisStream.Arn Api: Type: 'AWS::ApiGateway::RestApi' Properties: Name: apigw-kinesis-integration Description: Kinesis integration REST API streams: Type: 'AWS::ApiGateway::Resource' Properties: RestApiId: !Ref Api ParentId: !GetAtt Api.RootResourceId PathPart: 'streams' streamName: Type: 'AWS::ApiGateway::Resource' Properties: RestApiId: !Ref Api ParentId: !Ref streams PathPart: '{stream-name}' record: Type: 'AWS::ApiGateway::Resource' Properties: RestApiId: !Ref Api ParentId: !Ref streamName PathPart: 'record' records: Type: 'AWS::ApiGateway::Resource' Properties: RestApiId: !Ref Api ParentId: !Ref streamName PathPart: 'records' sharditerator: Type: 'AWS::ApiGateway::Resource' Properties: RestApiId: !Ref Api ParentId: !Ref streamName PathPart: 'sharditerator' recordMethodPost: Type: 'AWS::ApiGateway::Method' Properties: RestApiId: !Ref Api ResourceId: !Ref record HttpMethod: PUT ApiKeyRequired: false AuthorizationType: NONE Integration: Type: AWS Credentials: !GetAtt APIGatewayRole.Arn # Should always be POST when integrating with AWS services IntegrationHttpMethod: POST # More info: https://docs.aws.amazon.com/apigateway/api-reference/resource/integration/ Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:kinesis:action/PutRecord' PassthroughBehavior: WHEN_NO_TEMPLATES RequestTemplates: application/json: !Sub | { "StreamName": "$input.params('stream-name')", "Data": "$util.base64Encode($input.json('$.Data'))", "PartitionKey": "$input.path('$.PartitionKey')" } IntegrationResponses: - StatusCode: '200' MethodResponses: - StatusCode: '200' recordsMethodPost: Type: 'AWS::ApiGateway::Method' Properties: RestApiId: !Ref Api ResourceId: !Ref records HttpMethod: PUT ApiKeyRequired: false AuthorizationType: NONE Integration: Type: AWS Credentials: !GetAtt APIGatewayRole.Arn # Should always be POST when integrating with AWS services IntegrationHttpMethod: POST # More info: https://docs.aws.amazon.com/apigateway/api-reference/resource/integration/ Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:kinesis:action/PutRecords' PassthroughBehavior: WHEN_NO_TEMPLATES RequestTemplates: application/json: !Sub | { "StreamName": "$input.params('stream-name')", "Records": [ #foreach($elem in $input.path('$.records')) { "Data": "$util.base64Encode($elem.data)", "PartitionKey": "$elem.partition-key" }#if($foreach.hasNext),#end #end ] } IntegrationResponses: - StatusCode: '200' MethodResponses: - StatusCode: '200' sharditeratorMethodGET: Type: 'AWS::ApiGateway::Method' Properties: RestApiId: !Ref Api ResourceId: !Ref sharditerator HttpMethod: GET ApiKeyRequired: false AuthorizationType: NONE RequestParameters: method.request.querystring.shard-id: false Integration: Type: AWS Credentials: !GetAtt APIGatewayRole.Arn # Should always be POST when integrating with AWS services IntegrationHttpMethod: POST # More info: Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:kinesis:action/GetShardIterator' PassthroughBehavior: WHEN_NO_TEMPLATES RequestTemplates: application/json: !Sub | { "ShardId": "$input.params('shard-id')", "ShardIteratorType": "TRIM_HORIZON", "StreamName": "$input.params('stream-name')" } IntegrationResponses: - StatusCode: '200' MethodResponses: - StatusCode: '200' recordsMethodGET: Type: 'AWS::ApiGateway::Method' Properties: RestApiId: !Ref Api ResourceId: !Ref records HttpMethod: GET ApiKeyRequired: false AuthorizationType: NONE RequestParameters: method.request.header.shard-Iterator: false Integration: Type: AWS Credentials: !GetAtt APIGatewayRole.Arn # Should always be POST when integrating with AWS services IntegrationHttpMethod: POST # More info: Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:kinesis:action/GetRecords' PassthroughBehavior: WHEN_NO_TEMPLATES RequestTemplates: application/json: !Sub | { "ShardIterator": "$input.params('Shard-Iterator')" } IntegrationResponses: - StatusCode: '200' MethodResponses: - StatusCode: '200' ApiDeployment: Type: 'AWS::ApiGateway::Deployment' DependsOn: - recordMethodPost Properties: RestApiId: !Ref Api StageName: 'dev' Outputs: ApiRootUrl: Description: Root Url of the API Value: !Sub - 'https://${ApiId}.execute-api.${AWS::Region}.amazonaws.com/dev' - ApiId: !Ref Api KinesisStream: Description: Kinesis Data Stream name Value: !Ref KinesisStream