Cross-Account Lambdas to API Gateway Setup - amazon-web-services

So the scenario is we have 3 different accounts(EDGE, PROD, DEV). I want to create some APIs in EDGE account and integrate them with lambdas in DEV and PROD Account respectively.
I have 2 different stages of API : dev/prod and also have defined integration of API : LAMBDA with target = ${stageVariables.LAMBDA}.
When I mention the full ARN of LAMBDA in stage variables it shows the following error after api hit:
{
"message": "1 validation error detected: Value \'arn:aws:lambda:ap-south-1:XXEDGEACCOUNTXX:function:arn:aws:lambda:ap-south-1:XXDEVACCOUNTXX:function:funcName\' at \'functionName\' failed to satisfy constraint: Member must satisfy regular expression pattern: (arn:(aws[a-zA-Z-]*)?:lambda:)?([a-z]{2}((-gov)|(-iso(b?)))?-[a-z]+-\\d{1}:)?(\\d{12}:)?(function:)?([a-zA-Z0-9-_\\.]+)(:(\\$LATEST|[a-zA-Z0-9-_]+))?"
}
with
target = arn:aws:lambda:ap-south-1:${stageVariables.ACC}:function:${stageVariables.LAMBDA}/invocations
I get error of invalid function ARN or URI while saving it..
Please help.
PS. Permissions policy are attached perfectly fine. Issue is API gateway check Lambda in own account only that's why read only function name and keep account number fixed.

There is a mistake in the below statement
target = arn:aws:lambda:ap-south-1:${stageVariables.ACC}:function:${stageVariables.LAMBDA}/invocations
${stageVariables.LAMBDA} in the above statement is getting resolved to the lambda function arn. Hence there is a validation error.
arn:aws:lambda:ap-south-1:XXEDGEACCOUNTXX:function:arn:aws:lambda:ap-south-1:XXDEVACCOUNTXX:function:funcName
Also, noticed that the target arn your building is incorrect and should be of the below form
A stage variable can be used in place of a Lambda function name, or version/alias, as shown in the following examples.
arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:${stageVariables.<function_variable_name>}/invocations
arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:<function_name>:${stageVariables.<version_variable_name>}/invocations
For more information can go through this link
https://docs.aws.amazon.com/apigateway/latest/developerguide/aws-api-gateway-stage-variables-reference.html

Related

Error: "SQL compilation error: invalid value [aws_private_api_gateway] for parameter 'API_PROVIDER'"

So I have been trying to implement an external UDF for use in Snowflake through AWS API Gateway. I'm running into an error that I have not seen documented anywhere online. The error occurs when trying to create an api integration using api gateway with a private endpoint:
CREATE OR REPLACE API INTEGRATION LAMBDA_API
API_PROVIDER = aws_private_api_gateway
API_AWS_ROLE_ARN = 'arn:aws:iam::************:role/****'
[API_KEY = '****************************************']
API_ALLOWED_PREFIXES = ('https://*******.execute-api.us-****-*.amazonaws.com/******')
ENABLED = true;
I have tried providing the optional arguement API_KEY, but no luck with that either. I essentially followed the steps listed here (more specifically, here) verbatim.
Has anyone encountered this error, or does anyone know where I might be able to learn more about this parameter?
The code does execute if I specify API_PROVIDER as 'aws_api_gateway', but our current architecture requires a vpc configuration.
EDIT 1 - The exact error (also in title):
SQL compilation error: invalid value [aws_private_api_gateway] for parameter 'API_PROVIDER'
EDIT 2 - We noticed that the documentation for altering the API integration mentions that an AWS role ARN is not required for aws_private_api_gateway, removing this from the creation statement did not solve the issue however.

AWS Api Gateway Custom Domain Name with undefined stage

I'm trying to set up a Custom Domain Name in AWS API Gateway where callers have to specify explicitly the stage name after any base path name. It is something I did in the past but now it seems that, since AWS updated the console interface, it is no more possible.
The final url should be like:
https://example.com/{basePath}/{stage}/function
I tried using the console, but stage is now a mandatory field (chose from a drop-down).
I tried using AWS CLI, but stage is again a mandatory field
aws: error: the following arguments are required: --stage
I tried using Boto3, following the documentation (https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigateway.html#APIGateway.Client.create_base_path_mapping) but, even if stage can be specified as 'none' (The name of the API's stage that you want to use for this mapping. Specify '(none)' if you want callers to explicitly specify the stage name after any base path name.), doing this returns an error:
botocore.errorfactory.BadRequestException: An error occurred (BadRequestException) when calling the CreateBasePathMapping operation: Invalid stage identifier specified
What is funny (or frustrating) is that I have some custom domain names created with the old console and that are perfectly working, without any stage defined.
It is still possible to specify only the "API ID" and "Path" and leave out the "stage" parameter. I have tried this both from the console and the CLI:
From console: The "Stage" setting is a drop-down as you mentioned, but can be left blank (don't select anything). If you did select a stage, delete the API mapping and add it again
From CLI: Just tried this as well and works fine for me on CLI version aws-cli/1.18.69 Python/3.7.7 Darwin/18.7.0 botocore/1.16.19
$ aws apigateway create-base-path-mapping --domain-name **** --rest-api-id *** --base-path test
{
"basePath": "test",
"restApiId": "***"
}

How to get all parameters used by the AWS account without providing a parameter name?

When I need to fetch all of the secrets that are stored by AWS Secrets Manager in the AWS account I'm calling listSecrets passing ListSecretsRequest as an argument.
And now I'm looking for a similar method in AWS Systems Manager to get all parameters stored in the AWS account.
I have found a getParameterHistory method in the API documentation but the description looks confusing. The Request syntax states that there is a required Name parameter (The name of a parameter you want to query). But I need to get all parameters without providing a certain name.
I'm getting the following error when calling the method: AWSSimpleSystemsManagementException: 1 validation error detected: Value null at 'name' failed to satisfy constraint: Member must not be null (Service: AWSSimpleSystemsManagement; Status Code: 400; Error Code: ValidationException; Request ID: 0caa3be7-9d85-4671-9515-fdcc45c641d6)
At the same time the API provides a getParameter method that allows to Get information about a parameter by using the parameter name.
What is the correct way to get all parameters used by the AWS account via AWS Secrets Manager similar to the AWS Secrets Manager's listSecrets method without having to provide a parameter name?
Call describeParameters(describeParametersRequest)

Lambda aliases and CloudFront: The function ARN must reference a specific function version

I have a Lambda that is working as a CloudFront Origin Request handler when referenced using an ARN that contains the version (e.g. ...:function:MyFunction:123). I've created a PROD alias to version 123 which I would like to use instead.
Using the ...:function:MyFunction:PROD ARN yields the following error
com.amazonaws.services.cloudfront.model.InvalidLambdaFunctionAssociationException:
The function ARN must reference a specific function version. (The ARN
must end with the version number.) ARN:
...:function:MyFunction:PROD (Service: AmazonCloudFront; Status Code:
400; Error Code: InvalidLambdaFunctionAssociation; Request ID:
d407f350-bc7f-11e9-8498-e7f23762c03e)
Removing the version entirely (i.e. ...:function:MyFunction) which according to the docs should hit latest, using $LATEST or LATEST for the version all fail with the same error.
The documentation that I've found all suggests that this should just work, so I'm not sure what I could have screwed up here. Might it be a problem with permissions on the IAM role I created?
I have to apologize in advance for writing the answer that you were probably not hoping for, but according to AWS, it is unfortunately not currently possible to have CloudFront point to $LATEST or a specific alias of a function when using Labmda#Edge.
According to the official AWS documentation (found under LambdaFunctionARN on https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_LambdaFunctionAssociation.html):
You must specify the ARN of a function version; you can't specify a Lambda alias or $LATEST.
In case the following is an option for you and can also suit your needs, what we usually do at the company I'm a part of (not only the reason discussed in the context of this question) is having both the CloudFront distribution and the Lambda function defined under the same CloudFormation stack (in our case, managed using the Serverless framework). That way, deploying a change for a stack serving a specific environment (e.g production) creates a new version of the Lambda function and updates the CloudFront distribution to be associated with it, automatically.
Sharing just in case it can hopefully serve as an alternative solution.

AWS Lambda error There was an error loading Log Streams

When I go to the Logs page the below error shows.
There was an error loading Log Streams. Please try again by refreshing this page.
Problem is there is another function that is identical except the code that is creating log files no problem.
Any suggestions?
I solved it.
I added CloudwatchLogsFullAccess and then it took some time under an hour and then it was working.
I'm not sure why I needed to do this for the second function but not the first but it's working now.
Below is the link that helped me.
https://blogs.perficient.com/2018/02/12/error-loading-log-streams/
Make sure your Lambda has already logged at least once!
Appears to me that this error occurs if that is not the case - I've tested fresh Lambdas both with and without any log statements to confirm: Without any log statements, a corresponding Log Group for the Lambda does not exist yet; after the first log statement is made, the statement then exists in a seemingly-newly-made corresponding Log Group.
Although this may seem obvious/intuitive after-the-fact, this is how I ran into this scenario: I think before any logging had occurred on my new Lambda, I tried to hook it up to CloudWatch events - I tried after that attempt to see if the Lambda was invoked (by the events) via viewing 'Monitoring' tab -> 'View logs in CloudWatch' button - and that is where I encountered this error. The Lambda had not been invoked [CloudWatch events hookup had failed], so no logging had occurred, and thus there was no corresponding Log Group made yet to examine (when trying to hyperlink into it from the Lambda Configuration).
(Fwiw, I imagine maybe a corresponding Log Group could be manually made before the first logging, but I have not tested that.)
Ensure your Lambda's Execution Role has a Policy that allows writing to CloudWatch Logs from your Lambda.
IAM console -> 'Roles' -> < your Lambda's role > -> 'Permissions' tab -> 'Permissions policies' accordion
Ensure there is a Policy listed that has parameters set like this:
'Service': "CloudWatch Logs"
'Access level': includes at least "Write"
'Resource': your Lambda is not excluded (i.e: its not set to another specific Lambda, or another directory of Lambdas, or another resource type)
'Request condition': does not preclude the context of your given Lambda execution
An example of an "AWS managed policy" that meets these requirements [out-of-the-box, being that it is AWS-managed] is "AWSLambdaBasicExecutionRole". It has these parameters:
'Service': "CloudWatch Logs"
'Access level': "Limited: Write"
'Resource': "All resources"
'Request condition': "None"
If your Role does not have such a policy already, either add a new one or edit and existing one to have the requirements listed here - then this error should be resolved.
For example, in my case before I fixed things, my Lambda's Role had a policy that was based off [AWS-managed] "AWSLambdaBasicExecutionRole", but somehow had a Resource that was limited to a different Lambda (which was my problem - insufficient permission to meet that policy from my different intended Lambda). I fixed this by adding the original [AWS-managed] "AWSLambdaBasicExecutionRole" Policy to my intended Lambda's role (I also deleted the prior-said Policy as it wasn't used by anything else, but that probably wasn't strictly necessary [although nice to tidy up]).
I resolved it by attaching CloudWatchFullAccess policy to the execution role of my lambda function