自动化部署中处理生产配置的密码

15
我在这里看到了相关问题,但它们似乎并没有完全回答我所需要的内容。
我们使用PowerShell脚本来部署应用程序,并且大多数环境(如UAT等)中的配置文件中的密码等信息都是明文。这不是一个大问题,但当涉及到PREPROD和PROD时,就成为了一个大问题。因此,我们在配置文件中添加了一些标记,比如"{{prompt-password}}",这将提供一个登录对话框(Get-Credential),执行部署的人员可以输入凭据,然后部署继续进行。
但这对于自动化部署并不是真正有帮助的(意味着通过像TeamCity这样的工具进行一键部署)。
我应该选择使用非对称加密(http://msdn.microsoft.com/en-us/library/as0w18af.aspx),其中密码使用公钥进行加密,输入到配置中,私钥存储在“代理”(例如,从TeamCity触发部署并具有受限访问权限的VM)中运行的自动化部署中,并且可以解密密码(如此描述 http://msdn.microsoft.com/en-us/library/tswxhw92.aspx)。我对密码学等方面不是很了解,但这是否听起来像正确的方法?还有其他建议吗?人们如何处理这样的自动化部署?

更新:

好的,我已经实现了它。我用C#编写了一个控制台应用程序,使用了加密库。该应用程序生成密钥:

RSACryptoServiceProvider rsa = GetRsa(containerName);
File.WriteAllText("keys.kez",rsa.ToXmlString(true));

我也得到了公钥:

File.WriteAllText("public.pke", rsa.ToXmlString(false));

把公钥交给需要加密密码的人,并要求他们在配置中输入密码。将keys.kez文件放置在任何需要运行部署的代理中。

嘿,Manojlds,我今天在想这个问题,我很好奇你需要密码做什么,而不能通过其他方式完成,比如集成身份验证或证书(用于证明你的身份而不是解密)? - Matt
@Matt - 请提供数据库密码/连接字符串? - manojlds
你可以使用集成身份验证 - 使用的用户凭据是应用程序池或服务正在运行的用户。 - Matt
啊哈,我正想着微软呢。干杯! - Matt
我真的很想要一个简单的示例应用程序,供那些对加密不太熟悉的人使用。从提供的几行代码中,我无法确定它们确切地在做什么。 - Cody Konior
6个回答

4

从安全和简单性的角度来看,非对称加密绝对是胜者。我已经成功地以这种方式部署了生产SaaS应用程序。

有一些技巧。首先,像你提到的那样,请确保公钥/私钥对已安装在主机上,而不是存储在配置文件或代码中。其次,假设MS提供的管理和密钥生成工具很弱或极差,并相应地计划(我们为运营创建了一个简单的keygen exe,在部署期间运行)。


标记为答案,因为这是我想要的最合适的答案。 - manojlds

2

虽然不是真正的答案,但我有一个建议或另一个问题。

为什么不将密码存储在配置文件中的加密字符串中?

$credential.Password | ConvertFrom-SecureString | Set-Content c:\temp\password.txt

据我所了解的文档,使用相同凭据运行的进程可以获取它。
$password = Get-Content c:\temp\password.txt | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential `
         "username",$password

您可以用read-host -assecurestring替换$credential.Password

1
你可以用 read-host -assecurestring 替换 $credential.Password - 这就是关键所在。如果你看了我的问题,这已经是我们正在做的事情 - 任何 {{prompt-password}} 的内容都会被读取为安全字符串并在配置中使用。对于通过命令行进行部署来说这是很好的。有人可以输入密码。但是当通过TeamCity的构建配置运行时,没有办法输入/传递密码。这是我的问题所在。 - manojlds
1
我相信非对称加密是最好的解决方案,我在许多项目中都使用了它。但很抱歉,这仅仅是我个人的理解。代理正在使用一个特殊用户运行。因此,如果这个用户账户用于加密密码,并且加密字符串仅存储在配置文件中,那么只有这个代理可以解密密码,这也是一种解决方案吗?我的错误在哪里? - JPBlanc

1

根据您在问题中提到的,您的密码以明文形式保存在PROD配置文件中。任何加密都无法解决这个问题。而且,这是一个恶性循环 - 您如何保护加密密钥呢?

关键在于看看什么是实际可行的,以及您的组织在部署方面遵循哪些业务流程。

让我用一个例子来解释。假设由基础架构团队执行对PROD的部署。该团队可以访问您配置文件中所需的密码。出于安全原因,他们永远不会向您(部署开发人员)透露此密码。您希望避免他们在每次安装时输入密码。想一想,这是您能做的最好的事情。他们至少需要输入一次密码。

在这里,加密解决方案并不真正起作用,因为您的部署包仍然需要一种方法来解密密码,如果它可以在没有用户输入的情况下完成,那么您(开发人员)也可以这样做,这是不可接受的。

由于密码以明文形式存储在PROD配置文件中,因此部署包应仅在不知道密码时提示输入密码。一旦基础设施团队成员提供了密码,请将其保存在本地文件中。最好将其保存在机器范围的密钥容器中,这样您就不需要密码了。下次安装时,密钥已经被知道,您的安装程序将不再需要提示输入密钥。当然,如果需要,您需要提供一种更改存储密钥的方法。

您所描述的标记化方法是有效的。我已经成功地使用这种方法相当长时间了(即通过外部安全审查)。由于PROD中有明文密码,因此必须考虑PROD是安全的环境。既然它是安全的,那么在其中缓存(存储副本)此安全密码是没有问题的。


0
无论您使用非对称还是对称加密,都需要将解密密钥保存在代码中,这样就将安全风险从配置文件转移至可执行文件(代理)中。从混淆方面来看,这要好得多,但是如果有人足够决心地提取解密密钥,可执行文件实际上是可以被反向工程的。

不,我在问题中提到私钥存储在代理“机器”的KeyStore中,并且对机器的访问将受到限制。 - manojlds

0
创建一个定时任务来运行部署脚本怎么样?将任务设置为使用特定的用户账户运行,并授予该账户相关权限。

抱歉,这没有意义。为什么预定的工作在这里出现了? - manojlds
您可以为作业提供备用凭据,因此无需提示输入密码。让作业完成所有部署工作。 - vonPryz
在这里的重点是,您只需配置作业一次,并提供凭据一次。从现在开始,在这些凭据下,您可以进行任意多次部署。无需每次提示。 - Andrew Savinykh

0
一个有趣的问题,我也使用多个环境,并且面临不同环境的不同设置的挑战。我们并没有在配置文件中放置密码(因为机器被攻击或工程师犯了错误等原因)。如果我们这样做,那么它们就是相当不安全的东西,因此我们将它们保持为纯文本。
考虑到这一点,构建机器是否可以没有每个环境的密码列表?
如果您不想将它们保持为纯文本,则可以尝试使用PowerShell进行某些操作-我确信Jaykul曾经在这方面发表过文章,但我的(快速)搜索只返回了Halr的一些内容(两者都是PowerShell MVP,所以应该很有趣)。

http://halr9000.com/article/531


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接