OpenApiGatewayToLambda - Dynamically inclue ARN for Cognito Pool Authorizer
Is there a way to dynamically include the ARN in the providerArns when using the "x-amazon-apigateway-authorizer" in the open API document?
I've created the cognito pool/scopes/domain/client etc. in CDK, but I just realised nothing is showing in the UI for API Gateway, so I don't think it is linked up to the gateway. I used an example that seemed to setup cognito pool as a standard oauth provider rather than anything AWS specific.
I saw the example here that showed the cognito pool in the provider ARN list, but it required a hard-coded ARN.
It's very possible I'm just doing something wrong in my current code which is causing it to not get attached. Switching to the example in the repo does seem like a much more straightforward option, if it's possible to dynamically add that ARN value somehow as I'd be deploying to multiple accounts/environments so they'd each have a different ARN for the cognito pool.
components:
securitySchemes:
UserPool:
type: oauth2
description: Using Cognito oAuth
x-amazon-apigateway-authorizer:
type: jwt
identitySource: "$request.header.Authorization" # This indicates that the JWT token is passed in the Authorization header of the request
jwtConfiguration:
audience:
- "XXXXXXXXXXXXXXXXXXXXXXXXXX" # This is where you specify the client ID of your Cognito user pool app client
issuer: https://cognito-idp.XX-XXXXXXX-X.amazonaws.com/XX-XXXXXXX-X_xxxxxxxx
Thanks!
Thanks for the feedback. There currently is no way to do what you are looking for with this construct. Any CloudFormation formula you use to dynamically set the arn in the OpenAPI spec file won't be processed since the spec file is not processed by CloudFormation. This is the issue that this construct set out to address for Lambda functions - the construct includes a custom resource that updates the OpenAPI spec with the Lambda function arn's after they are available. That's the primary value of this construct. The custom resource we wrote is basically generic, e.g. it is not limited to Lambda function arn's, but the Construct itself only defines a map for Lambda function arn's. We have discussed adding the ability to map other resource arn's, but to this point haven't had the resources nor seen user demand to prompt us to make the investment.
An alternative path forward would be to use the SpecRestApi class directly and specify the OpenAPI spec as an InlineApiDefinition. This would embed the spec in the CloudFormation template and I think allow you to dynamically reference any arn's (you will probably need a DependsOn to ensure the other resource is created first). There two drawbacks to this approach:
- The OpenAPI spec is no longer a separate file you can manage indpendently. Making the spec an independent artifact gives you a lot of flexibility.
- If your OpenAPI spec becomes large, then embedding it in the CloudFormation template like this may cause your template to grow beyond the 64k limit.
Hi Biff, thanks for the tips! I'll have a look into that SpecRestApi option and using the Fn::Sub method in the API definition - I think I saw a guide that explained overriding the logical IDs in the stacks, then using Sub with the Arn in the yml (https://aws.amazon.com/blogs/devops/deploy-and-manage-openapi-swagger-restful-apis-with-the-aws-cloud-development-kit/)
Another thing I considered was potentially doing a one off lambda as a custom resource (or something in a ci/cd pipeline) to swap the value out in the yml file before the construct is called - it sounds like that's what you already do for the lambda URLs, but it might be more tricky to control the timings of that (after the cognito pool is created but before the API gateway is built) and the alternative you mentioned might be the wiser option here.
Cheers!
Hello,
The custom resource we wrote is basically generic, e.g. it is not limited to Lambda function arn's, but the Construct itself only defines a map for Lambda function arn's.
I guess the change would look something like this: https://github.com/gianmarcocalbi/aws-solutions-constructs/commit/f4135e80274c87a2d705a97102f8a7a176292fea
Then I should be able to pass any token like
new OpenApiGatewayToLambda(this, 'Gateway', {
tokenReplacements: {
USER_POOL_ARN_TOKEN: props.cognitoUserPoolArn, // the arn is still a cdk token
},
// ...
});
and it will get replaced by its actual value just like lambda are.
I am not sure what are the limitations though..