Skip to content

Commit 785d999

Browse files
authored
Merge pull request aws-samples#490 from paavan98pm/master
aws-samples#475 Added Instructions to Use AWS Secrets Manager within 401
2 parents 5be568c + a527771 commit 785d999

File tree

6 files changed

+206
-0
lines changed

6 files changed

+206
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
npm-debug.log
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
FROM node:carbon
2+
# Create app directory
3+
WORKDIR /usr/src/app
4+
5+
# Install app dependencies
6+
# A wildcard is used to ensure both package.json AND package-lock.json are copied
7+
# where available (npm@5+)
8+
COPY package*.json ./
9+
10+
RUN npm install
11+
# If you are building your code for production
12+
# RUN npm install --only=production
13+
# Bundle app source
14+
COPY . .
15+
16+
CMD [ "npm", "start" ]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "docker_web_app",
3+
"version": "1.0.0",
4+
"description": "Node.js on Docker",
5+
"author": "Paavan Mistry",
6+
"main": "server.js",
7+
"scripts": {
8+
"start": "node server.js"
9+
},
10+
"dependencies": {
11+
"aws-sdk": "latest",
12+
"dotenv": "^6.0.0",
13+
"npm": "^6.1.0"
14+
}
15+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
'use strict';
2+
3+
require('dotenv').config();
4+
5+
var AWS = require('aws-sdk'),
6+
endpoint = process.env.ENDPOINT,
7+
region = process.env.REGION,
8+
secretName = process.env.SECRETNAME,
9+
secret = "",
10+
binarySecretData = "";
11+
12+
13+
// Constants
14+
var client = new AWS.SecretsManager({
15+
endpoint: endpoint,
16+
region: region
17+
});
18+
19+
20+
// App
21+
client.getSecretValue({SecretId: secretName}, function(err, data) {
22+
if(err) {
23+
if(err.code === 'ResourceNotFoundException')
24+
console.log("The requested secret " + secretName + " was not found");
25+
else if(err.code === 'InvalidRequestException')
26+
console.log("The request was invalid due to: " + err.message);
27+
else if(err.code === 'InvalidParameterException')
28+
console.log("The request had invalid params: " + err.message);
29+
}
30+
else {
31+
// Decrypted secret using the associated KMS CMK
32+
// Depending on whether the secret was a string or binary, one of these fields will be populated
33+
if(data.SecretString !== "") {
34+
secret = data.SecretString;
35+
// console.log(secret);
36+
} else {
37+
binarySecretData = data.SecretBinary;
38+
}
39+
}
40+
41+
// Your code goes here.
42+
console.log(`Secret retrieved from AWS SecretsManager: The Secret ${secretName} has SecretString ${secret}`);
43+
});

04-path-security-and-networking/401-configmaps-and-secrets/readme.adoc

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,112 @@ Check the logs of the Pod:
676676

677677
This shows that the Java application has been able to read both the NAME and GREETING secrets from AWS Parameter Store.
678678

679+
== Secrets using AWS Secrets Manager
680+
681+
In this section, we will create a secret using https://aws.amazon.com/secrets-manager/[AWS Secrets Manager] in the region of choice, and access the secret in a Node.js application deployed within Kubernetes pod. AWS Secrets Manager is available in https://docs.aws.amazon.com/general/latest/gr/rande.html#asm_region[most AWS regions].
682+
683+
AWS Secrets Manager enables you to easily rotate, manage, and retrieve database credentials, API keys, and other secrets throughout their lifecycle. The service integrates with KMS, which uses a https://aws.amazon.com/blogs/security/aws-key-management-service-now-offers-fips-140-2-validated-cryptographic-modules-enabling-easier-adoption-of-the-service-for-regulated-workloads/[FIPS 140-2 validated Hardware Security Module], to provide robust key management controls to secure the secret. AWS Secrets Manager also integrates with AWS IAM and AWS CloudTrail to provide fine-grained access, audit and alerting integration.
684+
685+
=== Update the IAM role for EKS or `kops` Kubernetes Cluster
686+
687+
==== EKS Kubernetes Cluster
688+
EC2 worker nodes use `NodeInstanceRole` created in Step 3 of the https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html[EKS Getting Started guide]. This role must be updated to allow the worked nodes to read the secrets from Secrets Manager.
689+
690+
In the IAM Console, click `roles` and type `NodeInstanceRole` and click it. In the Permissions tab, expand the inline policy and click `Edit policy`. Add the `secretsManager:GetSecretValue` permission to the policy so the policy looks similar to the one below.
691+
692+
{
693+
"Version": "2012-10-17",
694+
"Statement": [
695+
{
696+
"Effect": "Allow",
697+
"Action": [
698+
"secretsmanager:GetSecretValue",
699+
"secretsmanager:DescribeSecret"
700+
],
701+
"Resource": [
702+
"arn:aws:secretsmanager:us-west-2:<account-id>:secret:<secret-name>"
703+
]
704+
}
705+
]
706+
}
707+
708+
==== `kops` Kubernetes Cluster
709+
710+
EC2 worker nodes use an instance profile to allow the EC2 node instances to access other AWS services. This role must be updated to allow the worker nodes to read the secrets from Secrets Manager.
711+
712+
In the IAM Console click `roles` and type `nodes` into the search box. Find the `nodes.example.cluster.k8s.local` role
713+
and click it. In the `Permissions` tab, expand the inline policy for `nodes.example.cluster.k8s.local` and click
714+
`Edit policy`.
715+
716+
{
717+
"Version": "2012-10-17",
718+
"Statement": [
719+
{
720+
"Effect": "Allow",
721+
"Action": [
722+
"secretsmanager:GetSecretValue",
723+
"secretsmanager:DescribeSecret"
724+
],
725+
"Resource": [
726+
"arn:aws:secretsmanager:us-west-2:<account-id>:secret:<secret-name>"
727+
]
728+
}
729+
]
730+
}
731+
732+
=== Create secrets
733+
734+
. Create a secret key-value pair using https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/create-secret.html[AWS Secrets Manager CLI]. Replace `<SECRETNAME>` and `<REGION>` with your preference.
735+
736+
aws secretsmanager create-secret --name <SECRETNAME> --description "EKS/kops Demo Secret" --secret-string [{"testkey1":"testvalue1"},{"testkey2":"testvalue2"}] --region <REGION>
737+
738+
. Get the value of created secret using https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/get-secret-value.html[GetSecretValue] API call.
739+
740+
aws secretsmanager get-secret-value --secret-id <SECRETNAME> --region <REGION>
741+
742+
. For the selected `<REGION>`, AWS Secrets Manager `<ENDPOINT>` can be determined from https://docs.aws.amazon.com/general/latest/gr/rande.html#asm_region[AWS Documentation].
743+
744+
. Note the `ENDPOINT`, `REGION` and `SECRETNAME` values. They will be passed as environment variables in a `.yaml` file described in the next section.
745+
746+
=== Consume secrets in a Pod
747+
748+
The Github repository directory `images/sec_mgr_app` contains a Node.js sample application that reads a secret from AWS Secrets Manager from specified region. This application is then packaged as a Pod and deployed in the cluster.
749+
750+
The Pod configuration is shown below. The `ENDPOINT`, `REGION` and `SECRETNAME` variables are passed as environment variables to the docker image. Change the values of these environment variables to match the values used during creation of secret in AWS Secrets Manager.
751+
752+
apiVersion: v1
753+
kind: Pod
754+
metadata:
755+
name: pod-secretsmanager
756+
spec:
757+
containers:
758+
- name: pod-secretsmanager
759+
image: paavanmistry/node-aws-sm-demo:latest
760+
env:
761+
- name: ENDPOINT
762+
value: "https://secretsmanager.us-west-2.amazonaws.com"
763+
- name: REGION
764+
value: "us-west-2"
765+
- name: SECRETNAME
766+
value: "sm-demo-secret"
767+
restartPolicy: Never
768+
769+
Create the Pod:
770+
771+
$ kubectl apply -f templates/pod-secretsmanager.yaml
772+
pod "pod-secretsmanager" configured
773+
774+
Check the logs of the Pod:
775+
776+
$ kubectl logs pod-secretsmanager
777+
Secret retrieved from AWS SecretsManager: The Secret <SECRETNAME> is [{testkey1}:{testvalue1},{testkey2:testvalue2}]
778+
779+
Clean up:
780+
781+
- `$ kubectl delete -f templates/pod-secretsmanager.yaml`
782+
- `$ aws secretsmanager delete-secret --secret-id $SECRETNAME --region $REGION`
783+
- Delete IAM role policy updates for AWS Secrets Manager
784+
679785
== Secrets using Vault
680786

681787
https://www.vaultproject.io/[Hashicorp Vault] is a tool for managing secrets. It secures, stores and tightly controls access to tokens, passwords, certificates, API keys and other secrets.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: v1
2+
kind: Pod
3+
metadata:
4+
name: pod-secretsmanager
5+
annotations:
6+
seccomp.security.alpha.kubernetes.io/pod: docker/default
7+
apparmor.security.beta.kubernetes.io/pod: runtime/default
8+
spec:
9+
securityContext:
10+
runAsUser: 1337
11+
runAsNonRoot: true
12+
containers:
13+
- name: pod-secretsmanager
14+
image: paavanmistry/node-aws-sm-demo:latest
15+
securityContext:
16+
allowPrivilegeEscalation: false
17+
env:
18+
- name: ENDPOINT
19+
value: "https://secretsmanager.us-west-2.amazonaws.com"
20+
- name: REGION
21+
value: "us-west-2"
22+
- name: SECRETNAME
23+
value: "sm-demo-secret"
24+
restartPolicy: Never

0 commit comments

Comments
 (0)