The Lambda Blog

Serverless Cloud Guide

Menu
  • Home
  • Categories
  • Projects
  • About Us
  • Privacy Policy
  • Disclaimer
  • Contact
Menu
aws appsync cloudformation lambda python

AWS AppSync Python Lambda Resolver using Cloudformation

Posted on December 23, 2021August 14, 2022 by user
Navigation » Home » AppSync

This quick tutorial will demonstrate the basics of defining an AppSync Lambda Resolver with Cloudformation. We will use Python to write our Lambda.

Typically AppSync resolvers are defined against their specific data sources – Dynamodb or RDS being the most common – using the GraphQL velocity template language. For the most part – this works just fine – great in fact. If it is possible to resolve all the GraphQL operations for an application simply using CRUD operations using velocity template language – that is the way to go – reduces code bloat and your entire logic can be easily reviewed using the series of schema operations that AppSync is very good at implementing.

And especially against Dynamodb data sources – this is probably going to be the most performant implementation.

Lambda resolvers however are amongst the most powerful features in the already powerful AppSync toolkit. All too often, simply sticking to velocity template language – even with AppSyncs utility classes – we will find ourselves restricted. There are times when more complex business logic and operations simply cannot be done with velocity templates – think something like using encryption/decryption – calling custom libraries – triggering other services like SNS/SQS/Eventbridge – to name a few.

And even if that is not the restriction – sometimes it is just more convenient to use “regular” code.

No matter the reason – Lambda resolvers are a powerful way to extend your AppSync application’s functionality easily.

Lambda Resolvers explained – briefly

Lambda resolvers are no different from any other regular AppSync resolver from a GraphQL schema point of view.

In a typical schema with a selection of queries and mutations – the normal practice is to define a “resolver” for each operation. AppSync knows to invoke the particular resolver when a query or mutation operation is called from the client. And for Dynamodb/RDS resolvers, a velocity template language script is used to do a particular operation.

The prototypical example – a select operation from the client side is used to invoke a resolver where a select query is called against the datasource.

Lambda resolvers follow the same workflow – but instead of defining your Lambda in a velocity template script – you simply point your resolver to the Lambda definition and AppSync will invoke the Lambda.

You can use request mapping and response mapping templates with Lambda resolvers just like regular resolvers and the entire event is available in the Lambda context.

Lets demonstrate how this is done using a Python Lambda.

Before we begin in case you need it this post covers how to create a Python Lambda with Cloudformation.

Defining a sample AppSync schema

We will implement a Lambda resolver for this sample schema.

There is a getData query which expects a single “data” string response back.

AppSyncApi:
    Type: "AWS::AppSync::GraphQLApi"
    Properties:
      Name: "sample-appsync-api"
      AuthenticationType: "API_KEY"

AppSyncGraphQLSchema:
    Type: "AWS::AppSync::GraphQLSchema"
    Properties:
      ApiId: !GetAtt AppSyncApi.ApiId
      Definition: |
        schema {
          query: Query
        }

        type Data {
        	data: String!
        }

        type Query {
        	getData(
        		key: String!
        	): Data!
        }
	  

Defining the Lambda Resolver in Cloudformation

To define a Lambda resolver – we will need to define an AppSync DataSource which will point to our Lambda function.

While we can define a request/response mapping template to perform pre/post operations for the resolver – we do not need to – for this example we will skip it – but keep in mind it is possible to do so.

DataReturningLambda:
    Type: AWS::Serverless::Function
    Properties:
      Architectures:
        - arm64
      Runtime: python3.9
      CodeUri: ./data-lambda/
      Handler: data-lambda.event_handler
      Description: Python Lambda Resolver to return the data string
      FunctionName: data-lambda

AppSyncLambdaDataSource:
    Type: "AWS::AppSync::DataSource"
    Properties:
      ApiId: !GetAtt AppSyncApi.ApiId
      Name: "AppSyncLambdaDataSource"
      Description: "AppSync LambdaData Source referring to the DataReturningLambda"
      Type: "AWS_LAMBDA"
      LambdaConfig:
        LambdaFunctionArn: !GetAtt DataReturningLambda.Arn

GetDataResolver:
    Type: "AWS::AppSync::Resolver"
    Properties:
      ApiId: !GetAtt AppSyncApi.ApiId
      TypeName: "Query"
      FieldName: "getData"
      DataSourceName: !GetAtt AppSyncLambdaDataSource.Name

That’s almost it- all we need to do now is code our Lambda.

We do need to grant our API permissions to invoke the Lambda.

Granting permissions to AppSync to invoke the Lambda

AppSyncApiLambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !GetAtt DataReturningLambda.Arn
      Action: lambda:InvokeFunction
      Principal: appsync.amazonaws.com
      SourceAccount: !Ref 'AWS::AccountId'
      SourceArn: !GetAtt AppSyncApi.Arn

Coding our Python Lambda Resolver

This is of course a very very simple Lambda – but the purpose is to demonstrate the setup for a more complex operation

#data-lambda.py

def event_handler(event, context):
	
	key = event["key"]
	return f"you sent {key}"

Concluding

To see a more complex application using AppSync Lambda resolvers – do check out my post on creating a serverless texting system with AppSync.

Recent Posts

  • Coding a JSON format logger in Python for use as a Lambda Layer package
  • Configuring an S3 Bucket to send events to a Lambda destination for processing
  • How to request a public SSL certificate for a domain name from the AWS Certificate Manager Console
  • Creating automated CloudFormation Stack Build and Deployments with AWS CodePipeline and CodeBuild
  • A concise guide to setting up the AWS command-line libraries on your local development environment
  • How to implement a Lambda Authorizer for an AWS AppSync API and invoke the API with the required Authorization Token
  • Filtering CloudWatch Logs by LogGroups and LogStreams and reading them using Python and the Boto3 SDK
  • Azure AD Multi Tenancy issue in AWS Cognito
  • Setting up Enterprise Federation from Azure Active Directory to Amazon Cognito using Open ID Connect
  • How to Setup IAM Multifactor Authentication (MFA) for the AWS CLI

Categories

  • Amplify
  • API Gateway
  • AppSync
  • AWS CLI
  • CloudFormation
  • CloudWatch
  • Cognito
  • DynamoDB
  • EventBridge
  • KMS
  • Lambda
  • Projects
  • Route 53
  • SES
  • SNS

Post Tags

ACM Amplify API Gateway AppSync AWS CLI Azure Boto3 CloudFormation CloudWatch CodeBuild CodePipeline Cognito DynamoDB EventBridge Firebase IAM KMS Lambda OIDC Project Python Rekognition Route53 S3 SAM SES SNS VPC

©2022 The Lambda Blog