{"id":2241,"date":"2024-01-07T23:50:04","date_gmt":"2024-01-07T23:50:04","guid":{"rendered":"https:\/\/www.maghilda.com\/staging\/9669\/?p=2241"},"modified":"2024-01-08T00:24:14","modified_gmt":"2024-01-08T00:24:14","slug":"cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito","status":"publish","type":"post","link":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/","title":{"rendered":"HOWTO: Automate builds with  CloudFormation for API Gateway, Cognito, Lambda, and Amplify"},"content":{"rendered":"\n<p>In this tutorial, you will create AWS CloudFormation templates to build a serverless web application using AWS lambda, Amazon API Gateway, Amazon DynamoDB, Amazon Cognito and AWS Amplify. This application enables users to request rides from the <a href=\"http:\/\/www.wildrydes.com\/\">Wild Rydes<\/a> fleet. The application will present users with an HTML-based user interface for indicating the location where they would like to be picked up and will interact with a RESTful web service on the backend&nbsp;to submit the request and dispatch a nearby unicorn. The application will also provide facilities for users to register with the service and log in before requesting rides.&nbsp;<\/p>\n\n\n\n<p>AWS has already provided a great <a href=\"https:\/\/aws.amazon.com\/getting-started\/hands-on\/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito\/\">step-by-step tutorial <\/a>on this web application setup using AWS management console. I have modified this tutorial as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\" style=\"padding-top:0;padding-right:var(--wp--preset--spacing--50);padding-bottom:0;padding-left:var(--wp--preset--spacing--50)\">\n<li>using CloudFormation template instead of AWS management console<\/li>\n\n\n\n<li>instead of using AWS CodeCommit, I am using GitHub.&nbsp;<\/li>\n\n\n\n<li>Additionally, instead of using AWS Access Key ID and Secret Access Key to connect GitHub with AWS Services, I have set up OIDC provider for GitHub, and additionally set up a GitHub action to test the connection from GitHub to AWS when there is a push or pull.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">AWS Services Used:<\/h3>\n\n\n\n<ul class=\"wp-block-list\" style=\"padding-top:0;padding-right:var(--wp--preset--spacing--50);padding-bottom:0;padding-left:var(--wp--preset--spacing--50)\">\n<li>AWS CLI<\/li>\n\n\n\n<li>AWS Lambda<\/li>\n\n\n\n<li>Amazon API Gateway<\/li>\n\n\n\n<li>AWS Amplify<\/li>\n\n\n\n<li>Amazon DynamoDB<\/li>\n\n\n\n<li>Amazon Cognito<\/li>\n\n\n\n<li>AWS CloudTrail<\/li>\n\n\n\n<li>AWS CloudWatch<\/li>\n<\/ul>\n\n\n\n<p>In addition to the above AWS services, we will also be using ARCGIS for maps and GitHub for managing source code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Prerequisites<\/strong><\/h3>\n\n\n\n<ol class=\"wp-block-list\" style=\"padding-right:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<li>Create AWS account and IAM user in the IAM Identity center<\/li>\n\n\n\n<li>AWS CLI is installed<\/li>\n\n\n\n<li>An account with ARCGIS. I signed up for a 21 day free trial<\/li>\n\n\n\n<li>Git is installed<\/li>\n<\/ol>\n\n\n\n<p>This tutorial has the same modules and steps as the AWS tutorial so you can follow along easily.<\/p>\n\n\n\n<ul class=\"wp-block-list\" style=\"padding-right:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<li>Module 1: Host a static website with continuous deployment<\/li>\n\n\n\n<li>Module 2: Manage UsersModule 2: Manage Users<\/li>\n\n\n\n<li>Module 3: Serverless Service Backend<\/li>\n\n\n\n<li>Module 4: Deploy a RESTful API<\/li>\n\n\n\n<li>Module 5: Resource Cleanup<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Module 1: Host a static website with continuous deployment<\/strong><\/h3>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 1: Create a repo<\/strong> on GitHub and clone to your local directory<\/h5>\n\n\n\n<p>Create your git repository on GitHub and name it <strong>wildrydes-site<\/strong><\/p>\n\n\n\n<p>On your machine, create a folder with the same name and then run the following commands on your terminal to connect to your GitHub repo<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>echo \"# wildrydes-site-repo\" &gt;&gt; README.md\ngit init\ngit add README.md\ngit commit -m \"first commit\"\ngit branch -M main\ngit remote add origin https:\/\/github.com\/maghilda\/testrepo.git\ngit push -u origin main<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 2: Populate the git repository<\/strong><\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code>cd \/Users\/maghilda\/Documents\/GitHub\/wildrydes-site\/\naws s3 cp s3:\/\/wildrydes-<strong>us-east-1<\/strong>\/WebApplication\/1_StaticWebHosting\/website .\/ --recursive<\/code><\/pre>\n\n\n\n<p>Once your local system is populated with all the files, push commits to the remote repository on GitHub<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git add .\ngit commit -m 'new files\u2019\ngit push -u origin main<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 3: <\/strong>Set up OIDC and GitHub Actions<\/h5>\n\n\n\n<p>If you configure an&nbsp;<a href=\"https:\/\/openid.net\/connect\/\" target=\"_blank\" rel=\"noreferrer noopener\">OpenID Connect (OIDC)<\/a>&nbsp;identity provider (IdP) inside an AWS account, you can use IAM roles and short-term credentials, which removes the need for IAM user access keys. Using long-term credentials requires you to create IAM users and secure the access keys to prevent their disclosure. A better approach is to use GitHub&#8217;s support for OpenID Connect to authenticate using an IAM role to generate temporary security credentials. This template will perform the following actions<\/p>\n\n\n\n<ul class=\"wp-block-list\" style=\"padding-right:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<li>Create an OIDC provider for GitHub<\/li>\n\n\n\n<li>Create an IAM role and scope the trust policy<\/li>\n\n\n\n<li>Define TrustPolicy for GitHub and Amplify<\/li>\n<\/ul>\n\n\n\n<p>Obtain GitHub thumbprint and replace the below thumbprint if it has changed.<br>Refer:  https:\/\/docs.aws.amazon.com\/IAM\/latest\/UserGuide\/id_roles_providers_create_oidc_verify-thumbprint.html<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">CloudFormation Template for OIDC and GitHub Actions<\/h6>\n\n\n\n<pre class=\"wp-block-code\"><code>AWSTemplateFormatVersion: 2010-09-09\nDescription: test OIDC and GitHub actions\n\nParameters:\n\n  GithubActionsThumbprint:\n    Type: CommaDelimitedList\n    Default: 1b511abead59c6ce207077c0bf0e0043b1382612   \n    \n  AudienceList:\n    Type: CommaDelimitedList\n    Default: sts.amazonaws.com\n \n  SubjectClaimFilters:\n    Type: CommaDelimitedList\n    Default: \"repo:maghilda\/wildrydes-site:ref:refs\/heads\/main\"  #replace with your repo url\n\nMetadata:\n  AWS::CloudFormation::Interface:\n    ParameterGroups:\n      - Label:\n          default: \"GitHub Action Info\"\n        Parameters:\n          - SubjectClaimFilters\n          - GithubActionsThumbprint\n          - AudienceList\n      - Label:\n          default: \"AWS IAM Info\"\n        Parameters:\n          - Path\n          - PermissionsBoundaryARN\n          - ManagedPolicyARNs\n\nResources:\n  GitHubIdentityProvider:\n    Type: AWS::IAM::OIDCProvider\n    Properties:\n      Url: https:\/\/token.actions.githubusercontent.com #URL of the GitHub OIDC IdP\n      ThumbprintList: !Ref GithubActionsThumbprint\n      ClientIdList: !Ref AudienceList\n  GitHubActionAssumeRoleWithAction:\n    Type: AWS::IAM::Role\n    Properties:\n      Description: Service Role for use in GitHub Actions\n      AssumeRolePolicyDocument:\n        Version: \"2012-10-17\"\n        Statement:\n          - Sid: RoleForGitHubActions #for github to work\n            Effect: Allow\n            Principal:\n              Federated: !GetAtt GitHubIdentityProvider.Arn\n            Action:\n              - \"sts:AssumeRoleWithWebIdentity\"\n            Condition:\n              StringEquals:\n                \"token.actions.githubusercontent.com:aud\": !Ref AudienceList\n              StringLike:\n                \"token.actions.githubusercontent.com:sub\": !Ref SubjectClaimFilters\n          - Sid: RoleForAmplify     #for amplify to work\n            Effect: Allow\n            Principal: \n              Service: amplify.amazonaws.com\n            Action: sts:AssumeRole\n\nOutputs:\n  ServiceRoleARN:\n    Description: arn of service role for use in GitHub actions\n    Value: !GetAtt GitHubActionAssumeRoleWithAction.Arn<\/code><\/pre>\n\n\n\n<p>Save the above template as github-actions-oidc-template.yml and create the stack from your terminal<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation create-stack --stack-name testoidc --template-body file:\/\/github-actions-oidc-template.yml --capabilities CAPABILITY_IAM<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation describe-stacks --stack-name testoidc<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code><strong>OUTPUT<\/strong>:\naws cloudformation describe-stacks --stack-name testoidc\n{\n    \"Stacks\": &#91;\n        {\n            \"StackId\": \"arn:aws:cloudformation:us-east-1:123456789012:stack\/testoidc\/5d9295c0-ace5-11ee-94ec-0ea1c2170c63\",\n            \"StackName\": \"testoidc\",\n            \"Parameters\": &#91;\n                {\n                    \"ParameterKey\": \"GithubActionsThumbprint\",\n                    \"ParameterValue\": \"1b511abead59c6ce207077c0bf0e0043b1382612\"\n                },\n                {\n                    \"ParameterKey\": \"AudienceList\",\n                    \"ParameterValue\": \"sts.amazonaws.com\"\n                },\n                {\n                    \"ParameterKey\": \"SubjectClaimFilters\",\n                    \"ParameterValue\": \"repo:maghilda\/wildrydes-site:ref:refs\/heads\/main\"\n                }\n            ],\n            \"CreationTime\": \"2024-01-06T22:46:01.300000+00:00\",\n            \"RollbackConfiguration\": {},\n            \"StackStatus\": \"CREATE_COMPLETE\",\n            \"DisableRollback\": false,\n            \"NotificationARNs\": &#91;],\n            \"Capabilities\": &#91;\n                \"CAPABILITY_IAM\"\n            ],\n            \"Outputs\": &#91;\n                {\n                    \"OutputKey\": \"ServiceRoleARN\",\n                    \"OutputValue\": \"<strong>arn:aws:iam::123456789012:role\/testoidc-GitHubActionAssumeRoleWithAction-yEDYZNzTDIxw<\/strong>\",\n                    \"Description\": \"arn of service role for use in GitHub actions\"\n                }\n            ],\n            \"Tags\": &#91;],\n            \"EnableTerminationProtection\": false,\n            \"DriftInformation\": {\n                \"StackDriftStatus\": \"NOT_CHECKED\"\n            }\n        }\n    ]\n}<\/code><\/pre>\n\n\n\n<p>On successful completion, note the ARN of the AWS GitHubAction role in the output.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 4: Create a GitHub action<\/strong><\/h5>\n\n\n\n<p>GitHub actions are defined as methods that you can use to automate, customize, and run your software development workflows in GitHub. <\/p>\n\n\n\n<ul class=\"wp-block-list\" style=\"padding-right:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<li>On your new repo on GitHub, click Actions and under Get Started with GitHub Actions, click <strong>set up a workflow yourself<\/strong><\/li>\n\n\n\n<li>You can keep the default main.yml file name. The structure will look like this <strong>wildrydes-site<\/strong>\/<a href=\"https:\/\/github.com\/vibhafauver\/wildrydes-site\/tree\/main\/.github\">.github<\/a>\/<a href=\"https:\/\/github.com\/vibhafauver\/wildrydes-site\/tree\/main\/.github\/workflows\">workflows<\/a>\/main.yml in main<\/li>\n\n\n\n<li>Add the following basic workflow to the file<\/li>\n\n\n\n<li>Replace the role arn with your role<\/li>\n\n\n\n<li>Commit changes<\/li>\n<\/ul>\n\n\n\n<p>Refer: https:\/\/aws.amazon.com\/blogs\/security\/use-iam-roles-to-connect-github-actions-to-actions-in-aws\/<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># This is a basic workflow to help you get started with Actions\nname:Connect to an AWS role from a GitHub repository\n\n# Controls when the action will run. Invokes the workflow on push events but only for the main branch\non:\n  push:\n    branches: &#91; main ]\n  pull_request:\n    branches: &#91; main ]\n\nenv:\n  \n  AWS_REGION : &lt;\"us-east-1\"&gt; #Change to reflect your Region\n\n# Permission can be added at job level or workflow level    \npermissions:\n      id-token: write   # This is required for requesting the JWT\n      contents: read    # This is required for actions\/checkout\njobs:\n  AssumeRoleAndCallIdentity:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Git clone the repository\n        uses: actions\/checkout@v3\n      - name: configure aws credentials\n        uses: aws-actions\/configure-aws-credentials@v1.7.0\n        with:\n          role-to-assume: &lt;arn:aws:iam::111122223333:role\/GitHubAction-AssumeRoleWithAction&gt; #change to reflect your IAM role\u2019s ARN\n          role-session-name: GitHub_to_AWS_via_FederatedOIDC\n          aws-region: ${{ env.AWS_REGION }}\n      # Hello from AWS: WhoAmI\n      - name: Sts GetCallerIdentity\n        run: |\n          aws sts get-caller-identity<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Step 5: <strong>Validate&nbsp;<\/strong>your implementation<\/h5>\n\n\n\n<p>If there is a push or pull on the repository\u2019s \u201cmain\u201d branch, the GitHub action that you just created will be invoked. <\/p>\n\n\n\n<p>To test your workflow, <\/p>\n\n\n\n<ol class=\"wp-block-list\" style=\"padding-right:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<li>On your local machine, navigate to the the&nbsp;<strong>wildrydes-site<\/strong>&nbsp;folder and open the&nbsp;<strong>index.html<\/strong>&nbsp;file.&nbsp;<\/li>\n\n\n\n<li>Modify the title line with the following text:&nbsp;<em>&lt;title&gt;Wild Rydes &#8211; Rydes of the Future!&lt;\/title&gt;<\/em><\/li>\n\n\n\n<li>Save the file.&nbsp;<\/li>\n\n\n\n<li>In your terminal window, add, commit your change, and push the change to the git repository again.<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>git add .\ngit commit -m 'test GitHub actions\u2019\ngit push -u origin main<\/code><\/pre>\n\n\n\n<p>Under your GitHub repo, in the Actions tab, you will see if your workflow ran successfully.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img fetchpriority=\"high\" decoding=\"async\" width=\"925\" height=\"745\" src=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM.png\" alt=\"\" class=\"wp-image-2293\" style=\"width:766px;height:auto\" srcset=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM.png 925w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM-300x242.png 300w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM-768x619.png 768w\" sizes=\"(max-width: 925px) 100vw, 925px\" \/><\/figure>\n\n\n\n<p>Audit the role\u2019s use with Amazon CloudTrail logs. Once you have validated the GitHub connection, you can remove the workflow as it is not longer needed for the rest of the tutorial.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 6: Host the website with AWS Amplify<\/strong><\/h5>\n\n\n\n<p>Amplify Console provides a git-based workflow for continuous deployment and hosting of the static web resources including HTML, CSS, JavaScript, and image files which are loaded in the user&#8217;s browser. <\/p>\n\n\n\n<p>Before deploying the website, make sure you provide Amplify access to GitHub repositories by following the steps in AWS document.<br>Refer: https:\/\/docs.aws.amazon.com\/amplify\/latest\/userguide\/setting-up-GitHub-access.html#setting-up-github-app-cloudformation<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-4.30.27-PM-1024x593.png\" alt=\"\" class=\"wp-image-2327\" style=\"width:654px;height:auto\" srcset=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-4.30.27-PM-1024x593.png 1024w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-4.30.27-PM-300x174.png 300w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-4.30.27-PM-768x444.png 768w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-4.30.27-PM.png 1130w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Now deploy the website you&#8217;ve just committed to git via the CloudFormation template.&nbsp;<\/p>\n\n\n\n<h6 class=\"wp-block-heading\">CloudFormation Template for AWS Amplify<\/h6>\n\n\n\n<pre class=\"wp-block-code\"><code>AWSTemplateFormatVersion: 2010-09-09\nDescription: test amplify\n\nParameters:\n\n  accessToken:\n    Type: String\n    Default: ghp_atxHHFEKEFKEFK:DDKDP1NnD8   #replace with your GitHub personal token\n\nResources:\n  AWSAmplify:\n    Type: AWS::Amplify::App\n    Properties:\n      AccessToken: !Ref accessToken\n      BuildSpec: |\n         version: 1\n         frontend:\n            phases:\n              # IMPORTANT - Please verify your build commands\n              build:\n                commands: &#91;]\n            artifacts:\n              # IMPORTANT - Please verify your build output directory\n              baseDirectory: \/\n              files:\n                - '**\/*'\n            cache:\n              paths: &#91;]\n      Description: test amplify\n      EnableBranchAutoDeletion: false\n      IAMServiceRole: \"arn:aws:iam::123456789012:role\/testoidc-GitHubActionAssumeRoleWithAction-yEDYZNzTDIxw\"\n      Name: WildRydesApp\n      Platform: WEB\n      Repository: \"https:\/\/github.com\/maghilda\/wildrydes-site\"\n\n  AmplifyBranch:\n    Type: AWS::Amplify::Branch\n    Properties:\n      BranchName: main\n      AppId: !GetAtt AWSAmplify.AppId\n      Description: Main Branch\n      EnableAutoBuild: true\n      Framework: Web\n      Stage: PRODUCTION\n\nOutputs:\n  DefaultDomain:\n    Value: !GetAtt AWSAmplify.DefaultDomain\n  MyAppId:\n    Value: !GetAtt AWSAmplify.AppId<\/code><\/pre>\n\n\n\n<p>Save the above template as amplify-template.yml and create the stack from your terminal<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation create-stack --stack-name testamplify --template-body file:\/\/amplify-template.yml --capabilities CAPABILITY_IAM<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation describe-stacks --stack-name testamplify<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 7: Validate your website<\/strong><\/h5>\n\n\n\n<ol class=\"wp-block-list\" style=\"padding-right:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<li>On your local machine, navigate to the the&nbsp;<strong>wildrydes-site<\/strong>&nbsp;folder and open the&nbsp;<strong>index.html<\/strong>&nbsp;file.&nbsp;<\/li>\n\n\n\n<li>Modify the title line with the following text:&nbsp;<em>&lt;title&gt;Wild Rydes &#8211; Something new !&lt;\/title&gt;<\/em><\/li>\n\n\n\n<li>Save the file.&nbsp;<\/li>\n\n\n\n<li>In your terminal window, add, commit your change, and push the change to the git repository again.<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>git add .\ngit commit -m 'test amplify\u2019\ngit push -u origin main<\/code><\/pre>\n\n\n\n<p>As soon as you commit changes to GitHub repo, Amplify will start to provision-&gt;build-&gt;deploy your website. Once Amplify has completed the deployment, open the Wild Rydes site from the link on the Amplify console and notice the tab title change.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Module 2: Manage Users<\/strong><\/h3>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 1: Create Amazon Cognito user pool<\/strong><\/h5>\n\n\n\n<p>This template will perform the following actions:<\/p>\n\n\n\n<ul class=\"wp-block-list\" style=\"padding-right:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<li>Create Amazon Cognito user pool<\/li>\n\n\n\n<li>Integrate your website with the user pool<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>AWSTemplateFormatVersion: 2010-09-09\nDescription: test cognito userpools\n\nParameters:\n\n  userPoolName:\n    Type: String\n    Default: WildRydes\n\n  userPoolClientName:\n    Type: String\n    Default: WildRydesWebApp\n\n  usernameAttributes:\n    Type: CommaDelimitedList\n    Default: email\n\n  autoVerifiedAttributes:\n    Type: CommaDelimitedList\n    Default: email\n\n  mfaConfiguration:\n    Type: String\n    Default: \"OFF\"\n                \n  passwordPolicyMinLength:\n    Type: Number\n    Default: 8\n\nResources:\n# BEGIN USER POOL RESOURCES\n  UserPool:\n    Type: AWS::Cognito::UserPool\n    Properties:\n      UserPoolName: !Ref userPoolName\n      Schema:\n        - Name: email\n          Required: true\n          Mutable: true\n      AutoVerifiedAttributes: !Ref autoVerifiedAttributes\n      Policies:\n        PasswordPolicy:\n          MinimumLength: !Ref passwordPolicyMinLength\n          RequireLowercase: true\n          RequireNumbers: true\n          RequireSymbols: true\n          RequireUppercase: true\n      MfaConfiguration: !Ref mfaConfiguration\n      EmailConfiguration:\n          EmailSendingAccount: COGNITO_DEFAULT\n\n# BEGIN USER POOL CLIENT RESOURCES\n  UserPoolClient:\n    Type: AWS::Cognito::UserPoolClient\n    Properties:\n      UserPoolId: !Ref UserPool\n      ClientName: !Ref userPoolClientName\n\nOutputs :\n  UserPoolId:\n    Value: !Ref UserPool\n    Description:  Id for the user pool\n\n  AppClientID:\n    Value: !Ref UserPoolClient<\/code><\/pre>\n\n\n\n<p>Save the above template as userpool-template.yml and create the stack from your terminal<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation create-stack --stack-name testuserpool --template-body file:\/\/userpool-template.yml<\/code><\/pre>\n\n\n\n<p>Note the user pool id and client id for the next step<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Step 2: Update the config file<\/h5>\n\n\n\n<p>The<strong>&nbsp;js\/config.js<\/strong>&nbsp;file contains settings for the user pool ID, app client ID and Region. Update this file with the settings from the user pool and app you created in the previous step. Save, add, commit, and push the file to your Git repository to have it automatically deploy to Amplify Console.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git add .\ngit commit -m 'test userpools\u2019\ngit push -u origin main<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Step 3: Validate your implementation<\/h5>\n\n\n\n<p>Once the Amplify deploy is complete, launch your website and register for a user. You should receive a verification code to complete the registration process. If successful you should be redirected to<em>\u00a0\/ride.html<\/em> and you should see the auth token. Save the auth token in order to create the Amazon Cognito user pool authorizer in the next module.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" width=\"629\" height=\"292\" src=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-04-at-12.54.17-PM.png\" alt=\"\" class=\"wp-image-2325\" style=\"width:472px;height:auto\" srcset=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-04-at-12.54.17-PM.png 629w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-04-at-12.54.17-PM-300x139.png 300w\" sizes=\"(max-width: 629px) 100vw, 629px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Module 3: Serverless Service Backend<\/strong><\/h3>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 1: Create an Amazon DynamoDB table<\/strong><\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code>AWSTemplateFormatVersion: 2010-09-09\nDescription: test dynamodb \n\nParameters:\n  mTableName:\n    Type: String\n    Default: Rides\n\n  billingMode:  \n    Type: String\n    Default: PAY_PER_REQUEST\n\nResources:\n  # BEGIN DYNAMODB RESOURCES\n  MyDynamoDB:\n    Type: AWS::DynamoDB::Table\n    Properties:\n      AttributeDefinitions: \n        - AttributeName: \"RideId\"\n          AttributeType: \"S\"\n      KeySchema: \n        - AttributeName: \"RideId\"\n          KeyType: \"HASH\"\n      TableName: !Ref mTableName\n      BillingMode: !Ref billingMode\n\nOutputs :\n  DynamodDB:\n    Value: !Ref MyDynamoDB\n\n  DynamoDBArn:\n    Value: !GetAtt MyDynamoDB.Arn<\/code><\/pre>\n\n\n\n<p>Save the above template as dynamodb-template.yml and create the stack from your terminal<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation create-stack --stack-name <strong>testdynamodb<\/strong> --template-body <strong>file:\/\/dynamodb-template.yml<\/strong><\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>aws dynamodb list-tables<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>aws dynamodb describe-table --table-name  Rides <\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 2: Create a Lambda function for handling requests<\/strong><\/h5>\n\n\n\n<p>Copy the Lambda function in the AWS tutorial into a new file <strong>requestUnicorn.js<\/strong> in your wildrydes-site project. Then zip the file as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>zip requestUnicorn.zip requestUnicorn.js<\/code><\/pre>\n\n\n\n<p>Create a S3 bucket <strong>m-lambdafunctions<\/strong> and upload <strong>requestUnicorn.zip<\/strong> to this bucket<\/p>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 3: Create an IAM role for your Lambda function<\/strong> and add permissions<\/h5>\n\n\n\n<pre class=\"wp-block-code\"><code>AWSTemplateFormatVersion: 2010-09-09\nDescription: test lambda function \n\nResources:\n  # BEGIN MANAGED POLICY \n  ManagedPolicy:\n    Type: AWS::IAM::ManagedPolicy\n    Properties:\n      PolicyDocument: \n        Version: '2012-10-17'\n        Statement:\n          - Sid: CloudWatchLogs #similar to AWSLambdaBasicExecutionRole\n            Effect: Allow\n            Action:\n              - logs:PutLogEvents\n              - logs:CreateLogGroup\n              - logs:CreateLogStream\n            Resource: \"arn:aws:logs:*:*:*\"\n          - Sid: DynamoDBAccess\n            Effect: Allow\n            Action: dynamodb:PutItem\n            Resource: \"arn:aws:dynamodb:us-east-1:123456789012:table\/Rides\" #replace with your account id\n  # BEGIN LAMBDA IAM RESOURCES\n  WildRydesLambdaRole:\n    Type: 'AWS::IAM::Role'\n    Properties:\n      AssumeRolePolicyDocument:\n        Version: '2012-10-17'\n        Statement:\n          - Effect: Allow\n            Principal:\n              Service:\n                - lambda.amazonaws.com\n            Action:\n              - 'sts:AssumeRole'\n      ManagedPolicyArns:\n          - !Ref ManagedPolicy\n\n  myLambdaFunction:\n    Type: AWS::Lambda::Function\n    Properties:\n      FunctionName: RequestUnicorn\n      Runtime: nodejs16.x\n      Role: !GetAtt WildRydesLambdaRole.Arn\n      Handler: requestUnicorn.handler #filename.handler\n      Code:\n        S3Bucket: m-lambdafunctions  #s3 bucket name\n        S3Key: requestUnicorn.zip   #file uploaded to the s3 bucket\n      Description: test my lambda function\n      TracingConfig:\n        Mode: Active\n\nOutputs :\n  LambdaFunctionName:\n    Value: !Ref myLambdaFunction\n\n  LambdaRoleArn:\n    Value: !GetAtt WildRydesLambdaRole.Arn<\/code><\/pre>\n\n\n\n<p>Save the above template as lambda-template.yml and create the stack from your terminal<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation create-stack \\\n  --stack-name testlambda \\\n  --capabilities CAPABILITY_NAMED_IAM \\\n  --template-body file:\/\/lambda-template.yml<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Step 4: Validate your implementation<\/h5>\n\n\n\n<p>Follow the test procedures in AWS tutorial. The output should look like this<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n  \"statusCode\": 201,\n  \"body\": \"{\\\"RideId\\\":\\\"ryvBjGAhp-5jZJOe27Txig\\\",\\\"Unicorn\\\":{\\\"Name\\\":\\\"Angel\\\",\\\"Color\\\":\\\"White\\\",\\\"Gender\\\":\\\"Female\\\"},\\\"Eta\\\":\\\"30 seconds\\\",\\\"Rider\\\":\\\"the_username\\\"}\",\n  \"headers\": {\n    \"Access-Control-Allow-Origin\": \"*\"\n  }\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Module 4: Deploy a RESTful API<\/strong><\/h3>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>Step 1: Create a new REST API<\/strong><\/h5>\n\n\n\n<p>API Gateway will be the trigger for the lambda function (just like we had s3 trigger in the previous tutorial) when the user requests a ride. The following template will perform these steps:<\/p>\n\n\n\n<ul class=\"wp-block-list\" style=\"padding-right:var(--wp--preset--spacing--50);padding-left:var(--wp--preset--spacing--50)\">\n<li>Create a new API<\/li>\n\n\n\n<li>Create authorizer<\/li>\n\n\n\n<li>Create a resource<\/li>\n\n\n\n<li>Create a method<\/li>\n\n\n\n<li>Deploy the API<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>AWSTemplateFormatVersion: 2010-09-09\nDescription: test API Gateway  \n\nParameters:\n  apiName:\n    Type: String\n    Default: WildRydes\n\n  endPointType:\n    Type: String\n    Default: \"EDGE\"\n\n  roleArn:\n    Type: String\n    Default: \"arn:aws:iam::123456789012:role\/testlambda-WildRydesLambdaRole-JvCwTpjGxiCi\" #replace with your role arn\n\n  authorizerName:\n    Type: String\n    Default: WildRydes\n\n  providerCognitoARN:\n    Type: String\n    Default: \"arn:aws:cognito-idp:us-east-1:123456789012:userpool\/us-east-1_4qA0ngoIL\" #replace with your userpool arn\n\n  authorizerType:\n    Type: String\n    Default: COGNITO_USER_POOLS\n\n  pathPart:\n    Type: String\n    Default: ride\n\n  functionArn:\n    Type: String\n    Default: \"arn:aws:lambda:us-east-1:123456789012:function:RequestUnicorn\"\n\n  \n  uri:\n    Type: String\n    Default: \"arn:aws:apigateway:us-east-1:lambda:path\/2015-03-31\/functions\/arn:aws:lambda:us-east-1:123456789012:function:RequestUnicorn\/invocations\"\n\nResources:\n  RestApi:\n    Type: AWS::ApiGateway::RestApi\n    Properties:\n      ApiKeySourceType: AUTHORIZER\n      EndpointConfiguration:\n        Types:\n        - !Ref endPointType\n      Name: !Ref apiName\n  \n  RestApiAuthorizer:\n    Type: AWS::ApiGateway::Authorizer\n    Properties:\n      AuthorizerCredentials: !Ref roleArn\n      IdentitySource: method.request.header.authorization\n      Name: !Ref authorizerName\n      ProviderARNs: \n        - !Ref providerCognitoARN\n      RestApiId: !Ref RestApi\n      Type: !Ref authorizerType\n\n  RestApiResource:\n    Type: AWS::ApiGateway::Resource\n    Properties:\n      ParentId: !GetAtt RestApi.RootResourceId\n      PathPart: !Ref pathPart\n      RestApiId: !Ref RestApi\n\n  RestApiMethod:\n    Type: AWS::ApiGateway::Method\n    DependsOn:\n      - LambdaApiPerms\n    Properties:\n      ApiKeyRequired: false\n      AuthorizationType: !Ref authorizerType\n      AuthorizerId: !Ref RestApiAuthorizer\n      HttpMethod: POST \n      Integration:\n        IntegrationHttpMethod: POST\n        Type: AWS_PROXY   #Use Lambda Proxy integration\n        Uri: !Ref uri\n        RequestTemplates:\n          application\/json: '{\"statusCode\": 200}'\n        IntegrationResponses:\n          - ResponseTemplates:\n              application\/json: \"{\\\"message\\\": \\\"Hello from API gateway\\\"}\"\n            StatusCode: 200\n        PassthroughBehavior: WHEN_NO_TEMPLATES\n      MethodResponses:\n        - ResponseModels:\n            application\/json: 'Empty'\n          StatusCode: 200\n      ResourceId: !Ref RestApiResource\n      RestApiId: !Ref RestApi\n\n  #Enable API Gateway CORS\n  OptionsMethod:  \n    Type: AWS::ApiGateway::Method\n    Properties:\n      AuthorizationType: NONE\n      ResourceId: !Ref RestApiResource\n      RestApiId: !Ref RestApi\n      HttpMethod: OPTIONS\n      Integration:\n        IntegrationResponses:\n          - StatusCode: 200\n            ResponseParameters:\n              method.response.header.Access-Control-Allow-Headers: \"'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'\"\n              method.response.header.Access-Control-Allow-Methods: \"'POST,OPTIONS'\"\n              method.response.header.Access-Control-Allow-Origin: \"'*'\"\n            ResponseTemplates:\n              application\/json: ''\n        PassthroughBehavior: WHEN_NO_MATCH\n        RequestTemplates:\n          application\/json: '{\"statusCode\": 200}'\n        Type: MOCK\n      MethodResponses:\n        - StatusCode: 200\n          ResponseModels:\n            application\/json: 'Empty'\n          ResponseParameters:\n            method.response.header.Access-Control-Allow-Headers: false\n            method.response.header.Access-Control-Allow-Methods: false\n            method.response.header.Access-Control-Allow-Origin: false\n\n  LambdaApiPerms:\n    Type: AWS::Lambda::Permission\n    Properties:\n      Action: lambda:InvokeFunction\n      FunctionName: !Ref functionArn\n      Principal: apigateway.amazonaws.com\n      SourceArn:\n        !Join\n        - ''\n        - - 'arn:'\n          - !Ref AWS::Partition\n          - ':execute-api:'\n          - !Ref AWS::Region\n          - ':'\n          - !Ref AWS::AccountId\n          - ':'\n          - !Ref RestApi\n          - \/*\/*  \n      SourceAccount: !Ref AWS::AccountId  \n\n  RestApiDeployment:\n      Type: AWS::ApiGateway::Deployment\n      DependsOn:\n        - RestApiMethod\n      Properties:\n        RestApiId: !Ref RestApi\n        #StageName: prod\n\n  # Enable logging of all HTTP requests\n  ApiStage:\n    Type: AWS::ApiGateway::Stage\n    Properties:\n      DeploymentId: !Ref RestApiDeployment\n      MethodSettings:\n        - HttpMethod: '*'\n          LoggingLevel: INFO\n          ResourcePath: \/*\n          DataTraceEnabled: true\n      RestApiId: !Ref RestApi\n      StageName: prod\n\nOutputs:\n  RestApiId:\n    Value: !Ref RestApi\n\n  AuthorizerId:\n    Value: !GetAtt RestApiAuthorizer.AuthorizerId\n\n  ApiUrl:\n    Description: URL of the REST API.\n    Value:\n      Fn::Join:\n      - ''\n      - - https:\/\/\n        - Ref: RestApi\n        - .execute-api.\n        - Ref: AWS::Region\n        - .\n        - Ref: AWS::URLSuffix\n        - \/prod<\/code><\/pre>\n\n\n\n<p>Save the above template as apigateway-template.yml and create the stack from your terminal<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation create-stack \u00a0--stack-name testapigateway\u00a0 --template-body file:\/\/apigateway-template.yml<\/code><\/pre>\n\n\n\n<p>Note the ApiUrl from the output. At this time, you should have all the stacks successfully completed like the below<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"973\" height=\"730\" src=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-07-at-5.39.46-PM.png\" alt=\"\" class=\"wp-image-2338\" style=\"width:817px;height:auto\" srcset=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-07-at-5.39.46-PM.png 973w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-07-at-5.39.46-PM-300x225.png 300w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-07-at-5.39.46-PM-768x576.png 768w\" sizes=\"(max-width: 973px) 100vw, 973px\" \/><\/figure>\n\n\n\n<h5 class=\"wp-block-heading\">Step 2: Update the website config<\/h5>\n\n\n\n<p>Update <strong>\u00a0js\/config.js<\/strong>\u00a0file with the invokeUrl in the previous step. <br>invokeUrl: &#8216; &#8216; \/\/ e.g. https:\/\/rc7nyt4tql.execute-api.us-west-2.amazonaws.com\/prod&#8217;,<\/p>\n\n\n\n<p>Update the ArcGIS version from 4.3 to 4.6 in the\u00a0<strong>ride.html<\/strong>\u00a0file as specified in the AWS tutorial<\/p>\n\n\n\n<p>Save, add, commit, and push the file to your Git repository to have it automatically deploy to Amplify Console.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git add .\ngit commit -m 'update configs\u2019\ngit push -u origin main<\/code><\/pre>\n\n\n\n<h5 class=\"wp-block-heading\">Step 3: Validate your implementation<\/h5>\n\n\n\n<p>Visit\u00a0<strong>\/ride.html\u00a0<\/strong>under your website domain and click <strong>Request Unicorn<\/strong>. You should see a notification in the right sidebar that a unicorn is on its way and then see a unicorn icon fly to your pickup location.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"707\" src=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-07-at-6.01.34-PM-1024x707.png\" alt=\"\" class=\"wp-image-2340\" style=\"width:823px;height:auto\" srcset=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-07-at-6.01.34-PM-1024x707.png 1024w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-07-at-6.01.34-PM-300x207.png 300w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-07-at-6.01.34-PM-768x530.png 768w, https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-07-at-6.01.34-PM.png 1031w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Module 5: Resource Cleanup<\/strong><\/h3>\n\n\n\n<p><strong>Step 1: Delete your app<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation delete-stack --stack-name testamplify<\/code><\/pre>\n\n\n\n<p><strong>Step 2: Delete your Amazon Cognito user pool<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation delete-stack --stack-name testuserpool<\/code><\/pre>\n\n\n\n<p><strong>Step 3: Delete your server less backend<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation delete-stack --stack-name testdynamodb\naws cloudformation delete-stack --stack-name testlambda<\/code><\/pre>\n\n\n\n<p><strong>Step 4: Delete your REST API<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation delete-stack --stack-name testapigateway<\/code><\/pre>\n\n\n\n<p><strong>Step 5: Delete your OIDC provider<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws cloudformation delete-stack --stack-name testoidc<\/code><\/pre>\n\n\n\n<p><strong>Step 6: Delete your CloudWatch Log<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws logs delete-log-group --log-group-name \/aws\/lambda\/RequestUnicorn<\/code><\/pre>\n\n\n\n<p>References:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/aws.amazon.com\/getting-started\/hands-on\/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito\/?ref=gsrchandson\">https:\/\/aws.amazon.com\/getting-started\/hands-on\/build-serverless-web-app-lambda-apigateway-s3-dynamodb-cognito\/?ref=gsrchandson<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/aws.amazon.com\/blogs\/security\/use-iam-roles-to-connect-github-actions-to-actions-in-aws\/\">https:\/\/aws.amazon.com\/blogs\/security\/use-iam-roles-to-connect-github-actions-to-actions-in-aws\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.aws.amazon.com\/amplify\/latest\/userguide\/custom-domains.html\">https:\/\/docs.aws.amazon.com\/amplify\/latest\/userguide\/custom-domains.html<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.aws.amazon.com\/amplify\/latest\/userguide\/getting-started.html\">https:\/\/docs.aws.amazon.com\/amplify\/latest\/userguide\/getting-started.html<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.aws.amazon.com\/dtconsole\/latest\/userguide\/connections-create-github.html\">https:\/\/docs.aws.amazon.com\/dtconsole\/latest\/userguide\/connections-create-github.html<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/aws.amazon.com\/blogs\/opensource\/deploy-aws-cloudformation-stacks-with-github-actions\/\">https:\/\/aws.amazon.com\/blogs\/opensource\/deploy-aws-cloudformation-stacks-with-github-actions\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.stephengream.com\/http-gateway-with-cognito\">https:\/\/www.stephengream.com\/http-gateway-with-cognito<\/a><\/li>\n<\/ul>\n\n\n\n<p>This is the end of the tutorial. You can make linked and nested templates but for simplicity and to follow along the AWS tutorial, I created multiple templates. Hope you got something out of it!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you will create AWS CloudFormation templates to build a serverless web application using AWS lambda, Amazon API Gateway, Amazon DynamoDB, Amazon Cognito and AWS Amplify. This application enables users to request rides from the Wild Rydes fleet. The application will present users with an HTML-based user interface for indicating the location where [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[44,48,12,41,45,47,24],"tags":[51,49,50,52,26],"class_list":["post-2241","post","type-post","status-publish","format-standard","hentry","category-amplify","category-api-gateway","category-aws-tutorial","category-cloudformation","category-cognito","category-dynamodb","category-lambda","tag-amplify","tag-apigateway","tag-cognito","tag-dynamodb","tag-lambda"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify - maghilda<\/title>\n<meta name=\"description\" content=\"Build and automate web apps with AWS CloudFormation templates using AWS lambda, Amazon API Gateway, Amazon DynamoDB, Amazon Cognito and AWS Amplify.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify - maghilda\" \/>\n<meta property=\"og:description\" content=\"Build and automate web apps with AWS CloudFormation templates using AWS lambda, Amazon API Gateway, Amazon DynamoDB, Amazon Cognito and AWS Amplify.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/\" \/>\n<meta property=\"og:site_name\" content=\"maghilda\" \/>\n<meta property=\"article:published_time\" content=\"2024-01-07T23:50:04+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-01-08T00:24:14+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM.png\" \/>\n<meta name=\"author\" content=\"vibs\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"vibs\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/\"},\"author\":{\"name\":\"vibs\",\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/#\\\/schema\\\/person\\\/21009c5e4f1817ea18c81d5004bcec1e\"},\"headline\":\"HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify\",\"datePublished\":\"2024-01-07T23:50:04+00:00\",\"dateModified\":\"2024-01-08T00:24:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/\"},\"wordCount\":1642,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/Screen-Shot-2024-01-06-at-6.08.42-PM.png\",\"keywords\":[\"Amplify\",\"APIGateway\",\"Cognito\",\"DynamoDB\",\"Lambda\"],\"articleSection\":[\"Amplify\",\"API Gateway\",\"AWS Tutorial\",\"CloudFormation\",\"Cognito\",\"DynamoDB\",\"Lambda\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/\",\"url\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/\",\"name\":\"HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify - maghilda\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/Screen-Shot-2024-01-06-at-6.08.42-PM.png\",\"datePublished\":\"2024-01-07T23:50:04+00:00\",\"dateModified\":\"2024-01-08T00:24:14+00:00\",\"description\":\"Build and automate web apps with AWS CloudFormation templates using AWS lambda, Amazon API Gateway, Amazon DynamoDB, Amazon Cognito and AWS Amplify.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/Screen-Shot-2024-01-06-at-6.08.42-PM.png\",\"contentUrl\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/wp-content\\\/uploads\\\/2024\\\/01\\\/Screen-Shot-2024-01-06-at-6.08.42-PM.png\",\"width\":925,\"height\":745},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/#website\",\"url\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/\",\"name\":\"maghilda.com\",\"description\":\"Technology blog focused on cloud computing, emerging technologies, software development and security.\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/#organization\",\"name\":\"maghilda.com\",\"url\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/wp-content\\\/uploads\\\/2023\\\/12\\\/cropped-logo_red.png\",\"contentUrl\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/wp-content\\\/uploads\\\/2023\\\/12\\\/cropped-logo_red.png\",\"width\":512,\"height\":512,\"caption\":\"maghilda.com\"},\"image\":{\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/#\\\/schema\\\/person\\\/21009c5e4f1817ea18c81d5004bcec1e\",\"name\":\"vibs\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/28233c799bf0736fecb2854057b69e52d9bd97b467b55be3406890936003faee?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/28233c799bf0736fecb2854057b69e52d9bd97b467b55be3406890936003faee?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/28233c799bf0736fecb2854057b69e52d9bd97b467b55be3406890936003faee?s=96&d=mm&r=g\",\"caption\":\"vibs\"},\"sameAs\":[\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\"],\"url\":\"https:\\\/\\\/www.maghilda.com\\\/staging\\\/9669\\\/author\\\/obliczte\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify - maghilda","description":"Build and automate web apps with AWS CloudFormation templates using AWS lambda, Amazon API Gateway, Amazon DynamoDB, Amazon Cognito and AWS Amplify.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/","og_locale":"en_US","og_type":"article","og_title":"HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify - maghilda","og_description":"Build and automate web apps with AWS CloudFormation templates using AWS lambda, Amazon API Gateway, Amazon DynamoDB, Amazon Cognito and AWS Amplify.","og_url":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/","og_site_name":"maghilda","article_published_time":"2024-01-07T23:50:04+00:00","article_modified_time":"2024-01-08T00:24:14+00:00","og_image":[{"url":"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM.png","type":"","width":"","height":""}],"author":"vibs","twitter_card":"summary_large_image","twitter_misc":{"Written by":"vibs","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/#article","isPartOf":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/"},"author":{"name":"vibs","@id":"https:\/\/www.maghilda.com\/staging\/9669\/#\/schema\/person\/21009c5e4f1817ea18c81d5004bcec1e"},"headline":"HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify","datePublished":"2024-01-07T23:50:04+00:00","dateModified":"2024-01-08T00:24:14+00:00","mainEntityOfPage":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/"},"wordCount":1642,"commentCount":0,"publisher":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/#organization"},"image":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/#primaryimage"},"thumbnailUrl":"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM.png","keywords":["Amplify","APIGateway","Cognito","DynamoDB","Lambda"],"articleSection":["Amplify","API Gateway","AWS Tutorial","CloudFormation","Cognito","DynamoDB","Lambda"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/","url":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/","name":"HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify - maghilda","isPartOf":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/#primaryimage"},"image":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/#primaryimage"},"thumbnailUrl":"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM.png","datePublished":"2024-01-07T23:50:04+00:00","dateModified":"2024-01-08T00:24:14+00:00","description":"Build and automate web apps with AWS CloudFormation templates using AWS lambda, Amazon API Gateway, Amazon DynamoDB, Amazon Cognito and AWS Amplify.","breadcrumb":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/#primaryimage","url":"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM.png","contentUrl":"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2024\/01\/Screen-Shot-2024-01-06-at-6.08.42-PM.png","width":925,"height":745},{"@type":"BreadcrumbList","@id":"https:\/\/www.maghilda.com\/staging\/9669\/cloudformation-build-website-lambda-apigateway-amplify-dynamodb-cognito\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.maghilda.com\/staging\/9669\/"},{"@type":"ListItem","position":2,"name":"HOWTO: Automate builds with CloudFormation for API Gateway, Cognito, Lambda, and Amplify"}]},{"@type":"WebSite","@id":"https:\/\/www.maghilda.com\/staging\/9669\/#website","url":"https:\/\/www.maghilda.com\/staging\/9669\/","name":"maghilda.com","description":"Technology blog focused on cloud computing, emerging technologies, software development and security.","publisher":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.maghilda.com\/staging\/9669\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.maghilda.com\/staging\/9669\/#organization","name":"maghilda.com","url":"https:\/\/www.maghilda.com\/staging\/9669\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.maghilda.com\/staging\/9669\/#\/schema\/logo\/image\/","url":"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2023\/12\/cropped-logo_red.png","contentUrl":"https:\/\/www.maghilda.com\/staging\/9669\/wp-content\/uploads\/2023\/12\/cropped-logo_red.png","width":512,"height":512,"caption":"maghilda.com"},"image":{"@id":"https:\/\/www.maghilda.com\/staging\/9669\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.maghilda.com\/staging\/9669\/#\/schema\/person\/21009c5e4f1817ea18c81d5004bcec1e","name":"vibs","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/28233c799bf0736fecb2854057b69e52d9bd97b467b55be3406890936003faee?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/28233c799bf0736fecb2854057b69e52d9bd97b467b55be3406890936003faee?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/28233c799bf0736fecb2854057b69e52d9bd97b467b55be3406890936003faee?s=96&d=mm&r=g","caption":"vibs"},"sameAs":["https:\/\/www.maghilda.com\/staging\/9669"],"url":"https:\/\/www.maghilda.com\/staging\/9669\/author\/obliczte\/"}]}},"_links":{"self":[{"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/posts\/2241","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/comments?post=2241"}],"version-history":[{"count":5,"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/posts\/2241\/revisions"}],"predecessor-version":[{"id":2380,"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/posts\/2241\/revisions\/2380"}],"wp:attachment":[{"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/media?parent=2241"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/categories?post=2241"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.maghilda.com\/staging\/9669\/wp-json\/wp\/v2\/tags?post=2241"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}