It’s no wonder that we all have some secrets in our lives. However, maintaining them can be exhausting sometimes! Likewise, the diverse range of applications and systems in the IT ecosystem consists of secrets, which makes it arduous for enterprises to securely store, transmit, and audit them.
Kubernetes Secrets let you store and manage sensitive information, such as passwords, authentication tokens, and ssh keys. However, a lot of production-grade systems avoid using Kubernetes Secrets for storing secrets as it does not include an option for strong encryptions but only base64 encodings. Further, it is also recommended to externalize secrets to secret management tools like AWS Secret Manager or Vault.
AWS ECS has out-of-the- box integration with AWS Secrets Manager where one could externalize secrets to AWS Secret Manager whereas no such direct integration exists with AWS EKS.
This blog showcases how we can externalize application secrets in Kubernetes to AWS Secret Manager with a sample implementation where your application secrets are injected into your application container using an init-container.
The implementation contains a simple python based init-container for fetching secrets from AWS Secrets Manager to Kubernetes pods. It fetches the provided key from AWS Secrets Manager and stores it in pods' volume as emptyDir at a specified location so that the main containers can use them in the application.
The init-secret container requires these env variables to work-
Create a secret in AWS Secret Manager as shown below. Further, follow this AWS guide for creating a basic secret.
To build your docker image for init-container simply clone this repository and run below Docker commands:
➜ ~ docker build -t srijanlabs/init-secret:latest .
➜ ~ docker push srijanlabs/init-secret:latest
➜ ~ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-192-168-36-74.ap-southeast-1.compute.internal Ready <none> 72m v1.16.13-eks-2ba888
ip-192-168-48-236.ap-southeast-1.compute.internal Ready <none> 72m v1.16.13-eks-2ba888
ip-192-168-73-240.ap-southeast-1.compute.internal Ready <none> 71m v1.16.13-eks-2ba888
apiVersion: apps/v1
kind: Deployment
metadata:
name: secret-manager
labels:
app: my-app
spec:
replicas: 2
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
volumes:
- name: secret-volume
emptyDir: {}
initContainers:
- name: init-secret
image: srijanlabs/init-secret:latest
imagePullPolicy: Always
command: ["python"]
args:
- "secret.py"
env:
- name: SECRET_FILE_PATH
value: "/secret/secret.env"
- name: SM_DB
value: "demo-database-secret"
- name: AWS_REGION
value: "ap-southeast-1"
volumeMounts:
- mountPath: /secret
name: secret-volume
containers:
- name: main-app
image: busybox
imagePullPolicy: Always
command: ["/bin/sh", "-c"]
# Run your application command after sourcing env file or use the env file to your convenience
args:
- "source /secret/secret.env && while true; do echo '\n\n$DB_PASSWORD = '$DB_PASSWORD; echo '\nContents of secret.env file:'; cat /secret/secret.env; sleep 2; done"
env:
- name: SECRET_FILE_PATH
value: "/secret/secret.env"
volumeMounts:
- mountPath: /secret
name: secret-volume
➜ ~ kubectl get pods
NAME READY STATUS RESTARTS AGE
secret-manager-6685f778c7-lmk9g 0/1 Init:0/1 0 2s
secret-manager-6685f778c7-vggxn 0/1 Init:0/1 0 2s
➜ ~ kubectl get pods
NAME READY STATUS RESTARTS AGE
secret-manager-6685f778c7-lmk9g 0/1 PodInitializing 0 5s
secret-manager-6685f778c7-vggxn 0/1 PodInitializing 0 5s
➜ ~ kubectl get pods
NAME READY STATUS RESTARTS AGE
secret-manager-6685f778c7-lmk9g 1/1 Running 0 10s
secret-manager-6685f778c7-vggxn 1/1 Running 0 10s
➜ ~ kubectl logs secret-manager-6685f778c7-lmk9g -c init-secret
Running init container script
Saving demo-database-secret secrets to /secret/secret.env
Done fetching secrets demo-database-secret
Exiting init container script
➜ ~ kubectl logs secret-manager-6685f778c7-lmk9g
$DB_PASSWORD = supersecretpassword
Contents of secret.env file:
DB_USERNAME='demo'
DB_PASSWORD='supersecretpassword'
DB_ENGINE='mysql'
DB_HOST='127.0.0.1'
DB_PORT='3306'
DB_DBNAME='demo'
➜ ~ kubectl delete -f examples/k8s-deployment.yaml
As security remains a major concern across all industries and domains, it would be vitally important for enterprises to capitalize on a potential secrets management tool to avoid any business disruptions. Externalizing concerns like secrets to secret management tools is an ideal recommendation and this sample implementation sheds light on how this can be achieved using init-containers in Kubernetes.