- Newest
- Most votes
- Most comments
Hello Preston.
Unfortunately API Gateway does not allow creating resources after a greedy path, It is a design feature. You may however use workarounds like Proxy Resources in your API gateway.
When enabled “Proxy Resource” can pass a complete payload to your Lambda Function or Lambda Authoriser. This payload may be passed to your lambda function and provide more context and request tags.
Please try this workaround in a test environment first before migrating or deploying it in a Production environment.
The first step to follow would be to create a new resource in your API with “Proxy resources” enabled, as on the link provided below, [1]. Once your resource is created and ready we will have a path similar to /users/{userid+}.
On your Authorizer configuration you will need to make a few edits; on “Lambda Event Payload” select “Request” and implement your respective Headers as required by your designed Authoriser, see link below, [2]. In my test environment I used Auth as a header and on my lambda Authorizer I caught my Token on event["headers"]["Auth"]; userid on event["pathParameters"]["userid"].
Example Code - Please do excuse my Python. Url path passed on the test environment: GET: …/users/{userid+}/sensitive
try:
token = event["headers"]["Auth"]
methodarn = event["methodArn"]
userid = event["pathParameters"]["userid"]
theuser = userid.split("/")[0]
thepath = userid.split("/")[1]
except:
pass
API Gateway will accept anything after {userid+}, and pass it with {userid+} as one unit ‘event["pathParameters"]["userid”]’ making it necessary for you to handle the request, path mapping and the output or errors accordingly in your code.
You can then use the methodarn as a resource in your policy document returned by your Lambda Authoriser which is a default on API Gateway, all other policies are implicitly denied.
After making changes on any of your API gateway configuration or setting, you will need to Deploy the stage for changes to take effect; the same applies to your Lamda Functions.
Please also note this workaround would be ideal if you have an existing system that was designed with the path patterns (/users/{userid}/sensitive), when implementing a new project please take note and make use of standard API gateway resource paths.
Please also see another documentation below on Authorisation, [3].
Resource Links: [1] Lambda proxy Integration: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format [2] Input to an API Gateway: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-input.html#:~:text=Path%20parameters%20can%20be%20passed,be%20used%20as%20identity%20sources.&text=The%20requestContext%20is%20a%20map,new%20keys%20to%20the%20map. [3] API gateway Lambda Authorisers: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html
This doesn't address the problem. Issues I see with the proposed solution are:
- Doesn't permit alternate routing configurations for endpoints under /user/{userId} such as /user/{userId}/microservice1 and /user/{userId}/microservice2
- I don't want to run the lambda for every call. I want to run the lambda once on the first request by the user, generate the full allow list, respond to the gateway, cache the response so I don't have to create the list again until the cache TTL expires.
My implementation goals are:
- Set a Lambda authorizer called "userGroupAclAuthorizer" on all access controlled endpoints in the API.
- Enable 15m caching in the API gateway for userGroupAclAuthorizer responses.
- userGroupAclAuthorizer returns the complete list of allowed endpoints for the specific user in the "Resources" section of the returned policy with an ALLOW statement.
- Only allowed endpoints are in the policy. Requests to endpoints not present in the policy resource list will be implicitly denied.
- API Gateway caches the "userGroupAclAuthorizer" response so no additional calls to the lambda are required for the duration of the cache TTL.
I have workaround implemented now, but it sacrifices some efficiency and still potentially suffers from wildcard issues under certain circumstances:
- Implement 2 authorizers, one called "userGroupAclAuthorizer" and another called "userGroupAclInstanceAuthorizer".
- "userGroupAclInstanceAuthorizer" will be associated with all endponts that end with a REST path variable (ie GET:/user/{userId}), cache key will be method.request.header.Authorization and context.resourcePath. The authorizer returns only the specific endpoint in the resource policy response if the user is permitted to access this endpoint. This makes it where cache entries are specific to that endpoint. The lambda must be called for each endpoint protected this way during the cache TTL.
- "userGroupAclAuthorizer" will be associate with all endpoints that end with static path elements (ie GET:/user/{userId}/sensitive), authorizer type is token, so the cache key is the authorization header only. This authorizer returns the full set of allowed endpoints excluding those that end with REST path variables. This means that a single call to the lambda can be used for all calls to any endpoints protected this way for the duration of the cache TTL.
This solution suffers from some edge cases where the required wildcards in the resource policies may still match unintended resources, although this would be expected to be rare. It also forces lambda calls for any new call to REST instance endpoints rather than a single call that could be cached for the duration of the TTL.
I hope this provides some more detail on the issue and maybe some alternative paths for implementation.
Relevant content
- asked 8 months ago
- AWS OFFICIALUpdated 6 months ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 6 months ago
- AWS OFFICIALUpdated 2 years ago
Please see extended "answer" as to why this doesn't address the issue.