<?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: Stephan</title>
    <description>The latest articles on DEV Community by Stephan (@sthuber90).</description>
    <link>https://dev.to/sthuber90</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%2F393441%2Fb6fa160e-acd6-48ae-871b-acc9b1954473.JPG</url>
      <title>DEV Community: Stephan</title>
      <link>https://dev.to/sthuber90</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sthuber90"/>
    <language>en</language>
    <item>
      <title>Using Secrets in AWS Lambdas</title>
      <dc:creator>Stephan</dc:creator>
      <pubDate>Wed, 30 Jun 2021 08:41:15 +0000</pubDate>
      <link>https://dev.to/sthuber90/using-secrets-in-aws-lambdas-31gm</link>
      <guid>https://dev.to/sthuber90/using-secrets-in-aws-lambdas-31gm</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/sthuber90/storing-secrets-in-aws-57ca"&gt;previous part&lt;/a&gt; of the series, we had an overview of KMS, SSM Parameter Store, and Secrets Manager. In this part, let's put the services to the test and look at their different use cases with AWS Lambda. &lt;/p&gt;

&lt;p&gt;As a big fan and long-time user of the &lt;a href="https://www.serverless.com"&gt;serverless framework&lt;/a&gt;, we will also take a look at how storing secrets and the serverless framework play together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secrets in Environment Variables
&lt;/h2&gt;

&lt;p&gt;In the Lambda the encrypted secrets may still be stored as environment variables, combining Secrets Manager, or Parameter Store with KMS. &lt;br&gt;
That way environment variables still contain secrets but are stored in one central place. However, when you want to update a secret all functions using it must be redeployed. This is not practical.&lt;/p&gt;

&lt;p&gt;Nonetheless, if you fancy this solution, make sure to avoid, that any user can see the unencrypted environment variables in the Lambda function's settings you deny them the &lt;code&gt;kms:Decrypt&lt;/code&gt; permission. &lt;br&gt;
You can deny users access to all KMS key decryption with the following permission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BlockKMSDecryptForAllResources"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"kms:Decrypt"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--slttoqnb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khxojcwwbwr7umjogh84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--slttoqnb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khxojcwwbwr7umjogh84.png" alt="Deny KMS Decrypt in Lambda function"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;kmsKeyArn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arn:aws:kms:us-east-1:XXXXXX:key/some-hash&lt;/span&gt; &lt;span class="c1"&gt;# KMS key arn which will be used for encryption for all functions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Serverless supports &lt;code&gt;kmsKeyArn&lt;/code&gt; on &lt;code&gt;provider&lt;/code&gt; level to be used by all functions or on per functions basis. It is used to encrypt your environment variables on AWS. Beware, that if you haven't encrypted your secrets with KMS, using for instance the AWS CLI, before deploying your function, the secrets get transported in plaintext. &lt;/p&gt;

&lt;p&gt;In case you have encrypted them and only save their encrypted value in environment variables, you need to decrypt them inside of your Lambda function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eu-west-1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;functionName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AWS_LAMBDA_FUNCTION_NAME&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MY_SECRET_ENV&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;decrypted&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;processEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO handle the event here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;decrypted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Decrypt code should run once and variables stored outside of the&lt;/span&gt;
        &lt;span class="c1"&gt;// function handler so that these are decrypted once per container&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;KMS&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;CiphertextBlob&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="na"&gt;EncryptionContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;LambdaFunctionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;functionName&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;kms&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nx"&gt;decrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Plaintext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ascii&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Decrypt error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;processEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While it's certainly possible to protect your secrets by making them encrypted environment variables, it adds to the function's execution time. Also, there's no central place for you to manage all your secrets with this approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secrets in Parameter Store or Secrets Manager
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Still with Environment Variables
&lt;/h3&gt;

&lt;p&gt;When you store your secrets within SSM Parameter Store or Secrets Manager, they are managed in one central place. This can make rotating secrets for numerous Lambdas a lot easier. However, it still depends on your usage of these services.&lt;/p&gt;

&lt;p&gt;The serverless framework has built-in support for SSM parameters and Secrets Manager. You can get a &lt;code&gt;SecureString&lt;/code&gt;, or other parameters, from SSM with &lt;code&gt;${ssm:/path/to/secureparam}&lt;/code&gt; inside your &lt;em&gt;serverless.yml&lt;/em&gt;. To get a secret from Secrets Manager the syntax looks similar with &lt;code&gt;${ssm:/aws/reference/secretsmanager/secret_ID_in_Secrets_Manager}&lt;/code&gt;. Be aware, that SSM &lt;code&gt;SecureString&lt;/code&gt; automatically gets decrypted and parsed if they export stringified JSON content. You can turn this off by, passing the &lt;code&gt;raw&lt;/code&gt; instruction into variables (&lt;code&gt;${ssm(raw):/path/to/secureparam}&lt;/code&gt;). You can even get a raw SSM parameter from another region with &lt;code&gt;${ssm(eu-west-1, raw):/path/to/secureparam}&lt;/code&gt;. Unless you pass the &lt;code&gt;raw&lt;/code&gt; instruction your secrets get decrypted and stored in plaintext within your Lambda's environment variables. The only advantage to using purely KMS is that you manage your secrets in one central place. Not every developer needs to have access to the secrets to use them when working on one of your Lambdas. The problem remains, that the secrets get stored in environment variables. Therefore, they only change when a new deployment happens. Unless you use the &lt;code&gt;raw&lt;/code&gt; instruction your secrets get stored in plaintext, and if you use the &lt;code&gt;raw&lt;/code&gt; instructions you need to decrypt them within your Lambda with &lt;code&gt;kms.decrypt()&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  No more secrets in Environment Variables
&lt;/h3&gt;

&lt;p&gt;Instead of storing the secret in the environment variable, we just store the key from Secrets Manager/Parameter Store inside of it. You need to change your Lambda's code to fetch the secret from SSM and/or Secrets Manager, through this, the Lambda function always gets the secret directly from the Secrets Manager/Parameter Store. If we now change a secret it will be available to all functions right away, without having to change anything on the function itself. We could also get rid of the environment variables altogether and specify the secret keys inside our code.&lt;/p&gt;

&lt;p&gt;The downside to the increased security and maintainability with this approach is that the latency to retrieve the secrets and decrypt them adds to the Lambda function's execution time. Therefore, it's recommended to combine this approach with a caching of the secrets, to avoid retrieving, decrypting, processing them every time from the start. &lt;/p&gt;

&lt;p&gt;When you add a secret to Secrets Manager you can pick in the last step from a number of programming languages to get a code snippet for use in your function's code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DrA0vV16--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q5k0z5a3tvwyl1vb4lap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DrA0vV16--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q5k0z5a3tvwyl1vb4lap.png" alt="Secrets Manager Code Snippet"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a secret with name &lt;em&gt;test/abc&lt;/em&gt; the code snippet would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Use this code snippet in your app.&lt;/span&gt;
&lt;span class="c1"&gt;// If you need more information about configurations or implementing the sample code, visit the AWS docs:&lt;/span&gt;
&lt;span class="c1"&gt;// https://aws.amazon.com/developers/getting-started/nodejs/&lt;/span&gt;

&lt;span class="c1"&gt;// Load the AWS SDK&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eu-west-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;secretName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test/abc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;decodedBinarySecret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a Secrets Manager client&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SecretsManager&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;region&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// In this sample we only handle the specific exceptions for the 'GetSecretValue' API.&lt;/span&gt;
&lt;span class="c1"&gt;// See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html&lt;/span&gt;
&lt;span class="c1"&gt;// We rethrow the exception by default.&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getSecretValue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;SecretId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;secretName&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DecryptionFailureException&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// Secrets Manager can't decrypt the protected secret text using the provided KMS key.&lt;/span&gt;
            &lt;span class="c1"&gt;// Deal with the exception here, and/or rethrow at your discretion.&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;InternalServiceErrorException&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// An error occurred on the server side.&lt;/span&gt;
            &lt;span class="c1"&gt;// Deal with the exception here, and/or rethrow at your discretion.&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;InvalidParameterException&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// You provided an invalid value for a parameter.&lt;/span&gt;
            &lt;span class="c1"&gt;// Deal with the exception here, and/or rethrow at your discretion.&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;InvalidRequestException&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// You provided a parameter value that is not valid for the current state of the resource.&lt;/span&gt;
            &lt;span class="c1"&gt;// Deal with the exception here, and/or rethrow at your discretion.&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ResourceNotFoundException&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;// We can't find the resource that you asked for.&lt;/span&gt;
            &lt;span class="c1"&gt;// Deal with the exception here, and/or rethrow at your discretion.&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Decrypts secret using the associated KMS CMK.&lt;/span&gt;
        &lt;span class="c1"&gt;// Depending on whether the secret is a string or binary, one of these fields will be populated.&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SecretString&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;secret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SecretString&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;buff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SecretBinary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;decodedBinarySecret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buff&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ascii&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Your code goes here. &lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While SSM does not provide you with a code snippet for parameters stored it will be somewhat similar to how you get secrets from Secrets Manager. &lt;/p&gt;

&lt;p&gt;Instead of reinventing the wheel, I suggest having a look into Middy and see if the plugins for &lt;a href="https://middy.js.org/packages/ssm/"&gt;SSM Parameter Store&lt;/a&gt; and &lt;a href="https://middy.js.org/packages/secrets-manager/"&gt;Secrets Manager&lt;/a&gt; fulfill your needs. The plugins come with built-in caching support. If you're working with TypeScript or JavaScript it's worth looking into Middy as it provides further useful plugins, and is easy to extend and adapt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Don't save secrets in environment variables if you use the secret in other Lambdas as well. Instead, store them centrally in one place using SSM Parameter Store or Secrets Manager. Unless you need auto-rotation and multi-region replica support for your secrets SSM Parameter Store will likely be the perfect fit for you. Also, SSM provides a history of your parameter values.&lt;br&gt;
Access the secrets in your Lambda using the fitting Middy plugin and cache the value for consecutive executions. How long you cache depends on your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/monisnap/hide-your-f-king-api-keys-and-credentials-from-versioned-code-183p"&gt;https://dev.to/monisnap/hide-your-f-king-api-keys-and-credentials-from-versioned-code-183p&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@furqanshaikh/securing-secrets-in-aws-lambda-93c12861371f"&gt;https://medium.com/@furqanshaikh/securing-secrets-in-aws-lambda-93c12861371f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-encryption"&gt;https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-encryption&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/"&gt;https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.serverless.com/framework/docs/providers/aws/guide/variables/#reference-variables-using-the-ssm-parameter-store"&gt;https://www.serverless.com/framework/docs/providers/aws/guide/variables/#reference-variables-using-the-ssm-parameter-store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://serverless-stack.com/chapters/storing-secrets-in-serverless-apps.html"&gt;https://serverless-stack.com/chapters/storing-secrets-in-serverless-apps.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
      <category>secrets</category>
    </item>
    <item>
      <title>Storing Secrets in AWS</title>
      <dc:creator>Stephan</dc:creator>
      <pubDate>Wed, 30 Jun 2021 08:41:05 +0000</pubDate>
      <link>https://dev.to/sthuber90/storing-secrets-in-aws-57ca</link>
      <guid>https://dev.to/sthuber90/storing-secrets-in-aws-57ca</guid>
      <description>&lt;p&gt;Secrets can be keys, authorization tokens, passwords, and everything else that should be kept private and in this context be represented as a string. &lt;/p&gt;

&lt;p&gt;We can store secrets in multiple ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encrypting environment variables&lt;/li&gt;
&lt;li&gt;Store them in an encrypted file on S3&lt;/li&gt;
&lt;li&gt;Storing secrets in dedicated service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will look into each of these options shortly but before let's be more specific on "Storing secrets in dedicated service". There are numerous products available to store secrets, i.e. &lt;a href="https://www.hashicorp.com/products/vault"&gt;HashiCorp's Vault&lt;/a&gt;, or &lt;a href="https://www.strongdm.com/"&gt;strongDM&lt;/a&gt; to name a few, however, here we just want to focus on what solutions AWS offers. Therefore, our "dedicated services" include the Secrets Manager and the System Manager Parameter Store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encrypting environment variables
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://aws.amazon.com/kms/"&gt;AWS Key Management Service (AWS KMS)&lt;/a&gt; is an encryption and key management service scaled for the cloud. AWS KMS keys and functionality are used by other AWS services, and you can use them to protect data in your own applications that use AWS. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;KMS is the ideal tool to create and manage cryptographic keys which can be used to encrypt and decrypt secrets. KMS is so deeply rooted within AWS that it's used when encrypting files on S3 or anywhere AWS offers encrypted storage. Important to note is that KMS only stores the key used for decrypting/encrypting the secret, not the secret itself. In the context of AWS Lambda, the secret would still be stored within an environment variable and be decrypted during the Lambda runtime adding to your execution time and bill. As KMS is just meant for encrypting and decrypting the secrets, it has no built-in mechanism to rotate secrets. With the secrets themselves, still stored as environment variables, rotating the secrets, you have to encrypt the secret before you store it in an environment variable. You have to repeat this step for every function using the secret and for every encryption key used, in case you use more than one. Also, keep in mind that KMS encrypts the environment variables at rest, meaning when you deploy a Lambda function, and the secrets are "in transit" they will not be encrypted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Store them in an encrypted file on S3
&lt;/h2&gt;

&lt;p&gt;While this may suffice at first and is very easy to implement, it is hard to keep your secrets secret and not be over-permissive or have other resources, i.e. Lambda functions, access secrets they are not using. I wouldn't recommend it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storing secrets in AWS System Manager Parameter Store
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html"&gt;Parameter Store&lt;/a&gt;, a capability of AWS Systems Manager, provides secure, hierarchical storage for configuration data management and secrets management. You can store data such as passwords, database strings, Amazon Machine Image (AMI) IDs, and license codes as parameter values. You can store values as plain text or encrypted data. You can reference Systems Manager parameters in your scripts, commands, SSM documents, and configuration and automation workflows by using the unique name that you specified when you created the parameter. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Storing secrets inside Parameter Store as key-value pairs leverage KMS to encrypt the secrets at rest. A parameter is a key-value pair, where the value can be one string, a list of strings, or even a JSON object in string representation. Parameter Store allows to store &lt;code&gt;SecureStrings&lt;/code&gt; encrypting them with KMS, but its default is to store plaintext parameter values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1uO55Whf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6df1ubqibgvez4zgc6j3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1uO55Whf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6df1ubqibgvez4zgc6j3.png" alt="SSM Parameter Store"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The parameter key should follow a unique structure accepted by all admins of the Parameter Store within your account. The key must start with a slash (&lt;code&gt;/&lt;/code&gt;) and could be followed by your department or team name, the service to which the secret belongs, and a parameter name e.g. &lt;em&gt;/acme/serviceA/username&lt;/em&gt;. One reason for this is to limit access to parameters by key paths (&lt;em&gt;/acme/serviceA/*&lt;/em&gt;). Another one is, that Parameter Store allows us to read all parameters within a hierarchy. With this, we can get all parameters to &lt;em&gt;serviceA&lt;/em&gt; by retrieving all parameter keys starting with &lt;em&gt;/acme/serviceA/&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Parameter Store does not charge anything for storing parameters with up to 4 kB size, if you want to store larger parameters you get charged 0.05 USD per parameter and month.&lt;/p&gt;

&lt;p&gt;Rolling back secrets in Parameter Store is a piece of cake because Parameter Store provides a history of the parameter where you can not only see the previous value of the secret but also who changed it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gqzkrnQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/todd0tvjr7thkjdjzzu6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gqzkrnQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/todd0tvjr7thkjdjzzu6.png" alt="SSM Parameter Store History"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Together with &lt;a href="https://aws.amazon.com/de/cloudtrail/"&gt;CloudTrail&lt;/a&gt; this provides you with full control over your parameter stores. As Parameter Store is not region agnostic, the parameters get stored in a specific region. You can use them from other regions, of course, but if you want to replicate your parameters across regions, there's no built-in way to do so. However, with CloudTrail you could have a Lambda executed every time a parameter got changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storing secrets in AWS Secrets Manager
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html"&gt;AWS Secrets Manager&lt;/a&gt; helps you to securely encrypt, store, and retrieve credentials for your databases and other services. Instead of hardcoding credentials in your apps, you can make calls to Secrets Manager to retrieve your credentials whenever needed. Secrets Manager helps you protect access to your IT resources and data by enabling you to rotate and manage access to your secrets. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;AWS Secrets Manager complies with many &lt;a href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/asm_compliance.html"&gt;international security standards&lt;/a&gt;. The service is dedicated to storing all kinds of secrets and supports a default set of supported resources for which secret management is even simpler. Therefore, everything within Secrets Manager is stored encrypted with a KMS key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ln3Ynll3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u86bp4yjs1bl3p7bt16g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ln3Ynll3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u86bp4yjs1bl3p7bt16g.png" alt="Secrets Manager - Step 1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can store secrets as key-value pairs. A secret can consist of multiple key-value pairs. This is especially useful as you get &lt;a href="https://aws.amazon.com/secrets-manager/pricing/"&gt;charged 0.40 USD per stored secret and month&lt;/a&gt;. When you want to store an API key, username, password, and maybe even the URL, storing them in separate secrets would cost you 1.60 USD, whereas, if you store them together, similar to a JSON object you just pay 0.40 USD. Take care, that you need to parse the object, however.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_ff-LZYB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0o84lra8t8ge33ptgst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_ff-LZYB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m0o84lra8t8ge33ptgst.png" alt="Secrets Manager - Step 1 JSON"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the secret's name, it's also recommended to follow some structure, though retrieving secrets hierarchically is not possible like it is in Parameter Store, you can still benefit from a somewhat structured key when setting up IAM permissions.&lt;br&gt;
Like in other AWS services a tag can be helpful in the context of billing, i.e. separating the bill by a specific tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html"&gt;Resource permissions&lt;/a&gt; are particularly helpful when you want to share secrets across AWS accounts.&lt;/p&gt;

&lt;p&gt;Similar to Parameter Store, Secrets Manager keeps the secrets within the AWS region they were created in. With "Replicate Secrets" you have the option to automatically have your secrets copied to other regions as read-only copies. The secret in the origin region is the only one you can edit. Read the &lt;a href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/create-manage-multi-region-secrets.html"&gt;getting started guide&lt;/a&gt; to learn more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aGqvJb4M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11rt1zyuapi2cowbd3de.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aGqvJb4M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11rt1zyuapi2cowbd3de.png" alt="Secrets Manager - Step 2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For your own secret types (API key, username, passwords, ...) Secret Manager does not provide automatic secret rotation. To rotate your secrets in this case, set up a Lambda function dedicated to creating new secrets and invalidating the old ones. Be careful in this Lambda function on what you log, to not accidentally leak your secrets. You can renew your secrets once a day or up to once a year, it's up to your use case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PHfPZsdU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9lmaj9nsql1thm2yt8qw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PHfPZsdU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9lmaj9nsql1thm2yt8qw.png" alt="Secrets Manager - Step 3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When setting up Secrets Manager please consider the &lt;a href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/best-practices.html"&gt;best practices&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jf2QhN3e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r1a02gahxlycocv3juy3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jf2QhN3e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r1a02gahxlycocv3juy3.png" alt="Parameter Store vs. Secrets Manager from Yan Cui's Production Ready Serverless Course"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can mix and match KMS with Secrets Manager or Parameter Store or only use one of the services to keeping the secrets completely safe. &lt;br&gt;
Secrets Manager and Parameter Store are in many parts very similar to one another. Parameter Store will likely be your cheaper solution. Unless you need an automatic rotation of secrets or secret replication across regions and fancy convenience, Parameter Store will likely be your preferred solution. It does not have to be one or the other as Secrets Manager and Parameter Store can be used side by side. Make sure to take advantage of CloudTrail and set up carefully drafted IAM roles for your users.&lt;/p&gt;

&lt;p&gt;In the next part of the series, we look into how we can use these services to &lt;a href="https://dev.to/sthuber90/using-secrets-in-aws-lambdas-31gm"&gt;secure secrets when using AWS Lambda&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.manning.com/livevideo/production-ready-serverless"&gt;https://www.manning.com/livevideo/production-ready-serverless&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://seanjziegler.com/a-complete-guide-to-using-the-aws-systems-manager-parameter-store"&gt;https://seanjziegler.com/a-complete-guide-to-using-the-aws-systems-manager-parameter-store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dhwaneetbhatt.com/blog/using-aws-parameters-store"&gt;https://dhwaneetbhatt.com/blog/using-aws-parameters-store&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://openupthecloud.com/kms-aws-lambda/"&gt;https://openupthecloud.com/kms-aws-lambda/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@ZeroDeth/aws-secrets-manager-vs-parameter-store-606d4ee2af88"&gt;https://medium.com/@ZeroDeth/aws-secrets-manager-vs-parameter-store-606d4ee2af88&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://orca.security/aws-lambda-secrets/"&gt;https://orca.security/aws-lambda-secrets/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://serverless-stack.com/chapters/storing-secrets-in-serverless-apps.html"&gt;https://serverless-stack.com/chapters/storing-secrets-in-serverless-apps.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>secrets</category>
    </item>
    <item>
      <title>The case of monitoring your internet speed during a pandemic</title>
      <dc:creator>Stephan</dc:creator>
      <pubDate>Sun, 24 Jan 2021 16:42:48 +0000</pubDate>
      <link>https://dev.to/sthuber90/the-case-of-monitoring-your-internet-speed-during-a-pandemic-8p1</link>
      <guid>https://dev.to/sthuber90/the-case-of-monitoring-your-internet-speed-during-a-pandemic-8p1</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Not interested in the background and just want to know how to monitor your internet speed regularly? Jump right to it&lt;/p&gt;

&lt;p&gt;I live in Germany, and I know that we don't have the fastest internet in the world. Still, with a mean download speed of 42.33 Mbps, the country does better than the global average of 24.83 Mbps. Nevertheless, it is just enough to place 42&lt;sup&gt;nd&lt;/sup&gt; out of 221 countries compared.&lt;sup id="fnref1"&gt;1&lt;/sup&gt; In comparison with only the European countries, Germany does not even make it into the top 10, placing 26&lt;sup&gt;th&lt;/sup&gt;.&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;With digitization as one of the thriving factors for the world economy, the internet and connectivity to it start playing an ever more important role, as it is the foundation that digitization needs to flourish.&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Currently, Germany is the 13&lt;sup&gt;th&lt;/sup&gt; biggest economy in the world - placing 8&lt;sup&gt;th&lt;/sup&gt; within Europe - measured by the gross domestic product (GDP) per capita, adjusted with purchasing power parity.&lt;sup id="fnref3"&gt;3&lt;/sup&gt; So, one could expect to have a fast, reliable internet connection. At least, the comparably high economic strength of Germany ($ 56K) does not seem to have a significant effect on the price of an internet contract. However, it is noteworthy that Luxembourg, as the country with the strongest economic power within Europe ($ 121K) gets better value (internet speed of avg. 118 Mbps) for a lower price.&lt;sup id="fnref4"&gt;4&lt;/sup&gt; Given that Luxembourg is a lot smaller than Germany, the countries face different challenges when it comes to getting the internet to where the people live. Therefore, it is an interesting fact, but one to be neglected.&lt;/p&gt;

&lt;p&gt;Lately, the pandemic urges people to work from home wherever possible, and with schools and universities closed, the internet infrastructure in Germany is put to a test. During the day employees, students, pupils working from home put an unprecedented load on the infrastructure. From the afternoon to the evening and night, when people stop working and switch their internet usage to scrolling through Instagram, TikTok, etc., and streaming their favorite shows on Netflix, Prime, and so on.&lt;/p&gt;

&lt;p&gt;The additional stress this puts on the internet service providers (ISPs) can be felt by customers. In my case, living in a densely populated area (a.k.a city), the result was that I had no internet connection at home between 8 a.m. and 11 p.m., making it impossible for me to work from home, or stream anything. I have a contract promising up to 50 Mbps and no less than 25 Mbps. For the past years, this was sufficient and I never had any serious problems with it. Now,  in the middle of the second "lockdown", I effectively have no internet during the day.&lt;/p&gt;

&lt;p&gt;Getting curious to see how much my internet speed varies throughout the day (and night) gave me the idea for this post.&lt;/p&gt;




&lt;h2&gt;
  
  
  Monitoring internet speed &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hGAqOmaS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sthuber90/docker-speedtest/main/docs/img/dashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hGAqOmaS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sthuber90/docker-speedtest/main/docs/img/dashboard.png" alt="Speed Test Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While there are numerous tools out there to test your internet speed&lt;sup id="fnref5"&gt;5&lt;/sup&gt;, &lt;a href="https://www.speedtest.net/apps/cli"&gt;Ookla's speedtest CLI&lt;/a&gt; seemed like the perfect fit. You can simply download it, it's well documented, it requires no additional tools, it comes from the official source, and seems to be maintained in contrast to others&lt;sup id="fnref6"&gt;6&lt;/sup&gt;. Running the speed test from my PC was a no go. First of all, the test would run on my WiFi, possibly distorting the results. Secondly, it would not monitor the connection day and night, but only run when my PC is on, so only when I work. Furthermore, it would likely distort the results more, as I depend on the internet, namely Stackoverflow, to work. Luckily, I have a RaspberryPi connected to my router. Services already deployed on the RaspberryPi, run only as Docker containers. Therefore, I aimed to run the speed test from a Docker container too and to keep the OS free from all that is unnecessary.&lt;/p&gt;

&lt;p&gt;The final result can be found on GitHub:&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--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/sthuber90"&gt;
        sthuber90
      &lt;/a&gt; / &lt;a href="https://github.com/sthuber90/docker-speedtest"&gt;
        docker-speedtest
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Regularly test your internet speed with Speedtest CLI within Docker container
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The repository contains the code, that is used to build the &lt;a href="https://hub.docker.com/r/sthuber90/speedtest/"&gt;sthuber90/docker-speedtest&lt;/a&gt; Docker image. The container can be configured to run a speed test every 5 minutes (default: 15 minutes). Be aware, that if you run this image, you agree to the Speedtest CLI's license and privacy regulations.&lt;/p&gt;

&lt;p&gt;The results of the speed test are intended to be forwarded to an InfluxDB and visualized in a Chronograf dashboard (provided in the repository). Detailed instructions to set up the monitoring can be found in the README on GitHub and Docker Hub. &lt;/p&gt;

&lt;p&gt;I hope you did find this post helpful.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://www.cable.co.uk/broadband/speed/worldwide-speed-league/"&gt;https://www.cable.co.uk/broadband/speed/worldwide-speed-league/&lt;/a&gt;, 2020 ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;PwC, &lt;a href="https://www.strategyand.pwc.com/m1/en/reports/digitization-for-economic-growth-and-job-creation.pdf"&gt;https://www.strategyand.pwc.com/m1/en/reports/digitization-for-economic-growth-and-job-creation.pdf&lt;/a&gt;, 2013 ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;GDP from 2019, considering PPP (World Bank: &lt;a href="https://data.worldbank.org/indicator/NY.GDP.MKTP.PP.CD?end=2019&amp;amp;most_recent_value_desc=true&amp;amp;start=1990&amp;amp;view=chart"&gt;https://data.worldbank.org/indicator/NY.GDP.MKTP.PP.CD?end=2019&amp;amp;most_recent_value_desc=true&amp;amp;start=1990&amp;amp;view=chart&lt;/a&gt;) turned into GDP per capita in USD, taking the countries population into account (World Bank:  &lt;a href="https://data.worldbank.org/indicator/SP.POP.TOTL?most_recent_value_desc=true"&gt;https://data.worldbank.org/indicator/SP.POP.TOTL?most_recent_value_desc=true&lt;/a&gt;), 2019 ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;&lt;a href="https://www.cable.co.uk/broadband/pricing/worldwide-comparison/"&gt;https://www.cable.co.uk/broadband/pricing/worldwide-comparison/&lt;/a&gt;, 2020 ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn5"&gt;
&lt;p&gt;&lt;a href="https://fast.com"&gt;https://fast.com&lt;/a&gt; (by Netflix), &lt;a href="http://avm.de/nc/service/zack-der-speedtest-fuer-ihre-breitbandverbindung/"&gt;http://avm.de/nc/service/zack-der-speedtest-fuer-ihre-breitbandverbindung/&lt;/a&gt;, &lt;a href="https://breitbandmessung.de/"&gt;https://breitbandmessung.de/&lt;/a&gt; (by the German Federal Network Agency) ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn6"&gt;
&lt;p&gt;Other libraries using &lt;a href="https://speedtest.net"&gt;https://speedtest.net&lt;/a&gt; for internet speed tests, that seem not to be maintained anymore  (1) &lt;a href="https://www.npmjs.com/package/speedtest"&gt;https://www.npmjs.com/package/speedtest&lt;/a&gt;, (2) &lt;a href="https://pypi.org/project/speedtest-cli/"&gt;https://pypi.org/project/speedtest-cli/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>speedtest</category>
      <category>docker</category>
      <category>isp</category>
      <category>corona</category>
    </item>
  </channel>
</rss>
