在过去的一周左右,我一直在尝试学习docker和它能做的所有事情,但是有一件事我很难理解,那就是关于如何管理秘密的最佳实践,特别是关于数据库连接字符串以及这些秘密应该如何存储的最佳实践。
我在脑海中有一个计划,我想有一个码头图像,其中将包含一个ASP.NET核心网站,MySQL数据库和PHPMyAdmin前端,并将其部署到我在DigitalOcean的液滴上。
我已经尝试了一下,我有一个docker-compose.yml文件,它将MySQL DB和PhpMyAdmin正确地链接在一起
version: "3"
services:
db:
image: mysql:latest
container_name: mysqlDatabase
environment:
- MYSQL_ROOT_PASSWORD=0001
- MYSQL_DATABASE=atestdb
restart: always
volumes:
- /var/lib/mysql
phpmyadmin:
image: phpmyadmin/phpmyadmin
container_name: db-mgr
ports:
- "3001:80"
environment:
- PMA_HOST=db
restart: always
depends_on:
- db这正确地为我创建了一个MySQL DB,我可以使用根/ 0001作为用户名/密码组合,通过运行的PHPMyAdmin前端连接到它。
我知道我现在需要将我的AspNetCore web应用程序添加到其中,但我仍然被获得数据库密码的最佳方式难住了。
我看过docker swarm/secrets,但我仍然不完全理解它是如何工作的,特别是如果我想把docker-compose文件签入到GIT/SCM中。我读到的其他内容建议使用环境变量,但我似乎仍然不明白这与只检查appsettings.json文件中的连接字符串有什么不同,或者就这一点而言,这在完整的CI/CD构建管道中如何工作。
这个question帮助我走到了这一步,但他们的数据库密码仍然保存在他们的docker-compose文件中。
可能是我想得太多了
如有任何帮助、指导或建议,我们将非常感谢。
发布于 2019-11-16 02:38:03
如果您正在使用Docker Swarm,那么您可以利用secret功能,将所有敏感信息(如密码,甚至整个连接字符串)存储为docker secret。
对于创建的每个秘密,Docker将在容器中挂载一个文件。默认情况下,它将挂载/run/secrets文件夹中的所有机密。
您可以创建自定义配置提供程序来读取密钥并将其映射为配置值
public class SwarmSecretsConfigurationProvider : ConfigurationProvider
{
private readonly IEnumerable<SwarmSecretsPath> _secretsPaths;
public SwarmSecretsConfigurationProvider(
IEnumerable<SwarmSecretsPath> secretsPaths)
{
_secretsPaths = secretsPaths;
}
public override void Load()
{
var data = new Dictionary<string, string>
(StringComparer.OrdinalIgnoreCase);
foreach (var secretsPath in _secretsPaths)
{
if (!Directory.Exists(secretsPath.Path) && !secretsPath.Optional)
{
throw new FileNotFoundException(secretsPath.Path);
}
foreach (var filePath in Directory.GetFiles(secretsPath.Path))
{
var configurationKey = Path.GetFileName(filePath);
if (secretsPath.KeyDelimiter != ":")
{
configurationKey = configurationKey
.Replace(secretsPath.KeyDelimiter, ":");
}
var configurationValue = File.ReadAllText(filePath);
data.Add(configurationKey, configurationValue);
}
}
Data = data;
}
}然后,必须将自定义提供程序添加到应用程序配置中
public static IHostBuilder CreateHostBuilder(string[] args)
{
return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddSwarmSecrets();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}然后,如果您创建了一个名为"my_connection_secret“的秘密
$ echo "Server=myServerAddress;Database=myDataBase;Uid=myUsername;Pwd=myPassword;" \
| docker secret create my_connection_secret -并将其作为连接字符串映射到您的服务:DatabaseConnection
services:
app:
secrets:
- target: ConnectionStrings:DatabaseConnection
source: my_connection_secret这与将其写入appsettings.config是相同的
{
"ConnectionStrings": {
"DatabaseConnection": "Server=myServerAddress;Database=myDataBase;Uid=myUsername;Pwd=myPassword;"
}
}如果您不想将所有连接字符串存储为secret,则可以使用占位符作为密码
Server=myServerAddress;Database=myDataBase;Uid=myUsername;Pwd={{pwd}};并使用另一个自定义配置提供程序将其替换为存储为secret的密码。
在我的博客文章How to manage passwords in ASP.NET Core configuration files中,我详细解释了如何创建自定义配置提供程序,该提供程序允许您只保留密码作为秘密,并在运行时更新配置字符串。此外,本文的完整源代码也托管在github.com/gabihodoroaga/blog-app-secrets上。
发布于 2018-03-23 04:49:39
秘密是复杂的。我要说的是,把它们放到环境变量中会让问题变得有点复杂,特别是当你只使用docker-compose (而不是kubernetes或swarm之类的更花哨的东西)的时候。您的docker-compose.yaml文件将如下所示:
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}当您启动服务时,Compose将从.env文件或命令行/环境变量中提取MYSQL_ROOT_PASSWORD。大多数CI/CD服务提供了加密映射到CI服务器上的环境变量的秘密的方法(通过GUI或某些命令行界面)。
这并不是说环境变量一定是处理秘密的最佳方式。但如果您确实迁移到编排平台,如kubernetes,将有一条直接的路径将kubernetes秘密映射到这些相同的环境变量。
https://stackoverflow.com/questions/49437336
复制相似问题