This is part 2 in a series on serverless computing. To read part 1 click here. In this post I will give a brief overview of AWS’s serverless offering.
AWS Amplify + AppSync
Though you can run multiple environments within the same account, I don’t like having to sift through lists of the same resources for different environments. So we went with one account per environment (dev, test, prod) following these basic steps:
- Create a parent account and an associated organization. The parent account will manage billing, auditing (CloudTrail), and user accounts (IAM) for the child accounts.
- Create a child account for shared services (primarily CI/CD in our case).
- Create a child account in the organization for each environment. Each child account is automatically assigned a role with admin priviledges and a trust relationship with the parent account so that users in the parent account can assume that role.
- Create an inline policy for each child environment on a user group in the parent account to allow users in that group to assume the corresponding role in each child account. In english, this allows a user to sign in once and switch to a different account.
Honestly I’m leaving out a lot of detail and it took us a good bit of research and trial and error to get it working. Here are some good resources for more detail:
- Video on architecting a multi-account strategy: https://www.youtube.com/watch?v=71fD8Oenwxc
- Guide for accessing child accounts: https://docs.aws.amazon.com/organizations/latest/userguide/orgsmanageaccounts_access.html
Once you set all this up you can get a “switch role” option on your user dropdown. After you switch to a role you will see a list of recent rolls that you have assumed and you can click on them and assume the role in the corresponding account. I believe that it only keeps the top 5 and the only way to edit them is to crack open the cookie they are stored in or install a chrome extension that will do that for you.
For infrastructure automation AWS offers CloudFormation (CF) which allows you to define your stack via a JSON or YAML template file. These are powerful but rather daunting files to wield. This is probably why they have many related offerings that act as a layer of abstraction on top of it. The main solutions are as follows:
- CF Designer: A drag-and-drop UI (think LucidCharts) that will generate the template file for you.
- Cloud Former: A tool that scans your existing resources and creates the templates to recreate them. Honestly you probably only use it once since once you start using CF to make infrastructure changes you probably want to avoid making changes via the console.
- Serverless Application Model (SAM): SAM is an extension of CF specialized for serverless applications. Think of it as simplified CF for serverless resources. It also comes with a CLI to help you out. There is a related offering called Serverless Application Repository (SAR) which provides reusable stack definitions.
- Amplify: Amplify is many things but in relation to CF it either walks you through wizards or provides you palatable abstractions that it then turns into CF templates which you don’t really have to look at if you don’t want to. You can deploy them with the Amplify console and/or CLI.
- Serverless: This isn’t an AWS product but it worth mentioning due to its popularity. It is a cloud agnostic toolkit for building serverless applications that can help you generate your CF templates among other things.
I feel that the mere presence of so many abstractions is evidence of the pain of managing these monolithic CF templates. You can nest your stacks to break it up a bit… but still.
We ended up picking Amplify for our application. It seems to be the new recommended path and its solution for GraphQL was by far the best. It lets you define the GraphQL schemas outside of the CF template and has awesome decorators that let you specify intended behavior. Then the CLI takes that schema and generates your api, backing tables, resolvers, and a slew of other things. After viewing everything it created I would never want to manage that many things by hand.
Cognito is AWS’s serverless authentication and authorization solution. It consists of a web console where you can administer users, groups, and identities, and an api and associated SDKs for programatic access. One important thing to note about Cognito (as with most AWS services) is that there are limits which you can read more about here. Many of these limits can be increased upon request but it still has an influence on how you make use of its components.
Now we need to setup authorization so that each user is associated with one or more tenants and roles. The grouping mechanisms provided are user pools (limit 1000 per account) and groups (limit 300 per user pool). We can also define custom attributes on users. I hate using things with limits for tenancy since that is theoretically unbounded. It also seemed like a more natural fit to have one user pool for the app and Amplify tooling currently only supports having one per app. After some research we landed on using groups for roles and a custom attribute for tenancy.
The Amplify CLI enables you to quickly create a user pool by running the command below. It will run you through a wizard where you can customize the authentication options and flow. In the end it will create your CF templates and create and configure the user pool when you deploy.
amplify add auth
AWS also provides component libraries for React, Angular, and Vue that help you quickly setup your website to integrate with Cognito. You can also use the Amplify framework directly to perform authentication.
Since we are doing an Angular site and going serverless we want to use static site hosting. In AWS this means dropping our site into an S3 bucket and fronting it with the CloudFront CDN for HTTPS and quicker delivery. For the first pass I set it up manually in the console and it wasn’t too hard.
However we want to do IaC and thankfully the Amplify CLI facilitates that. You can setup hosting by running the command below. It will run you through a wizard where you can customize your hosting. In the end it will generate the CF templates and create and configure your S3 bucket, CloudFront CDN, and HTTPS.
amplify hosting add
You can setup a custom domain in the Amplify console.
For serverless database AWS gives us AppSync which is basically a managed GraphQL api. The api can use Lambda, DynamoDB, or Elasticsearch as a data source. In general you would use DynamoDB but you could use Lambda to source from anywhere and Elasticsearch for quick searching.
You can use the AppSync console to create your schema and resolvers and it will create your corresponding DynamoDB tables for you if you like. Since we want to do IaC we will use the Amplify CLI instead. You can setup the GraphQL api by running the command below. It will run you through a wizard where you can customize your api. In the end it will generate the bare-bones CF templates for your api.
amplify add api
Most of the magic happens in the
Automated deployments (CI/CD)
There are a few options in this department but in the end we want to do IaC so we need to use CloudFormation. We don’t have to use it directly though. On my first run I setup CloudBuild to do the deployments. CloudBuild is AWS’s general purpose managed CI service. However, AWS provides the Amplify console which is basically a managed CI service specialized for Amplify projects.
So I switched to using the Amplify console. Setting up automated deployments on the Amplify console was pretty easy You just connect it to your source code repository (GitHub, BitBucket, GitLab, CodeCommit), do a little bit of configuration, and you are ready to start deploying. The build is configured by the
amplify.yml file which is really similar to other build configuration formats out there (e.g. GitLab, BitBucket). The console also provides a number of convenient features like domain management, notifications, environment variables, access control, and rewrites/redirects.
In the next post I’ll describe the GCP serverless offering and in the final one I’ll provide a comparison. Click below to read on:
Erik is an agile software developer in Charlotte, NC. He enjoys working full-stack (CSS, JS, C#, SQL) as each layer presents new challenges. His experience involves a variety of applications ranging from developing brochure sites to high-performance streaming applications. He has worked in many domains including military, healthcare, finance, and energy.