问题
I have a node.js app which has a config file with sensitive data. I want to launch it through AWS ECS (cluster) as a docker container.
What would be the best way to store the sensitive config data?
I am currently sending them through the environmental variables in the Task Definition of the Docker container, but there has to be a better way to do that.
What is the best practice for something like this? Shall I use Docker secrets or Amazon secrets manager?
I know it's a pretty general question, but I couldn't find an answer to that, so maybe somebody has a recommendation?
回答1:
What would be the best way to store the sensitive config data?
Usually you would use either SSM Parameter Store or AWS Secrets Manager. One difference between them is that the SSM Parameter Store
is free (Standard type), while AWS Secrets Manager
is not.
Then you would pass "links" to your secrets in store or manager using environmental variables in the Task Definition.
For this, you application would need to use AWS SDK to get the secrets in the container. Also task role would need to be setup so that your containers can access the secrets.
The task would also need to be able to access the SSM Parameter
Store or the AWS Secrets Manager
. Thus if you run them in private subsets without internet, NAT gateway or VPC interface endpoints for SSM and Secret Manager (depending on what you use) would need to be setup to allow the access.
Extra details below:
- Managing Secrets for Amazon ECS Applications Using Parameter Store and IAM Roles for Tasks
回答2:
Great question. I agree that the SSM Parameter Store or AWS Secrets Manager are the recommended tools for this job, but they are just not that usable in my opinion if you follow the infrastructure as code principle.
Therefore I keep my configuration files right next to the Terraform scripts in the same Git repository and inject the actual sensitive data (passwords, keys, whatever) during runtime from the SSM Parameter Store into the specific target files.
This has several advantages over using the AWS provided solution:
- No size limit (SSM Parameter Store limits you to 4 KB in the free version).
- Non-sensitive configuration is version controlled with all the advantages that come with that.
- I can easily see the current configs used and update them instead of logging into the AWS console and so on.
Here is how I manage configs/secrets with Terraform / AWS ECS
The basic idea is as following: We store configuration files without sensitive data in the repository next to Terraform. Secrets are stored in AWS parameter store. To get the data into our containers at runtime, we modify the entrypoint. We could of course just create modified images, but that creates a big maintenance overhead in my opinion. Using the entrypoint approach, we can keep using vanilla images.
The disadvantage is that I have to create custom entrypoint scripts. That means that I have to find the Dockerfile of the image I'm interested in and extract the commands used to start the actual process running in the image.
I have a git repository like this:
├── files
│ └── promstack
│ ├── grafana
│ │ ├── default-datasources.yml
│ │ ├── grafana.ini
│ │ └── run.sh
│ ├── loki
│ │ └── run.sh
│ ├── nginx
│ │ ├── nginx.conf
│ │ └── run.sh
│ └── prometheus
│ ├── prometheus.yml
│ ├── rules-alerting.yml
│ ├── rules-recording.yml
│ └── run.sh
├── myscript.tf
└── variables.tf
The run.sh
scripts represent the entrypoints. Here is an exemplary run.sh
:
#!/bin/sh
set -x
require () {
if [ ! "$1" ]; then
echo "ERROR: var not found"
exit 1
fi
}
expand () {
var_name="${1}"
file="${2}"
eval var="\$$var_name"
sed -i "s+\${${var_name}}+${var}+g" ${file}
sed -i "s+\$${var_name}+${var}+g" ${file}
}
require ${GRAFANA_INI}
require ${DEFAULT_DATASOURCES_YML}
require ${DOMAIN}
echo ${GRAFANA_INI} | base64 -d > /etc/grafana/grafana.ini
chmod 666 /etc/grafana/grafana.ini
expand DOMAIN /etc/grafana/grafana.ini
echo ${DEFAULT_DATASOURCES_YML} | base64 -d > /etc/grafana/provisioning/datasources/default.yml
chmod 666 /etc/grafana/provisioning/datasources/default.yml
su -s "/bin/sh" -c "/run.sh" grafana
Here a part from a Terraform script (ECS Container task definition to be exact):
{
name: "grafana",
image: "grafana/grafana:7.0.5",
portMappings: [{
containerPort : 3000,
hostPort: 0,
protocol: "tcp"
}],
user: "0",
entryPoint: [ "/bin/sh", "-c", join(" ", [
"export DEFAULT_DATASOURCES_YML=${base64encode(file("${path.module}/files/promstack/grafana/default-datasources.yml"))};",
"export GRAFANA_INI=${base64encode(file("${path.module}/files/promstack/grafana/grafana.ini"))};",
"echo '${base64encode(file("${path.module}/files/promstack/grafana/run.sh"))}' | base64 -d | sh;"
])],
secrets: [
{
name: "DOMAIN",
valueFrom: "<my ssm parameter>"
}
]
},
来源:https://stackoverflow.com/questions/62791093/whats-the-best-way-to-store-a-config-file-for-a-docker-container-on-aws