-
Notifications
You must be signed in to change notification settings - Fork 4k
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
API Gateway: AwsIntegration with Step Functions #1465
Comments
Could we have an example of how this can be achieved? Via the |
I'm struggled with the same problem in typescript. |
@fumiyakk We did it this way, its in python but I think can be translated to any language. class AwsStateMachineIntegration(apig.AwsIntegration):
def __init__(
self,
state_machine: StateMachine,
request_templates: typing.Optional[typing.Dict[str, str]] = None,
integration_responses: typing.Optional[typing.List[apig.IntegrationResponse]] = None,
action_parameters: typing.Optional[typing.Mapping[str, str]] = None,
integration_http_method: typing.Optional[str] = None,
path: typing.Optional[str] = None,
proxy: typing.Optional[bool] = None,
subdomain: typing.Optional[str] = None):
if not integration_responses:
integration_responses = [
apig.IntegrationResponse(
selection_pattern="200",
status_code="200",
response_templates={
"application/json": """{
"executionToken": "$input.json('$.executionArn').split(':')[7].replace('"', "")"
}"""
}
)
]
# This is a velocity template that takes all the params in the url and inject them in the body.
# it also takes the path and inject it in the body as an attribute path
if not request_templates:
request_templates = {
"application/json": """#set($allParams = $input.params())
#set($pathParams = $allParams.get('path'))
#set($inputStr = "")
#set($jsonString = $input.body.substring(1))
#foreach($pathParamName in $pathParams.keySet())
#set($inputStr = $inputStr +'"'+ $pathParamName + '": "' + $util.escapeJavaScript($pathParams.get($pathParamName)) + '"')
#if($foreach.hasNext) #set($inputStr = $inputStr + ',')#end
#end
#if($pathParams.size()>0) #set($inputStr = $inputStr + ",") #end
{"input": "{$util.escapeJavaScript($inputStr) $util.escapeJavaScript($jsonString)",
"stateMachineArn": \"""" + state_machine.state_machine_arn
+ """"
}"""
}
start_execution_role = self._get_start_execution_role(state_machine)
super().__init__(
service="states",
action="StartExecution",
action_parameters=action_parameters,
integration_http_method=integration_http_method,
options=IntegrationOptions(
credentials_role=start_execution_role,
integration_responses=integration_responses,
request_templates=request_templates,
passthrough_behavior=apig.PassthroughBehavior.NEVER
),
path=path,
proxy=proxy,
subdomain=subdomain)
@staticmethod
def _get_start_execution_role(
state_machine: StateMachine) -> iam.Role:
start_execution_policy = iam.Policy(
scope=state_machine,
id=f"Start{state_machine.node.id}Policy",
statements=[
iam.PolicyStatement(
actions=[step_functions.Action.START_EXECUTION.value],
resources=[state_machine.state_machine_arn])])
start_execution_role = iam.Role(
scope=state_machine,
id=f"{state_machine.node.id}ExecutionRole",
assumed_by=iam.ServicePrincipal(
service="apigateway.amazonaws.com"))
start_execution_role.attach_inline_policy(
start_execution_policy)
return start_execution_role I don't have too much time to explain it all at once, but hope it helps. Either way if you don't understand something let me know! |
@jindriago-scf Thank you for helping! |
@fumiyakk Any chance you could share your code? :) |
@awlsring import * as cdk from '@aws-cdk/core';
import * as apigw from '@aws-cdk/aws-apigateway';
import * as iam from '@aws-cdk/aws-iam';
type Arns = { [key: string]: string }
export class SampleApiGatewayStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, Arns: Arns, props?: cdk.StackProps) {
super(scope, id, props);
const api = new apigw.RestApi(this, 'Api', {
restApiName: 'stateApiName',
});
const sampleRole = new iam.Role(this, 'StepFunctionRole',{
assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com')
});
sampleRole.addToPolicy(new iam.PolicyStatement({
resources: ['*'],
actions: ["states:*"]
}));
// Get StepFunctionArn
const str1: string = "#set($inputRoot = $input.path('$')) {"
const str2: string = `"input": "$util.escapeJavaScript($input.json('$'))",`
const str3: string = `"stateMachineArn":"`
const str4: string = `"}`
const templateString: string = str1 + str2 + str3 + Arns["stateMachineArn"] + str4
const requestTemplates = {
"application/json": templateString
}
// Connect stateMachine with api gateway
const stateMachineIntegration = new apigw.AwsIntegration({
service: "states",
action: "sampleAction",
options: {
credentialsRole: sampleRole,
requestTemplates: requestTemplates,
}
});
const process1 = api.root.addResource('preprocessing')
const process2 = process1.addResource('v1')
process2.addMethod('POST', stateMachineIntegration, {
methodResponses: [{
statusCode: '200',
}]
});
}
} |
Hi, I wonder if there is any news related to this or if anyone would have a sample code to share for the apigateway2 integration. |
I did it via L1 API. |
This issue has not received any attention in 1 year. If you want to keep this issue open, please leave a comment below and auto-close will be canceled. |
hi, any updates on this topic? |
Came up as a question on Gitter:
AWS integrations apparently always need a Role. The correct solution is to pass a RoleARN under the
options
key, but this is is validation plus a hint that we could have done locally.Even better, we should make it as easy as on other L2 constructs to construct this required role (by doing so implicitly). We should also look into a way to set up the right permissions automatically.
The text was updated successfully, but these errors were encountered: