I created a lambda function with a API gateway and Cloudfront distribution in the front
in the cloudfront behaviors I disabled caching
this is the lambda function:
exports.handler = async (event) => {
const response = {
statusCode: 200,
body: JSON.stringify('rawQueryString is: ' + event.rawQueryString),
};
return response;
};
calling the api gateway I see the querystring in the lambda response
https://xxx.execute-api.us-east-1.amazonaws.com/api?name=john
rawQueryString is: '?name=john'
calling the cloudfront distribution i can't see the querystring in the lambda response
https://xxx.cloudfront.net/api?name=john
rawQueryString is: ''
I tried with "Origin Request Policy"
but now when i call https://xxx.cloudfront.net/api?name=john
I get
{
"message": "Forbidden"
}
You should setup origin request policies for your cache behavior. You can try with AWS managed Managed-AllViewer policy or create new one just to forward the query strings:
This has been answered properly here
You cannot send Host - so make an Origin Policy passing as much as you want - but do not pass Host ! That's what produces the Forbidden.
https://kuchbhilearning.blogspot.com/2022/10/pass-query-params-from-cloudfront-to.html
We need to enable the cloudfront origin, this can also be done through CDK through addBehaviour or default ones.
Related
I have an ALB that has lambda as target group. Essentially, the lambda that does logic checks and returns a response:
{
'statusCode': 301,
'headers': {
'Location': url,
},
'body': null,
'isBase64Encoded': false
}
The response above will return a 502 bad gateway, which doesn't really help with debugging the issue. Cloudwatch says it returns the response above. The logic before the response works just fine. I would test with a status code 200, content-type application/json and a debugging message, which would return properly to the user. I know ALB has a listener for redirects, but the lambda has to go through logic to properly redirect someone first which requires things from secret manager. So the question stands, are there any other ways to redirect with alb using lambda? I tried searching through documentaries to see if there are any other limitations with lambdas as a target group. Other than the 1 mb payload/request and formatting response payload, I haven't seen anything of notice.
Sadly no. It's not lambdas role in alb to perform any redirections. If you use CloudFront, you can use lambda functions in your distribution to do redirections instead.
What you're aiming to do is possible.
What error message do you get, when you call the lambda directly (e.g. from AWS management console)?
I could successfully test your use case with a lambda with following implementation (node run time):
export const handler = async (event) => ({
statusCode: 302,
headers: {
Location: 'https://your-url/'
}
});
I have a custom domain linked to my test stage in the AWS API gateway.
I have a method as seen in the attached picture and have enabled cors (as also attached in the picture.
The endpoint will call my lambda function (with proxy lambda enabled as well)
I call the api endpoint from my Ionic angular application like so:
axios.defaults.headers.post['Content-Type'] = 'application/json';
return axios.post(url, {
data
}).then((response) => {
if (response.data.status == 'success') {
});
but in my console I get the following error:
Access to XMLHttpRequest at 'https://test.mycustomendpoint.com/auth/v1/?action=login' from origin 'http://localhost' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
I am wondering what I may be doing wrong.
Image11
Image22
This problem only happens when you run the app using serve to solve it just install this chrome extension on your device from here
I am currently playing around a bit with AWS AppSync and I am trying to use the Lambda authoriser feature to do some custom auth for the GraphQL API.
I have the Lambda function set up with the correct resource-based policy to allow AppSync to invoke the function and I have AppSync's Default authorization mode set to invoke my Lambda.
This is my lambda code:
exports.handler = (event) => {
console.log(JSON.stringify(event));
const response = {
isAuthorized: true,
};
console.log(JSON.stringify(response));
return response;
};
Now I am facing the issue that the Lambda authoriser is always giving me the following error when I attempt to run a GraphQL quarry:
Error: Request failed with status code 401
After debugging this problem for two hours I can say the following things:
The GraphQL endpoint is working fine, because if I set the Default authorization mode to API key or Amazon cognito user pool without changing anything else my Query executes successfully.
The lambda function is definitely being invoked whenever I make a request to the API and the lambda also receives the correct event from AppSync.
The Lambda returns {"isAuthorized":true} which means no Authorization Token would result in a 401.
So as far as I can tell everything is as it should but I am still getting the 401 no matter what I do and im getting pretty frustrated.
Whenever you receive an Error: Request failed with status code 401 in your AWS AppSync Console and you were using Lambda Authorizer as your custom Authorizer for your API. Irrespective of what are the frameworks you used to create the Infrastructure i.e., CDK or SAM or Serverless Framework. Check whether you have added these correctly for your Lanbda Authorizer
Check you have added proper policystatement to your Lambda Authorizer
Check you have added permission for your Lambda Authorizer to your API
Eg:
If you are using AWS CDK to create all your AppSync and Lambda Authorizer, Add these two things to solve the above error
lambdaAuth.addToRolePolicy("your policy statement"),
lambdaAuth.addPermission("appsync",{
principal: new ServicePrincipal("appsync.amazonaws.com"),
action: "lambda:InvokeFunction"
})
After some very frustrating debugging I finally figured out that the problem was the Lambda handler function. As it turns out a Node.js lambda handlers should be async.
So changing the lambda to the following code fixes the issue:
exports.handler = async (event) => {
console.log(JSON.stringify(event));
const response = {
isAuthorized: true,
};
console.log(JSON.stringify(response));
return response;
};
I didn't know this, since until no I only used Python for Lambdas, and the problem was hard to spot since the console.log's where still running correctly so I though the function was returning the correct data where as in fact it was returning null.
I've read this doc: https://docs.aws.amazon.com/en_us/lambda/latest/dg/nodejs-prog-model-logging.html and made this lambda:
exports.handler = async (event) => {
// TODO implement
// const response = {
// statusCode: 200,
// body: JSON.stringify('Hello from Lambda!'),
// };
console.log(123321);
console.log(event.Records[0].cf.response);
console.log(event.Records[0].cf.request);
console.log(JSON.stringify(event.Records[0].cf));
console.log(event);
console.log(arguments);
//Get contents of response
const response = event.Records[0].cf.response;
//Return modified response
return response;
};
It works (logs sends to CloudWatch) when I use "test" with fake model, but when I add CloudFront trigger and send request logs isn't send to any CloudWatch.
how to get real (from production) event object from lambda
how to send/get logs from lambda which triggers by CloudFront?
Due to Lambda being triggered by CloudFront, it now becomes a Lambda#Edge, so the CloudWatch Log streams are created in the region where the Lambda instance is called(that's decided by CloudFront).
So following the AWS Lambda#Edge Docs for Troubleshooting, the specific region could be easily determined with the provided shell script.
You can switch the region using dropdown at the header:
I have setup a CloudFront Distribution with an API Gateway as one of the origins and this API Gateway is configured with an AWS IAM authorizer.
When CloudFront url is invoked with Authorization headers, it returns a 403 error.
{
"message": "Missing Authentication Token"
}
However, when the API Gateway url is invoked instead of CloudFront url with the same Authorization headers, it worked.
I've also tried invoking the endpoint without any authorizer via CloudFront url and it worked. Any idea on how to solve this issue.
When provisioning a CloudFront distribution, remember that CloudFront removes most headers from the request by default.
This is done to optimize the cache hit ratio while preventing your origin server from making decisions based on those headers that would not be appropriate for different requests based on other variations (or absence) of those headers, which CloudFront would then serve from cache, inappropriately.
You'll need to whitelist the Authorization header for forwarding to the origin.
Note also that when provisioning API Gateway behind a CloudFront distribution that you control, you'll probably want to deploy your API endpoint as regional and not edge-optimized.
Please see below, in case if anyone is facing this issue when using API Gateway as a secondary origin - behavior instead of default behavior for the Cloudfront Distribution i.e.
forwarding all paths like /api/* requests to API Gateway
serving the remaining paths with an s3 or other default resource like an Application load balancer
I was using AWS CDK to define and deploy AWS API Gateway as a secondary behavior and faced the same issue and I did everything including
forwarding headers and query params
enabling all http request methods
Setting the API gateway as regional
My configuration for the deployment is as follows:
originConfigs: [{
customOriginSource: {
domainName: clientAppBucket.bucketWebsiteDomainName,
originProtocolPolicy: cloudfront.OriginProtocolPolicy.HTTP_ONLY
},
behaviors: [{
isDefaultBehavior: true,
compress: true
}]
},
{
customOriginSource: { domainName: `${api.restApiId}.execute-api.${this.region}.amazonaws.com/prod` },
behaviors: [
{
pathPattern: "/api/*",
allowedMethods: cloudfront.CloudFrontAllowedMethods.ALL,
defaultTtl: cdk.Duration.seconds(0),
forwardedValues: {
queryString: true,
headers: ["Authorization"],
},
},
],
}]
The problem was that Cloudfront prepends the path that we are using as a custom behavior with each request i.e. when we call domain.com/api/something, It will not call ${api.restApiId}.execute-api.${this.region}.amazonaws.com/prod/something. Instead it will call ${api.restApiId}.execute-api.${this.region}.amazonaws.com/prod/api/something.
Therefore, either the stage name of the default API Gateway URL which is usually prod should be equal to the behavior path which we specify i.e /path/* or /api/* or /backend/* etc -> /prod/* or we should have a /path/ as a resource at the top level of RestApi and nest all the resources under it