;TLDR: Effectively, how to build a backend for Amplify via AWS CDK which consists of an API Gateway and Lambda function.
I am currently attempting to make an Amplify solution as IaC. The application is relatively simple and only uses Amplify, which hosts frontend and acts as a passthrough the to other resources via the amplify library for JS, API Gateway and a Lambda function. The API Gateway passes REST requests to the Lambda function for processing.
As a dummy app, I have created IaC as such:
class AmplifyInfraStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
amplify_app = amplify.CfnApp(self, "MyApp", name='MyAppName')
lambda_function = lambda_.Function(
self,
'MyFunction',
code=lambda_.InlineCode(inline_code),
handler='index.lambda_handler',
runtime=lambda_.Runtime.PYTHON_3_9
)
api = apiGateway.LambdaRestApi(self, 'MyAPI', handler=lambda_function)
Which will create all of the resources I require, with the API Gateway and Lambda function being linked; however, the Amplify resource is effectively on its own and does not recognise the other resources linked resources, like in the backend section of the Amplify AWS Console where it should show 'APIs' and 'Functions'.
I understand this is because I haven't explicitly told them that they should be linked, though reading through the documentation I can't seem to find a way to actually tell Amplify that these resources need to be linked, like I have done for the API Gateway and Lambda in the example above.
My question is, is there a way to use CDK to generate Amplify with a backend containing Functions and APIs? My need for this, as described earlier is so the 'aws-amplify' library in the JS frontend can recognise the linked API to the Amplify resource it's hosted on.
Any help would be appreciated, thanks.
Related
Can you please advise, if there are any issues with using of FastAPI Web Framework in AWS Lambda:
What framework capabilities will be lost if using in AWS Lambda
environment?
Is there any overhead associated with ASGI technology or
anything else, e.g. when we have to use additional libraries like
Magnum?
We have been using the API gateway -> AWS Lambda -> Mangum -> FastApi combo in production for 3-4 months now and have had no issues.
The restrictions come from the fact that Lambda is a sync request/reply setup.
No point doing anything async in your code - AWS lambda will create a container/python process for each request.
No response streaming bodies. (use s3 for files etc)
The overhead is tiny, Mangum is super light ( see how little code is in: https://github.com/jordaneremieff/mangum/tree/main/mangum) its basically just restructuring the input dictionary.
is this possible to get a api gateway using it's arn and then add more endpoints to it ? for example I have a api gateway and it's root path is '/path-one' and more api's are attached to it like '/path-one/one' etc not I want to get this api gateway using it's
rest_api_root_resource_id and then add new api like '/path-one/two' to same path . is this possible ? how i can achieve using python cdk
FOR Example as the same way we access lambda function using arn
self.my_lambda = _lambda.Function.from_function_arn(self, "my-lambda", my_lambda_arn)
in same type of thing for api gateway I am finding. any help would be highly appericiated.
I'm creating an Amazon Managed Airflow (MWAA) using CDK with the setting of webserver_access_mode='PRIVATE_ONLY'. In this mode, AWS creates a VPC interface endpoint and binds an IP address, from the selected VPC private subnets, to them as explained here: https://docs.aws.amazon.com/mwaa/latest/userguide/configuring-networking.html
Now, I want to use those IPs to add a listener to an existing load balancer that I can then use to connect to a VPN, but this doesn't seem to be available as an output attribute/property of aws_cdk.aws_mwaa.CfnEnvironment: https://docs.aws.amazon.com/cdk/api/v1/python/aws_cdk.aws_mwaa/CfnEnvironment.html#aws_cdk.aws_mwaa.CfnEnvironment.NetworkConfigurationProperty
My question is, is there a way to obtain those IPs associated with the aws_cdk.aws_mwaa.CfnEnvironment? Right now I am looking up the results manually after the deployment with CDK and creating the listener but I would prefer to fully automate it in the same CDK construct.
I struggled with this same problem for some time. In the end I used a Custom Resource in my CFN template, passing it the URL of the MWAA webserver. In the Python code associated with the Custom Resource (Lambda) I do a socket.gethostbyname_ex() call, passing the URL as an argument. This call will return a tuple that that you'll have to parse to extract the endpoint addresses.
I made good use of the crhelper libraries (https://aws.amazon.com/blogs/infrastructure-and-automation/aws-cloudformation-custom-resource-creation-with-python-aws-lambda-and-crhelper/), which made things a lot easier.
In the end, I used a lambda function to resolve the webserver URL and register the IP addresses to the target group. The approach is described in the following AWS blog post: https://aws.amazon.com/blogs/networking-and-content-delivery/hostname-as-target-for-network-load-balancers/
The implementation of the lambda function is also available through the following AWS sample code: https://github.com/aws-samples/hostname-as-target-for-elastic-load-balancer
Few days back I asked a question to stack overflow community at about custom construct library Question
Although I didn't got the exact answer I was looking for. But somehow I managed to create a custom construct library. But now I have another query on how to host the CDK App as an API.
Below is the snapshot of custom construct library:
test_ec2 = ec2.Instance(self, "APIInstance",
vpc=my_vpc,
machine_image=ec2.AmazonLinuxImage(
generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX
),
key_name="test-cdk",
instance_name=inst-name
)
If I want to host above AWS CDK Application as an API that will accept a string for the variable inst-name and will create a EC2 instance. I tried creating it as an lambda function but not sure how to manage "node dependencies and python dependencies" at same time.
Can it be done using an already created EC2 Instance(attaching an IAM Role with permission of cloudformation) and accepting HTTP requests (But don't know how?) Is this making sense?
Thank You in advance to all the devs.
There are many ways to do this. I think the simplest would be to syntesize your cloudformation templates and publish them to S3 ahead of time and use API gateway with a REST API and with AWS request type integration that would create the Cloudformation stack.
Here's a tutorial that explains how to build a REST API with AWS API integration: https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-aws-proxy.html
Just this is for SNS:ListTopics action, but you would want cloudformation:CreateStack action instead.
[Derived from AWS ApiGateway Lambda Proxy access Authorizer ]
I´m using an Lambda Proxy and a Cognito User Pool Authorizer in my ApiGateway. With node.js Lambda functions, it's possible access to have access to the authorizer (basically, get the user id, email and stuff) in event.requestContext.authorizer.claims.
But in Python, there's no such object. Exploring the event object and the context object shows there's nothing like requestContext or authorizer, just an identity object that contains Cognito Federated Identities information : for me, it's just null.
I haven't seen any mention of the event.requestContext.authorizr.claims in Python AWS-Lambda functions, and it would be a pain to
use federated identities instead
in API Gateway, set Authorization to AWS_IAM and turn on Invoke with caller credential
drop the proxy integration for a custom integration or
write the lambdas with node.js instead of python
Have you any idea if I'm missing something, if it's not implemented by AWS, if there's an easy workaround, or anything else ?
Thanks a lot for your help !
Here's the context object in python aws-lambda function, in a dictionary-like form :
"aws_request_id":"99XXXXf5-6XXe-1XX8-bXXf-5dXXXXXXXX50",
"function_name":"test_DynamoDB",
"function_version":"$LATEST",
"invoked_function_arn":"arn:aws:lambda:eu-west-3:4XXXXXXXXXX0:function:test_DynamoDB",
"log":"<bound method LambdaContext.log of <__main__.LambdaContext object at 0x7f07bcb21da0>>",
"log_group_name":"/aws/lambda/test_DynamoDB",
"log_stream_name":"2018/06/13/[$LATEST]76XXXXXXXXXXXXXXXXXXXXXXXXXXXXf0",
"memory_limit_in_mb":"128",
"identity":{
"cognito_identity_id":null,
"cognito_identity_pool_id":null
},
"client_context": None
Update
From https://stackoverflow.com/a/44039371/9936457 , it seems the same issue was in C# lambda functions and there's a workaround for it, using System.IO.Streams. Would this solution work in Python, with the right syntax ?