<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MJ</title>
    <description>The latest articles on DEV Community by MJ (@mengjiann).</description>
    <link>https://dev.to/mengjiann</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F148813%2Fc97085fc-bca7-46bd-a721-f00c248ec26e.png</url>
      <title>DEV Community: MJ</title>
      <link>https://dev.to/mengjiann</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mengjiann"/>
    <language>en</language>
    <item>
      <title>Using Parameter Store for Workflow on AWS Step Functions</title>
      <dc:creator>MJ</dc:creator>
      <pubDate>Sat, 08 Jun 2019 09:10:21 +0000</pubDate>
      <link>https://dev.to/mengjiann/using-parameter-store-for-workflow-on-aws-step-functions-4n2g</link>
      <guid>https://dev.to/mengjiann/using-parameter-store-for-workflow-on-aws-step-functions-4n2g</guid>
      <description>&lt;p&gt;Workflow in AWS Step Functions is represented by a state machine which consists of a number of states (steps), their relationships and their input and output. When we are constructing the state machine using &lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html" rel="noopener noreferrer"&gt;Amazon States Language&lt;/a&gt;, we might define the application secrets as part of the state machine code. &lt;/p&gt;

&lt;p&gt;One of the possible situations is that we are using a &lt;code&gt;Pass&lt;/code&gt; state to prepare an input JSON for the next state. In the following example, we are passing the remote FTP username and password to the next state, which is a Lambda function to download files from remote FTP server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"ftp-download-lambda-config": {
      "Type": "Pass",
      "Result": {
          "ftpHost" : "ftp-server.com",
          "ftpUsername" : "username",
          "ftpPassword" : "password",
          "withDecryption": true
      },
      "ResultPath": "$",
      "Next": "ftp-download-lambda"
},
"ftp-download-lambda": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:xxx:xxx:function:ftp-download-lambda",
      "Next": "next-step"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will raise a concern if we are to version control the state machine code into any version control system like Git. It is because the application secrets(the FTP username and password) will be exposed to the users who have access to the codebase. As a good security practise, it is advisable to store the secrets in a separate environment, which will ensure that it is safe with limited access and possible encrypted where they are stored.  &lt;/p&gt;

&lt;p&gt;There are few prominent services in market: &lt;strong&gt;Vault&lt;/strong&gt;(from Hashicorp), &lt;strong&gt;Secrets Manager&lt;/strong&gt; and &lt;strong&gt;Parameter Store&lt;/strong&gt; (from AWS). Since a managed service is preferred, Vault will not be taken into consideration. Comparing Secrets Manager with Parameter Store, Secrets Manager costs $0.40 per secret per month $0.05 per 10,000 API calls and Parameter Store costs nothing for usage. Although Secrets Manager comes with a secret rotation feature which allows you to automatically rotate API keys, passwords and more, it is not required for our requirement. Therefore, AWS &lt;strong&gt;Parameter Store&lt;/strong&gt; is more preferable for this use case. &lt;/p&gt;

&lt;p&gt;So, once we have decided to store our secrets in the AWS Parameter Store, we have to modify our application(Lambda function in this case) to accept the reference of secrets stored in Parameter Store and retrieve the secrets from Lambda function. The change in the state machine code is showed as below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"ftp-download-lambda-config": {
      "Type": "Pass",
      "Result": {
          "ftpHost" : "ftp-server.com",
          "ftpUsername" : "&amp;lt;Reference to username in Parameter Store&amp;gt;",
          "ftpPassword" : "&amp;lt;Reference to password in Parameter Store&amp;gt;",
          "withDecryption": true
      },
      "ResultPath": "$",
      "Next": "ftp-download-lambda"
},
"ftp-download-lambda": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:xxx:xxx:function:ftp-download-lambda",
      "Next": "next-step"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or we can have additional Lambda function to retrieve the secrets from Parameters Store and pass the output to the next state in the state machine. Thus, the existing Lambda functions/tasks can remain as it is with the usage of new Lambda functions. The usage of new Lambda function is showed as below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"ssm-parameters-getter-lambda-config": {
      "Type": "Pass",
      "Result": {
          "param": [
            "parameters-store-ftpUsername",
            "parameters-store-ftpPassword"
          ],
          "withDecryption": true
      },
      "ResultPath": "$",
      "Next": "ssm-parameters-getter-lambda"
},
"ssm-parameters-getter-lambda": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:xxx:xxx:function:ssm-parameters-getter-lambda",
      "Next": "ftp-download-lambda"
},
"ftp-download-lambda": {
      "Type": "Task",
      "Parameters" : {
        "ftpHost": "ftp-server.com",
        "ftpUsername.$": "$.parameters-store-ftpUsername",
        "ftpPassword.$": "$.parameters-store-ftpPassword",
      },
      "Resource": "arn:aws:lambda:xxx:xxx:function:ftp-download-lambda",
      "Next": "next-step"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;ssm-parameters-getter-lambda&lt;/code&gt; accepts the following as input:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "param": [
    "random-input-a",
    "random-input-b"
  ],
  "withDecryption": true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And produce an object with param name as attribute and value from parameter store. The value can be&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "random-input-a": "&amp;lt;Value from Parameter Store&amp;gt;"
  "random-input-b": "&amp;lt;Value from Parameter Store&amp;gt;"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Lambda function is open sourced on Github. It can be deployed manually to your AWS account using the source code: index.js or deploy directly from the AWS &lt;strong&gt;Serverless Application Repository&lt;/strong&gt; with name: &lt;code&gt;ssm-parameters-getter-lambda&lt;/code&gt;. Remember to check &lt;strong&gt;Show apps that create custom IAM roles or resource policies&lt;/strong&gt; as if this Lambda requires additional role.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mengjiann" rel="noopener noreferrer"&gt;
        mengjiann
      &lt;/a&gt; / &lt;a href="https://github.com/mengjiann/ssm-parameters-getter-lambda" rel="noopener noreferrer"&gt;
        ssm-parameters-getter-lambda
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      To retrieve parameters from AWS Systems Manager's Parameter Store.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;ssm-parameters-getter-lambda&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;To retrieve parameters from AWS Systems Manager's Parameter Store.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Use case&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;The best use case is to place this before the state in a Step Function's workflow that accepts configuration as input such as username and password. As such, the application secrets are kept safely in AWS Parameter Store rather than in the Step Function's state machine code.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Parameters Access Restriction&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Following the principle of least privilege, there are two options that allows restriction on the AWS Lambda function to access certain parameters from the Parameters Store.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ParametersPrefix - Only allow access to parameters with certain prefix in the Parameters Store.&lt;/li&gt;
&lt;li&gt;Tag Keys List - Only allow access to parameters with certain tags for the parameters. Allows comma-delimited list of tag keys.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Sample Input and Output&lt;/h1&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Input&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;{
  "param": [
    "random-input-a",
    "random-input-b"
  ],
  "withDecryption": true
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Output&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;{
  "random-input-a": "&amp;lt;Value from Parameter Store&amp;gt;"
  "random-input-b": "&amp;lt;Value from Parameter Store&amp;gt;"
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mengjiann/ssm-parameters-getter-lambda" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>awsstepfunctions</category>
      <category>awsparameterstore</category>
    </item>
    <item>
      <title>Key Takeaway of Publishing Lambda Function using Serverless Application Repository (SAR)</title>
      <dc:creator>MJ</dc:creator>
      <pubDate>Sun, 26 May 2019 08:03:06 +0000</pubDate>
      <link>https://dev.to/mengjiann/key-takeaway-of-publishing-lambda-function-using-serverless-application-repository-sar-3m6m</link>
      <guid>https://dev.to/mengjiann/key-takeaway-of-publishing-lambda-function-using-serverless-application-repository-sar-3m6m</guid>
      <description>&lt;p&gt;The Serverless Application Repository (SAR) is an easy way for the developers to find and deploy existing application in the AWS Cloud. For more info, refer to &lt;a href="https://docs.aws.amazon.com/serverlessrepo/latest/devguide/what-is-serverlessrepo.html"&gt;official guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One of more popular use cases now is to share the Lambda function with the community. After being published on the AWS SAR, anyone can just deploy the Lambda function directly into their account with just a few clicks. &lt;/p&gt;

&lt;p&gt;There are few ways of publishing on SAR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Management Console&lt;/li&gt;
&lt;li&gt;AWS SAM command line interface (AWS SAM CLI)&lt;/li&gt;
&lt;li&gt;AWS SDKs to upload the code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The easy way is to do it through the &lt;strong&gt;Management Console&lt;/strong&gt; and here are some key take-aways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Only applications created in &lt;code&gt;us-east-1&lt;/code&gt; or &lt;code&gt;us-east-2&lt;/code&gt; allows sharing/visible to the public. Applications created in other regions can be shared privately using &lt;strong&gt;accounts number&lt;/strong&gt;. &lt;code&gt;Semantic version&lt;/code&gt; is also required for publicly published application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that you have created a bucket to host your Lambda code artifact (archive.zip) and amended the bucket policy with the following:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service":  "serverlessrepo.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::&amp;lt;your-bucket-name&amp;gt;/*"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Description and License info on the SAR is compulsory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The most important one is to create a valid AWS Serverless Application Model (AWS SAM) that define the AWS resources. The full documentation is &lt;a href="https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md"&gt;here&lt;/a&gt;. But, these are some samples on my Github: &lt;br&gt;
-- &lt;a href="https://github.com/mengjiann/aws-lambda-sqs/blob/master/template-sar.yaml"&gt;Example 1&lt;/a&gt; - This contains addition of multiple role policies required for the Lambda. &lt;code&gt;Parameters&lt;/code&gt; are also used in this examples to take in inputs for the SAR application.&lt;br&gt;
-- &lt;a href="https://github.com/mengjiann/aws-lambda-s3/blob/master/template-sar.yaml"&gt;Example 2&lt;/a&gt; - This contains creation of a S3 Bucket and adds listened &lt;code&gt;Events&lt;/code&gt; to the objects created in the S3 Bucket.&lt;br&gt;
-- &lt;a href="https://github.com/mengjiann/ssm-parameters-getter-lambda/blob/master/template/sar-template.yaml"&gt;Example 3&lt;/a&gt; - This contains creation of &lt;code&gt;Role&lt;/code&gt; and &lt;code&gt;RolePolicy&lt;/code&gt; resources for attached to the Lambda function. &lt;code&gt;DependsOn&lt;/code&gt; is also used to ensure the resources are created in correct order.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once your have published a new version of the application on SAR, the users need to redeploy the application with latest version. Otherwise, they will remain on the older version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once an application is &lt;strong&gt;deployed&lt;/strong&gt; using SAR, you can check the status from the Cloud Formation's Stacks console. You can remove the application from there and check if there is any issues with the deployment.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is AWS SAR: &lt;a href="https://docs.aws.amazon.com/serverlessrepo/latest/devguide/what-is-serverlessrepo.html"&gt;https://docs.aws.amazon.com/serverlessrepo/latest/devguide/what-is-serverlessrepo.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;How to publish on SAR: &lt;a href="https://docs.aws.amazon.com/serverlessrepo/latest/devguide/serverlessrepo-how-to-publish.html"&gt;https://docs.aws.amazon.com/serverlessrepo/latest/devguide/serverlessrepo-how-to-publish.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>awssar</category>
      <category>awslambda</category>
      <category>samtemplate</category>
    </item>
    <item>
      <title>Brief Guide to AWS Step Functions with Sample Workflow</title>
      <dc:creator>MJ</dc:creator>
      <pubDate>Wed, 10 Apr 2019 13:33:57 +0000</pubDate>
      <link>https://dev.to/mengjiann/sample-workflow-on-aws-step-function-acb</link>
      <guid>https://dev.to/mengjiann/sample-workflow-on-aws-step-function-acb</guid>
      <description>&lt;h1&gt;
  
  
  AWS Step Function Background
&lt;/h1&gt;

&lt;p&gt;AWS Step Functions is one of the AWS services which allows us to define workflow by &lt;strong&gt;integrating the existing AWS services&lt;/strong&gt; such as Lambda, Fargate, SNS and etc. Each workflow is based on the concept of a state machine and it is defined using &lt;strong&gt;Amazon States Language&lt;/strong&gt; (ASL) (JSON-based). &lt;/p&gt;

&lt;p&gt;Workflow on Step Functions is made up of series of steps, with the &lt;strong&gt;output of one step acting as input into the next step&lt;/strong&gt;. Thus, you can perform a series of actions to the workflow input. Due to the limitation of data passed between each steps, it is best to use a separate service like AWS S3 to transfer the large files (&lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/limits.html" rel="noopener noreferrer"&gt;Limit&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The benefit of using Step Function is that the application logic is implemented within the workflow and it is separated from the implementation of &lt;strong&gt;individual component&lt;/strong&gt; (step). This actually promotes the reusability of each component for other workflows.&lt;/p&gt;

&lt;p&gt;A simple state machine is defined as below. &lt;code&gt;StartAt&lt;/code&gt; and &lt;code&gt;States&lt;/code&gt; are the compulsory building blocks. &lt;code&gt;StartAt&lt;/code&gt; defines the entry point of your workflow and &lt;code&gt;States&lt;/code&gt; defines the steps for your customised workflow. There are other &lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-state-machine-structure.html" rel="noopener noreferrer"&gt;optional components&lt;/a&gt; that you can have within the state machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Comment": "A Hello World example of the ASL.", // Optional
  "StartAt": "HelloWorld", // Compulsory
  "States": {              // Compulsory
    "HelloWorld": {
      "Type": "Pass",
      "Result": "Hello World!",
      "End": true
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To define the steps within the workflow, these are the available types of states provided by ACL now:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Task&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;Task&lt;/code&gt; state represents a single unit of work performed by a state machine.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pass&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;Pass&lt;/code&gt; state passes its input to its output, without performing work.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Choice&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;Choice&lt;/code&gt; state adds branching logic to a state machine.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wait&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;Wait&lt;/code&gt; state delays the state machine from continuing for a specified time. You can choose either a relative time, specified in seconds from when the state begins, or an absolute end time, specified as a timestamp.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Succeed&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;Succeed&lt;/code&gt; state stops an execution successfully. The Succeed state is a useful target for Choice state branches that don't do anything but stop the execution.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fail&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;Fail&lt;/code&gt; state stops the execution of the state machine and marks it as a failure.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parallel&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;Parallel&lt;/code&gt; state can be used to create parallel branches of execution in your state machine.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h1&gt;
  
  
  Sample Step Functions Workflow
&lt;/h1&gt;

&lt;p&gt;This article is going to cover some useful features of ASL and how to create a simple workflow by using AWS Lambda functions. Sample AWS Lambda functions are &lt;a href="https://github.com/mengjiann/aws-step-functions-sample" rel="noopener noreferrer"&gt;available here&lt;/a&gt;. Before starting, you will need to deploy the AWS Lambda functions from the sample code. Do check out &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html" rel="noopener noreferrer"&gt;here&lt;/a&gt; if you need some help on the Lambda deployment.&lt;/p&gt;

&lt;p&gt;The sample Step Functions workflow diagram is as below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk0w3zibm31xmqwsfl9m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvk0w3zibm31xmqwsfl9m.png" alt="Sample AWS Step Function Workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The basic idea of this workflow is to:&lt;br&gt;
1) Configure the &lt;code&gt;random-number-generator-lambda&lt;/code&gt; to generate a random number from a number range.&lt;br&gt;
2) Then, trigger the &lt;code&gt;random-number-generator-lambda&lt;/code&gt; to generate a random number.&lt;br&gt;
3) Based on the output of the &lt;code&gt;random-number-generator-lambda&lt;/code&gt;, the next step is to check if the output is above or below number 5.&lt;br&gt;
4) If it is above 5, SNS notification will be triggered to send out SMS.&lt;br&gt;
5) If it is below 5, another Lambda &lt;code&gt;power-of-number-lambda&lt;/code&gt; will be triggered to raise the previous input to the power of configured exponents.&lt;br&gt;
6) Then, the workflow will end after that.&lt;/p&gt;

&lt;p&gt;Here is the explanation of ACL features being used for this sample workflow:&lt;br&gt;
1) &lt;code&gt;random-number-generator-lambda-config&lt;/code&gt; - To configure the &lt;code&gt;random-number-generator-lambda&lt;/code&gt; by using the &lt;code&gt;Pass&lt;/code&gt; state.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"random-number-generator-lambda-config": {
  "Comment": "To configure the random-number-generator-lambda.",
  "Type": "Pass",
  "Result": {
      "min": 1,
      "max": 10
    },
  "ResultPath": "$",
  "Next": "random-number-generator-lambda"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;2) &lt;code&gt;random-number-generator-lambda&lt;/code&gt; - To trigger a Lambda function by  using the &lt;code&gt;Task&lt;/code&gt; state.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"random-number-generator-lambda": {
  "Comment": "Generate a number based on input.",
  "Type": "Task",
  "Resource": "${random-number-generator-lambda-aws-arn}",
  "Next": "send-notification-if-less-than-5"
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;3) &lt;code&gt;send-notification-if-less-than-5&lt;/code&gt; - To check if the output from previous step is less than 5 using the &lt;code&gt;Choice&lt;/code&gt; state.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"send-notification-if-less-than-5": {
  "Comment": "A choice state to decide to send out notification for &amp;lt;5 or trigger power of three lambda for &amp;gt;5.",
  "Type": "Choice",
  "Choices": [
    {
        "Variable": "$",
        "NumericGreaterThanEquals": 5,
        "Next": "power-of-three-lambda"
    },
    {
      "Variable": "$",
      "NumericLessThan": 5,
      "Next": "send-multiple-notification"
    }
  ]
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;4) &lt;code&gt;power-of-number-lambda&lt;/code&gt; - If output is more than 5, trigger another Lambda function using &lt;code&gt;Parameters&lt;/code&gt; to customise the input JSON object.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"power-of-three-lambda": {
  "Comment": "Increase the input to power of 3 with customized input.",
  "Type": "Task",
  "Parameters" : {
    "base.$": "$",
    "exponent": 3
  },
  "Resource": "${power-of-number-lambda-aws-arn}",
  "End": true
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;5) &lt;code&gt;send-multiple-notification&lt;/code&gt; - A &lt;code&gt;Parallel&lt;/code&gt; state to trigger multiple actions.&lt;br&gt;
6) &lt;code&gt;send-sms-notification&lt;/code&gt; - To trigger SNS notification to send SMS.&lt;br&gt;
7) &lt;code&gt;send-email-notification&lt;/code&gt; - To trigger SNS notification to send Email. (Not include as part of the sample)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"send-multiple-notification": {
  "Comment": "Trigger multiple notification using AWS SNS",
  "Type": "Parallel",
  "End": true,
  "Branches": [
    {
     "StartAt": "send-sms-notification",
     "States": {
        "send-sms-notification": {
          "Type": "Task",
          "Resource": "arn:aws:states:::sns:publish",
          "Parameters": {
            "Message": "SMS: Random number is less than 5 $",
            "PhoneNumber": "${valid-handphone-number}"
          },
          "End": true
        }
     }
   },
   {
    "StartAt": "send-sns-topic",
     "States": {
       "send-sns-topic": {
          "Type": "Task",
          "Resource": "arn:aws:states:::sns:publish",
          "Parameters": {
            "Message": "Email: Random number is less than 5: $",
            "TopicArn": "${aws-sns-topic-to-send-out-email}"
          },
          "End": true
        }
     }
   }  
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can trigger the workflow by using the &lt;code&gt;Start Execution&lt;/code&gt; button within the Step Functions console. Each invocation allows JSON object as input to the workflow, but it is not compulsory. Or Cloudwatch Schedule event can be configured to trigger the workflow.  &lt;/p&gt;

&lt;p&gt;Before that, it is also important to ensure that you have granted the appropriate permission to the IAM role for the Step Function execution. For this sample workflow, you will need the following &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Managed Policy - &lt;code&gt;AmazonSNSFullAccess&lt;/code&gt; - To trigger SNS notification SMS or Email.&lt;/li&gt;
&lt;li&gt;AWS Lambda Invocation Permission.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction",
                "lambda:InvokeAsync"
            ],
            "Resource": "*"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You should see something as below if the execution is successful. Do try a few more rounds to see you get a SMS from the SNS notification!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkw0nxhennidxpwwbu7q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frkw0nxhennidxpwwbu7q.png" alt="Sample Invocation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not all states are being covered in the above sample workflow, more can be found from &lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html" rel="noopener noreferrer"&gt;official doc&lt;/a&gt; on the different ASL features. &lt;/p&gt;

&lt;p&gt;Hope this is useful for your exploration on Step Functions.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mengjiann" rel="noopener noreferrer"&gt;
        mengjiann
      &lt;/a&gt; / &lt;a href="https://github.com/mengjiann/aws-step-functions-sample" rel="noopener noreferrer"&gt;
        aws-step-functions-sample
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Sample Workflow for AWS Step Function (with terraform)
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Sample Project for AWS Step Functions&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;This is to demonstrate the usage of several AWS Lambda functions to create a workflow on AWS Step Function. Terraform configuration files are also provided to simplify the process of setting up the required AWS resources.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AWS Lambda Function&lt;/h1&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;power-of-number-lambda - To calculate the power of a number.&lt;/li&gt;
&lt;li&gt;random-number-generator-lambda - To generate a random number between MIN and MAX.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Terraform - Prerequisite&lt;/h1&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;To use terraform, go to &lt;a href="https://learn.hashicorp.com/terraform/getting-started/install.html" rel="nofollow noopener noreferrer"&gt;here&lt;/a&gt; to install and learn Terraform by Hashicorp.
&lt;ul&gt;
&lt;li&gt;For homebrew user: &lt;code&gt;brew install terraform&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;AWS user (programmatic access) with AdministratorAccess. Copy the &lt;code&gt;access key ID&lt;/code&gt; and &lt;code&gt;secret access key&lt;/code&gt; to setup the &lt;code&gt;awscli&lt;/code&gt; later.&lt;/li&gt;

&lt;li&gt;Install &lt;code&gt;awscli&lt;/code&gt; from official &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/install-linux-al2017.html" rel="nofollow noopener noreferrer"&gt;guide&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;For homebrew user: &lt;code&gt;brew install awscli&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Using the &lt;code&gt;access key ID&lt;/code&gt; and &lt;code&gt;secret access key&lt;/code&gt;, follow this &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html" rel="nofollow noopener noreferrer"&gt;guide&lt;/a&gt; to step a new profile for your &lt;code&gt;awscli&lt;/code&gt;.&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Terraform - Guide&lt;/h1&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;After &lt;code&gt;git clone&lt;/code&gt;, change directory to…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mengjiann/aws-step-functions-sample" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/welcome.html" rel="noopener noreferrer"&gt;AWS Step Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/concepts-amazon-states-language.html" rel="noopener noreferrer"&gt;AWS State Language Official Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/amazon-states-language-states.html" rel="noopener noreferrer"&gt;AWS State Language - Different States&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>awsstateslanguage</category>
      <category>awsstepfunctions</category>
      <category>awslambdanode</category>
    </item>
    <item>
      <title>Apple Magic Keyboard Multi-Device* trick </title>
      <dc:creator>MJ</dc:creator>
      <pubDate>Sat, 06 Apr 2019 16:06:49 +0000</pubDate>
      <link>https://dev.to/mengjiann/apple-magic-keyboard-multi-device-trick-4oif</link>
      <guid>https://dev.to/mengjiann/apple-magic-keyboard-multi-device-trick-4oif</guid>
      <description>

&lt;p&gt;I'm a big fan of &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RdeDANqX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.apple.com/sg/shop/product/MLA22ZA/A/magic-keyboard-us-english%3Ffnode%3D56" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RdeDANqX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.apple.com/sg/shop/product/MLA22ZA/A/magic-keyboard-us-english%3Ffnode%3D56" alt="Apple Magic Keyboard"&gt;&lt;/a&gt;. It has everything* that I need for a slim profile Bluetooth keyboard except its ability to connect to few different devices (one at a time). Occasionally, I would want to use my iMac (for its larger screen), but the action to switch/reconnect to another device is so painful and troublesome.&lt;/p&gt;

&lt;p&gt;But, I have discovered a trick recently, which is to make use the lightning port on the Apple Magic Keyboard to connect to different macs. Once the keyboard is connected to device through cable, it will be connected to it after that. &lt;/p&gt;

&lt;p&gt;Now, it is effortless* to switch the keyboard to another device (compared to disconnecting and connecting to the new device)&lt;/p&gt;

&lt;p&gt;Let me know if it works for you too.&lt;/p&gt;


</description>
      <category>apple</category>
      <category>magickeyboard</category>
    </item>
    <item>
      <title>Using Lambda@Edge for Single Page Application(SPA) on AWS Cloudfront</title>
      <dc:creator>MJ</dc:creator>
      <pubDate>Tue, 02 Apr 2019 15:53:06 +0000</pubDate>
      <link>https://dev.to/mengjiann/using-lambda-edge-for-single-page-application-spa-on-aws-cloudfront-4f98</link>
      <guid>https://dev.to/mengjiann/using-lambda-edge-for-single-page-application-spa-on-aws-cloudfront-4f98</guid>
      <description>

&lt;p&gt;Recently, there is a new requirement on the project that I have been working on at work, which is to enable social sharing. It is for a stock photography website which allows users to buy photos at different resolutions, similar to Shutterstock or GettyImages. The new feature requires sharing of individual photo URL on the social sites.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5pGnX7cy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3n3mzxgetlkutaum5s0j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5pGnX7cy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3n3mzxgetlkutaum5s0j.jpg" alt="Social Sharing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Implementing such feature is trivial for normal websites where basic metadata can be added to each HTML pages. Since the front-end app is implemented using Vuejs, it complicates. It is due to the fact that social sites like Facebook or Twitter &lt;strong&gt;do not executed the javascript&lt;/strong&gt; on the crawled page for sharing on their sites. Therefore, it is not possible to use library to update the HTML page metadata dynamically.&lt;/p&gt;

&lt;p&gt;One of the ways to resolve this is by implementing server side rendering for the pages. But, this will require additional hosting for the front-end app as the current setup leverages AWS S3 and AWS Cloudfront for static web hosting. This setup is considered cost effective and has well taken care of the scalability of the front-end app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vzs3dU9g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1lcerw1bro8b548bv4xc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vzs3dU9g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1lcerw1bro8b548bv4xc.png" alt="Lambda@Edge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A couple of hours researching on the web led me to discover that Lambda@Edge can be deployed to the AWS Cloudfront to intercept and customize the HTTP request. Depending on the source of request by &lt;strong&gt;inspecting the User-Agent header&lt;/strong&gt;, we can modify the returned response body in the Lambda@Edge function.&lt;/p&gt;

&lt;p&gt;So, this is how it works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E5ETfQxo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/uhb1xb9pkirjnkl2lp9i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E5ETfQxo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/uhb1xb9pkirjnkl2lp9i.jpg" alt="Flow Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The green line represents the request flow for normal user access from browser. Then, the red line represents the request coming from social sites.&lt;/p&gt;

&lt;p&gt;There are a few limitations on AWS Lambda@Edge as I have written it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The supported runtime for Lambda@Edge for Cloudfront is only &lt;strong&gt;Nodejs&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The Lambda@Edge function can only be deployed onto the &lt;strong&gt;North Virginia region&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The Lambda@Edge function timeout can only be configured to &lt;strong&gt;5 secs&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The Lambda@Edge function &lt;strong&gt;does not support environment variables&lt;/strong&gt; and I have handled using Gulp script. Or you can try AWS System Manager Parameter Store.&lt;/li&gt;
&lt;li&gt;The Lambda@Edge function cant be deployed into VPC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For deployment, you will have to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Publish a new version of your Lambda@Edge function.&lt;/li&gt;
&lt;li&gt;Update the Cloudfront distribution with the new Lambda ARN.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you will need to add the required permission to the Lambda role. Refer to &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-permissions.html"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For sample AWS Lambda@Edge code, please refer to the following Github repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qF2jUiUG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-6a5bca60a4ebf959a6df7f08217acd07ac2bc285164fae041eacb8a148b1bab9.svg"&gt;&lt;a href="https://github.com/mengjiann"&gt;mengjiann&lt;/a&gt; / &lt;a href="https://github.com/mengjiann/aws-lambda-edge-cloudfront"&gt;aws-lambda-edge-cloudfront&lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;AWS Lambda Edge for Cloudfront&lt;/h3&gt;
  &lt;/div&gt;
&lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="instapaper_body md"&gt;
&lt;h1&gt;
AWS Lambda Edge for Cloudfront&lt;/h1&gt;
&lt;p&gt;This is a Lambda@Edge function that is used to customize response body for Single Page Application (SPA) served through Cloudfront.&lt;/p&gt;
&lt;p&gt;It allows returning static html for social sites (including Facebook, WhatsApp, Twitter) for rich social sharing (due to the nature of Single Page Application - SPA).&lt;/p&gt;
&lt;h1&gt;
Pre-requisite&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;npm - can be installed via Homebrew &lt;code&gt;brew install node&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;gulp-cli - &lt;code&gt;npm install gulp-cli -g&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
Guide to prepare zip file for deployment&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Update the externalApi in the environment-config.json.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gulp default --env {environment}&lt;/code&gt; Environment: dev/ prod&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;archive.zip&lt;/code&gt; will be created in the root folder and can be deployed to AWS Lambda&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
Things to note&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Environment variables are not supported for the Lambda@Edge deployed to Cloudfront. Therefore, gulp is used to automate the task of replacing the env variables and also create the artifact for uploading. Or AWS System Manager Parameter Store can be used.&lt;/li&gt;
&lt;li&gt;AWS Lambda…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mengjiann/aws-lambda-edge-cloudfront"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Reference:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Graph Protocol: &lt;a href="http://ogp.me/"&gt;http://ogp.me/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Vue Social Sharing Plugin: &lt;a href="https://github.com/nicolasbeauvais/vue-social-sharing"&gt;https://github.com/nicolasbeauvais/vue-social-sharing&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Vue Server Side Rendering: &lt;a href="https://vuejs.org/v2/guide/ssr.html"&gt;https://vuejs.org/v2/guide/ssr.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Official AWS Lambda@Edge doc: &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html"&gt;https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Official AWS Lambda@Edge Limitation: &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-requirements-lambda-function-configuration"&gt;https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-requirements-limits.html#lambda-requirements-lambda-function-configuration&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;


</description>
      <category>awss3</category>
      <category>awscloudfront</category>
      <category>awslambdaedge</category>
      <category>socialsharing</category>
    </item>
    <item>
      <title>Shutdown Spring Boot command-line application</title>
      <dc:creator>MJ</dc:creator>
      <pubDate>Mon, 25 Mar 2019 02:49:05 +0000</pubDate>
      <link>https://dev.to/mengjiann/shutdown-spring-boot-command-line-application-9fl</link>
      <guid>https://dev.to/mengjiann/shutdown-spring-boot-command-line-application-9fl</guid>
      <description>

&lt;p&gt;If you have a SpringBootApplication which implements the CommandLineRunner interface and wish to terminate it after running the override run method, here is it:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

  SpringApplication app = new SpringApplicationBuilder()
                .sources(DemoApplication.class)
                .web(false).build();

  springApplication.run(args).close();

  @Overrride
  public void run(String... strings) throws Exception {
    // Code
  }

} 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;




</description>
      <category>spring</category>
      <category>commandline</category>
    </item>
  </channel>
</rss>
