AWS Lambda API Application .Net Core Not responding - amazon-web-services

I created an AWS Lambda Application API using AWS Toolkit for .Net Core 3.1. It has 2 Get request that expecting text JSON in a request body and returning text JSON as an output. It does not require any database connection or any other AWS resources. Locally everything works fine, all tests are passing. I publish my app to AWS account using AWS Toolkit which runs Cloud Formation setting file, again no problems, all passing. This creates my AWS Lambda API app with my API endpoint. However, when I try to use I am getting "403 Forbidden" errors:
Other thing I notice is that the default API Gateway type is Edge, I am unsure if that's making a problem. I would like to set it up to Private in cloud formation stuck from .Net Core level. I assume it is something to be change here:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Description": "An AWS Serverless Application that uses the ASP.NET Core framework running in Amazon Lambda.",
"Resources": {
"AspNetCoreFunction": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "AES.Protocol::AES.Protocol.LambdaEntryPoint::FunctionHandlerAsync",
"Runtime": "dotnetcore3.1",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambdaFullAccess"
],
"Events": {
"ProxyResource": {
"Type": "Api",
"Properties": {
"Path": "/{proxy+}",
"Method": "ANY"
}
},
"RootResource": {
"Type": "Api",
"Properties": {
"Path": "/",
"Method": "ANY"
}
}
}
}
}
},
"Outputs": {
"ApiURL": {
"Description": "API endpoint URL for Prod environment",
"Value": {
"Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
}
}
}
}
The previous question related to this API might be helpful.

I manage to find a solution. It seems like CloudFront is not supporting GET request with "body". So changing "GET" to "POST" request fix the problem.

Related

HTTP Error 500 when running cloud scheduler to HTTP trigger cloud function to run pipeline

I'm trying to follow this tutorial about setting up a schedule to trigger your pipeline using a cloud function and scheduler. I've followed the tutorial up to the letter, to my knowledge. I made sure the pipeline runs without errors, and set up the cloud function. For setting up the job:
I set the frequency to 0 9 * * 1
Set the URL to https://us-central1-[redacted].cloudfunctions.net/hello-world-scheduled-pipeline-function
For the Body section, following the guide I set
{
"pipeline_spec_uri": "gs://[redacted]/test/tab_classif_pipeline_test.json",
"parameter_values": {
"greet_name": "test"
}
}
Added OIDC token, set it to a service account that can invoke cloud functions (and other job scheduler permissions), and left all other fields to default.
After trying to run it manually, I get the following error, which I cannot for the life of me interpret:
{
"insertId": "j5h0k0flkeq6j",
"jsonPayload": {
"url": "https://us-central1-[redacted].cloudfunctions.net/hello-world-scheduled-pipeline-function",
"jobName": "projects/[redacted]/locations/us-central1/jobs/hello-world-cloud-scheduler",
"targetType": "HTTP",
"status": "INTERNAL",
"#type": "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"
},
"httpRequest": {
"status": 500
},
"resource": {
"type": "cloud_scheduler_job",
"labels": {
"job_id": "hello-world-cloud-scheduler",
"project_id": "[redacted]",
"location": "us-central1"
}
},
"timestamp": "2022-04-13T15:09:04.120977064Z",
"severity": "ERROR",
"logName": "projects/[redacted]/logs/cloudscheduler.googleapis.com%2Fexecutions",
"receiveTimestamp": "2022-04-13T15:09:04.120977064Z"
}
To my knowledge, I've been following this guide perfectly, so why isn't this working? Is there something wrong with how I set things up in the Body section? What could it be?

AWS Lambda Controller route not matching, with {proxy+} - 404 Not Found

I have a .NET core 3.1 project with a GET endpoint. Locally the route works fine - "/api" GET request returns JSON string.
After publishing to my AWS Lambda function, and invoking the lambda via Postman, I get a 404 Not Found response to the "/api" GET request. Full URL: "https://(lambda domain)/default/MyLambda2/api"
In my project's Startup.cs ConfigureServices and Configure methods, I added "LambdaLogger.Log" statements. My log lines show up in CloudWatch (so I am definitely reaching the app). It's just after that, the route fails.
In ConfigureServices method, I have
services.AddControllers();
In Configure method, I have
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
And in the Controller file
namespace LambdaTest.Controllers
{
[Route("api")]
public class ValuesController : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
}
I have an API Gateway trigger defined for the lambda, with
API endpoint: "https://(lambda domain)/default/MyLambda2/{proxy+}"
API type: REST
Authorization: NONE
Method: ANY
In Resources tab, I have...
/MyLambda2
ANY
/{proxy+}
ANY
OPTIONS
... and I have all Resources deployed to "default" stage (via Actions > Deploy API).
Here is the default auto-generated serverless.template file...
{
"AWSTemplateFormatVersion": "2010-09-09",
"Transform": "AWS::Serverless-2016-10-31",
"Description": "An AWS Serverless Application that uses the ASP.NET Core framework running in Amazon Lambda.",
"Parameters": {},
"Conditions": {},
"Resources": {
"AspNetCoreFunction": {
"Type": "AWS::Serverless::Function",
"Properties": {
"Handler": "LambdaTest::LambdaTest.LambdaEntryPoint::FunctionHandlerAsync",
"Runtime": "dotnetcore3.1",
"CodeUri": "",
"MemorySize": 256,
"Timeout": 30,
"Role": null,
"Policies": [
"AWSLambda_FullAccess"
],
"Events": {
"ProxyResource": {
"Type": "Api",
"Properties": {
"Path": "/{proxy+}",
"Method": "ANY"
}
},
"RootResource": {
"Type": "Api",
"Properties": {
"Path": "/",
"Method": "ANY"
}
}
}
}
}
},
"Outputs": {
"ApiURL": {
"Description": "API endpoint URL for Prod environment",
"Value": {
"Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
}
}
}
}
What could be causing the route to not get picked up in lambda?
Thanks
Found the issue. I needed my route on the controller to be
[Route("MyLambda2/api")]

List Documentation Parts AWS apigateway

Through Terraform I have created an AWS apigateway based on a swagger file.
I that swagger file I have added the specific AWS endpoints to document the API, like:
"x-amazon-apigateway-documentation": {
"documentationParts": [
{
"location": {
"type": "API"
},
"properties": {
"description": "This is the API description"
}
},
{
"location": {
"type": "METHOD",
"method": "GET",
"path": "/foo/{bar}"
},
"properties": {
"description": "This is the method description"
}
}
]
}
Then I have published the documentation version 1.0 through AWS console and I am trying to fetch that documentation via HTTP as stated in :
List Documentation Parts
But, unfortunately, I can't. I am doing a GET to the endpoint
http://apigateway.eu-central1.amazonaws.com/restapis/<TheIdOfMyApiGateway>/documentation/parts
And it doesn't even give me a 4XX code but neither response nor HTTP code at all.
What I am doing wrong?
My bad was a typo in the region.
I was missing a dash, the correct endpoint is:
http://apigateway.eu-central-1.amazonaws.com/restapis/<TheIdOfMyApiGateway>/documentation/parts
With eu-central-1 instead of eu-central1
I check the naming of the regions in AWS Regions

Stack is hung using CloudFormation with SNS-backed CustomResources

I'm trying to learn working of CustomResources in CloudFormation Template. Created simple template to create s3 bucket. But on creating stack, it remains in Create in progress state for long time and no bucket is created.
Is there anything, I'm missing in below validated template:
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "Building A bucket With customeResources in CloudFormation",
"Parameters" : {
"NewBucket": {
"Default": "",
"Description": "S3 bucket containing customer assets",
"Type": "String"
}
},
"Conditions": {
"NewBucket": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "NewBucket"
},
""
]
}
]
}
},
"Resources" : {
"CustomResource": {
"Properties": {
"S3Bucket": {
"Ref": "NewBucket"
},
"ServiceToken": "SNS topic ARN"
},
"Type": "AWS::CloudFormation::CustomResource"
}
},
"Outputs": {
"BucketName": {
"Value": {
"Fn::GetAtt": [ "CustomResource", {"Ref": "NewBucket"} ]
}
}
}
}
It would appear that your SNS-backed custom resource is not sending a response back to cloud formation, and it is stuck waiting for that response.
From Amazon Simple Notification Service-backed Custom Resources:
The custom resource provider processes the data sent by the template
developer and determines whether the Create request was successful.
The resource provider then uses the S3 URL sent by AWS CloudFormation
to send a response of either SUCCESS or FAILED.
When the request is made to the SNS service provider, it include the following object:
{
"RequestType": "Create",
"ServiceToken": "arn:aws:sns:us-west-2:2342342342:Critical-Alerts-development",
"ResponseURL": "https:\/\/cloudformation-custom-resource-response-uswest2.s3-us-west-2.amazonaws.com\/arn%3Aaws%3Acloudformation%3Aus-west-2%3A497903502641%3Astack\/custom-resource\/6bf07a80-d44a-11e7-84df-503aca41a029%7CCustomResource%7C5a695f41-61d7-475b-9110-cdbaec04ee55?AWSAccessKeyId=AKIAI4KYMPPRGIACET5Q&Expires=1511887381&Signature=WmHQVqIDCBwQSfcBMpzTfiWHz9I%3D",
"StackId": "arn:aws:cloudformation:us-west-2:asdasdasd:stack\/custom-resource\/6bf07a80-d44a-11e7-84df-503aca41a029",
"RequestId": "5a695f41-61d7-475b-9110-cdbaec04ee55",
"LogicalResourceId": "CustomResource",
"ResourceType": "AWS::CloudFormation::CustomResource",
"ResourceProperties": {
"ServiceToken": "arn:aws:sns:us-west-2:234234234:Critical-Alerts-development",
"S3Bucket": "test-example-com"
}
}
You will need to send a success/fail response to the ResponseURL provided in the event for Cloud Formation to continue processing.
I would also note that the bucket will not be created unless your custom service provider creates it. The Custom Resource function is only sending the request to the provider.

ApiGateway CloudFormation without lambda

I am trying to create a template so that when i call api/divide/inputvalue, The api sends back response from DynamoDB which corresponds to inputvalue mapping.
Its pretty straight forward since i am fetching value directly from db without any business logic hence I don't need any lambda. But all the examples that I google or all tutorials they are using lambdas and i am now lost that how can i make it working without lambda
This is what I have so far. There is bug in this template right now since I haven't provided Uri in ApiGateway::Method. Which is what I am currently stuck at.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"Deployment": {
"Type": "AWS::ApiGateway::Deployment",
"Properties": {
"RestApiId": { "Ref": "restApiName" },
"Description": "First Deployment",
"StageName": "StagingStage"
},
"DependsOn" : ["restApiMethod"]
},
"restApiMethod": {
"Type": "AWS::ApiGateway::Method",
"Properties": {
"AuthorizationType": "NONE",
"HttpMethod": "GET",
"ResourceId": {"Ref": "apiRestResource"},
"RestApiId": {"Ref": "restApiName"},
"Integration": {
"Type": "AWS",
"IntegrationHttpMethod": "GET",
"IntegrationResponses": [{"StatusCode": 200}],
"Uri": { "Fn::Sub":"arn.aws.apigateway:${AWS::Region}:dynamodb:action/${restApiName.Arn}"}
},
"MethodResponses": [{"StatusCode": 200}]
},
"DependsOn": ["apiRestResource"]
},
"apiRestResource": {
"Type": "AWS::ApiGateway::Resource",
"Properties": {
"RestApiId": {"Ref": "restApiName"},
"ParentId": {
"Fn::GetAtt": ["restApiName","RootResourceId"]
},
"PathPart": "divide"
},
"DependsOn": ["restApiName"]
},
"restApiName": {
"Type": "AWS::ApiGateway::RestApi",
"Properties": {
"Name": "CalculationApi"
}
}
}
}
According to the documentation, the Uri property is structured as follows for AWS service-proxy integration types:
If you specify AWS for the Type property, specify an AWS service that follows the form: arn:aws:apigateway:region:subdomain.service|service:path|action/service_api. For example, a Lambda function URI follows the form: arn:aws:apigateway:region:lambda:path/path. The path is usually in the form /2015-03-31/functions/LambdaFunctionARN/invocations. For more information, see the uri property of the Integration resource in the Amazon API Gateway REST API Reference.
The uri API Gateway property reference provides more details:
For AWS integrations, the URI should be of the form arn:aws:apigateway:{region}:{subdomain.service|service}:{path|action}/{service_api}. Region, subdomain and service are used to determine the right endpoint. For AWS services that use the Action= query string parameter, service_api should be a valid action for the desired service. For RESTful AWS service APIs, path is used to indicate that the remaining substring in the URI should be treated as the path to the resource, including the initial /.
For an AWS service proxy to the dynamodb service calling the Query Action, the Uri should be something like this (using the YAML short-form of Fn::Sub to insert a Ref for the current AWS region):
!Sub "arn:aws:apigateway:${AWS::Region}:dynamodb:action/Query"
As for your broader use-case of using API Gateway to access DynamoDB without using Lambda functions, refer to Andrew Baird's tutorial blog post, "Using Amazon API Gateway as a Proxy for DynamoDB", and translate the specified Management Console steps to corresponding CloudFormation template resources.