Amazon Web Services Sign-Up & Configuration -  Part 4 of Implementing a RESTful API on AWS
Tags: aws, serverless, rest, cognito
Published: 2021-04-25 11:55:44

Quick recap: this is a soup to nuts series covering implementing a full-featured REST API on AWS from the perspective of a long-time infrastructure engineer with a historical preference for Java-based solutions.

## AWS Setup

### 1) Create your AWS account
Although some of the Serverless Framework videos are outdated, their AWS Account setup video provides a concise summary of how to sign up for a AWS account. 
{% youtube 3rcwUa_H9Ok %}

After that, however, we are going to ignore the Serverless Framework videos and suggestions regarding granting Serverless access to our AWS account. 

### 2) Create Administrative user and group
You should now have an AWS account with a single 'root' user.  

Amazon recommends that, as with OS best practices, you don't use the root account for everyday use, but instead create a separate Administrative user and group.  You'll be using these credentials for your scripted CLI interaction with AWS.  So unless you blindly trust every last random NPM module on the Internet, you'll probably want to go ahead and create these according to Amazon's instructions:

https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started_create-admin-group.html

You'll be (1) activating IAm access, (2) creating a user, and (3) creating an Administrator group.  Note that the website lists two ways to do this; you only need to follow the console steps version.

### 3) Install Amazon's CLI
Once this is done, the next step is installing the Amazon Command Line Interface (CLI).  [Instructions can be found here] (https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html).   We'll install the newest version, which as of April 2021 is version 2 at:

https://awscli.amazonaws.com/AWSCLIV2.pkg

**Note:** the non-sudo "Install for me only" option defaults to an invalid installation location of "/usr/local" -- a directory that requires `root` permission (unlike /usr/local/bin) and therefore causes the installation to fail.  So either fix this by changing the default location (e.g. to ~/Applications) and creating symlinks as described in the instructions (e.g. `ln -s ~/Applications/aws-cli/aws /usr/local/bin/aws` and `ln -s ~/Applications/aws-cli/aws_completer /usr/local/bin/aws_completer`) or install for all users on the computer if you have `root` access.

Once this is done, go ahead and verify installation of the CLI:

```shell
$ which aws
/usr/local/bin/aws 
$ aws --version
aws-cli/2.1.25 Python/3.7.4 Darwin/20.3.0 exe/x86_64 prompt/off
```

### 4) Provide Your AWS Credentials to AWS CLI
With the CLI installed, we now need to provide it our credentials so that it can interact with AWS services.  Basically, each IAM user account has cryptographic keys that are used to authenticate every request to AWS.  Amazon has an explanation here:

https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html

We are going to run `aws configure` and provide our keys, which can be found by going to AWS's IAm user list page:

https://console.aws.amazon.com/iam/home#/users

then clicking our Administrator, 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjp56fuwmkvi8h69r24y.png)
then selecting the "Security credentials"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/382tevpaf6i5vx0wskxx.png)
Scroll down and select "Create Access Key." 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zs1sfz3m95inczdz7ye.png)
 This will create an (1) access key; and (2) secret key; pair.  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z22enjxwyerh4k778wvk.png)*Note the various security warnings about keeping this information secret.* (I immediately deleted this pair after creating it for this example.). Also note that you need to either copy/paste both somewhere or download the csv and store it in a safe place, as the secret key is unrecoverable.

Now, switch back to `terminal`, run `aws configure`, and provide our credentials:
```shell
$ aws configure
AWS Access Key ID [None]: <Our access key id, e.g. AKIA....>
AWS Secrete Access Key [None]: <Our secret access key>
Default region name [None]: <your region, e.g. 'us-east-2'>
Default output format [None]: <just hit enter, default is json>
```
The AWS CLI will now have created two files storing this information: (1) `~/.aws/config` and (2) `~/.aws/credentials`.  You should now be able to run:

```shell
$ aws iam list-users
```
and receive a list of the AWS IAm users you have created (in this case, just 'Administrator').

### 5) Create our Empty Serverless Framework Project
We are almost done.  Our last step is to create our skeleton Serverless Framework project.  Make sure you are in whatever directory you keep your workspaces (e.g. `~/workspace/`). Go ahead and run `serverless`.  We will (1) create a new project; (2) of type 'AWS Node.js'; and (3) called 'MyRESTProject'.  I personally (1) don't enable autoupdate of the Serverless Framework; and (2) turn on command line completion.

```shell
$ serverless
Serverless: No project detected. Do you want to create a new one? (Y/n) Y
Serverless: What do you want to make? (Use arrow keys)
> AWS Node.js
  AWS Python
  Other
Serverless: What do you want to call this project? MyRESTProject

Project successfully created in 'MyRESTProject' folder.

Serverless: Would you like the Framework to update automatically? (Y/n) n

Serverless: Would you like to setup a command line <tab> completion? (Y/n) Y

Serverless: Which Shell do you use? (use arrow keys)
  bash
> zsh
  fish
Serverless: We will install completion to ~/.zshrc, is it okay ? (Y/n) Y
```
We can now go into our project folder and see we have an empty skeleton:

```shell
$ cd MyRESTProject
$ ls
handler.js    serverless.yml
```

Now let's verify everything is working by deploying our empty skeleton to AWS using the `serverless deploy` command.

```shell
$ serverless deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
........
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service myrestproject.zip file to S3 (392 B)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...............
Serverless: Stack update finished...
Service Information
service: myrestproject
stage: dev
region: us-east-1
stack: myrestproject-dev
resources: 6
api keys:
  None
endpoints:
  None
functions:
  hello: myrestproject-dev-hello
layers:
  None
```
We can further verify the deployment using AWS's CLI (be sure to specify the right region as listed in your output above):

```shell

$ aws cloudformation list-stacks --stack-status-filter UPDATE_COMPLETE --region us-east-1     
{
    "StackSummaries": [
        {
            "StackId": "arn:aws:cloudformation:us-east-1:--------:stack/myrestproject-dev/----------------",
            "StackName": "myrestproject-dev",
            "TemplateDescription": "The AWS CloudFormation template for this Serverless application",
            "CreationTime": "2021-04-25T14:38:32.549000+00:00",
            "LastUpdatedTime": "2021-04-25T14:39:07.745000+00:00",
            "StackStatus": "UPDATE_COMPLETE",
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            }
        }
    ]
}
```
Now we will go ahead and undeploy the test from AWS using `serverless remove`.
```shell
$ serverless remove
Serverless: Getting all objects in S3 bucket...
Serverless: Removing objects in S3 bucket...
Serverless: Removing Stack...
Serverless: Checking Stack delete progress...
..........
Serverless: Stack delete finished...

Serverless: Stack delete finished...
```
And we can verify it uninstalled
```shell
$ aws cloudformation list-stacks --stack-status-filter DELETE_COMPLETE --region us-east-1
{ 
    "StackSummaries": [
        {
            "StackId": "arn:aws:cloudformation:us-east-1:---------:stack/myrestproject-dev/---------",
            "StackName": "myrestproject-dev",
            "TemplateDescription": "The AWS CloudFormation template for this Serverless application",
            "CreationTime": "2021-04-25T14:38:32.549000+00:00",
            "LastUpdatedTime": "2021-04-25T14:39:07.745000+00:00",
            "DeletionTime": "2021-04-25T14:43:25.069000+00:00",
            "StackStatus": "DELETE_COMPLETE",
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            }
        },
```

Next time, we'll go about explaining these files and then altering our directory structure to make it more useable.