15

I have seen related questions here, but they don't seem to be answering exactly what I need.

We use Powershell scripts to deploy our applications and the info like passwords in configuration files for most of the environments ( UATs etc. ) are in plain text. It is not a big issue, but when it comes to PREPROD and PROD, it is a big issue. So we had some markers in the config like "{{prompt-password}}" which will give a login dialog (Get-Credential) and the person doing the deployment can enter the credential and the deployment continues.

But this doesn't really help for automated deployment ( meaning one-click deploy through tools like TeamCity )

Should I go for Asymmetric encryption ( http://msdn.microsoft.com/en-us/library/as0w18af.aspx ) where the password is encrypted using a public key, entered in the config, and private key is stored (as described here http://msdn.microsoft.com/en-us/library/tswxhw92.aspx ) in the "agent" ( as in a VM from where TeamCity will trigger the deployment and which has restricted access ) running the automated deployment and it can decrypt the password? Not really strong on Cryptography and stuff, but does this sound like the way to go? Any other suggestions? How do people handle such automated deployment?


Update:

Ok, I have gone ahead and implemented it. I have written a Console Application in C# which uses the Crypography libraries. The app generates the keys:

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

I also get out the public key:

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

Give the public key to anyone who has to encrypt the password and ask them to enter the password in the config. Put the keys.kez file in any agent that has to run the deployment.

mklement0
  • 382,024
  • 64
  • 607
  • 775
manojlds
  • 290,304
  • 63
  • 469
  • 417
  • Hey Manojlds, I was thinking about this today and I'm intrigued to know what you need the password for that couldn't be done via another means, say Integrated Authentication or a certificate (for proving who you are not decrypting)? – Matt May 26 '11 at 21:27
  • @Matt - say database password / connection string? – manojlds May 26 '11 at 22:33
  • you can use integrated authentication there - the user credentials used are the user the app pool or service is running as. – Matt May 27 '11 at 07:44
  • aha, I was just thinking just Microsoft. Cheers. – Matt May 28 '11 at 12:46
  • I'd really like a simple sample application for this for those of us not too familiar with crypto. I couldn't work out from the few lines of code provided exactly what they're doing. – Cody Konior Jan 02 '13 at 06:26

6 Answers6

4

Asymmetric encryption is definitely the winner here from a security and simplicity standpoint. I have deployed production SaaS apps in this manner very successfully.

There are a few tricks. One, as you mentioned, make sure the public/private key pair is installed on the host, not stored in config files or in the code. Two, assume the management and key generation tools provided by MS are weak to terrible and plan accordingly (we created a simple keygen exe for Operations to run during deploy.)

hemp
  • 5,602
  • 29
  • 43
2

Not really an answer, but a suggestion or an other question.

Why don't tou store the password in a crypted string in a config file

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

As far as I understand the documentation a process running with the same credential can get it back

$password = Get-Content c:\temp\password.txt | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential `
         "username",$password

You can replace $credential.Password by read-host -assecurestring

JPBlanc
  • 70,406
  • 17
  • 130
  • 175
  • 1
    `You can replace $credential.Password by read-host -assecurestring` - that is the point right. If you read my question that is what we do already - anything with {{prompt-password}} will be read as secure string and used in the config. That is fine for deployment through command line. Someone can enter the password. But when running through a build configuration in TeamCity, there is no way to enter / pass on the password. That is my question. – manojlds May 27 '11 at 17:12
  • 1
    I'am persuaded Asymmetric encryption is the best solution, I used it in many projects. But Sorry, just for my understanding. The agent is running with a special user. So if this user account is used to crypt the password and the crypted string is stored in the config file only this agent can decrypt the password, and it's also a solution ? where is my mistake ? – JPBlanc May 28 '11 at 06:25
1

As you said in your question, your password are kept in PROD in config file in plain text. No amount of encryption can help with that. Also, this is kind of a vicious cycle - how are you going to protect encryption key?

The key think here is to look at what is practical, and what kind of business workflows your organization follows when it comes to deployments.

Let me explain this on an example. Let's assume that the deployment to PROD is executed by an infrastructure team. This team has access to the password that is required in your configs. They will never disclose this password to you (deployment developer) for security reasons. You want to avoid them entering the password during each installation. To think of it this is the best you can do. They will have to enter the password at least once.

Cryptography solution won't really work here because your deployment package will need a way to decrypt the password anyway and if it can do it without user input, so can you (the developer), and this is not acceptable.

Since the password is store in PROD config files in plain text anyway, make the deployment package prompt for the password only if it's not know. Once a infrastructure team member supplies the password, save it in a file locally. Better yet, save it in machine-wide key container. You do not need a password for this. Next installation around the key will already be known, and your installation won't need to prompt for a key again. Of course you need to provide a way to change the stored key too if needed.

The tokenizing approach, that you described, works. I've been doing this for quite some time quite successfully. (I.e. passed external security reviews) Since you do have a plain text password in PROD, PROD must be considered secure (safe) environment. And since it safe, there is nothing wrong about caching (storing a copy of) this secure password within it.

Andrew Savinykh
  • 25,351
  • 17
  • 103
  • 158
0

Whether you use asymetric or symetric encryption you'll need to keep the deciphering key in your code so you are shifting the security risk from your configuration file to your executable (agent). It is much better in terms of obfuscation but the executable could conceivably be reverse engineered by someone sufficiently determined to extract the deciphering key.

Malcolm
  • 1
  • 1
  • No, I mentioned in my question that the private key is stored in a KeyStore in the agent "machine" and the access to the machine will be restricted. – manojlds May 26 '11 at 05:53
0

How about creating a scheduled job to run the deployment scripts? Set the task to be run with specific an user account and grant the account relevant permissions.

vonPryz
  • 22,996
  • 7
  • 54
  • 65
  • Sorry, doesn't make sense. Why did scheduled job come in to the picture here? – manojlds May 26 '11 at 05:56
  • You can provide alternate credentials to the job, so you don't need to prompt for password. Let the job do all the deployment work. – vonPryz May 26 '11 at 06:14
  • The point here that you configure your job once. And provide credentials once. And from now on you can do as many deployments as you like under these credentials. No need prompting each time. – Andrew Savinykh May 26 '11 at 07:15
0

An interesting question, I work with multiple environments as well and have the challenge of different settings for different environments. We don't really put passwords in the config though (a compromised machine or a mistake by an engineer etc...). If we do it's for pretty insecure stuff, as such we keep them plain text.

With that in mind could the build machine just not have a list of password for each environment?

If you don't want to you keep them plain text you may be able to do something with PowerShell - I'm sure Jaykul did a post on this way back when but my (quick) googling only returned something from Halr (both are PowerShell MVPs so it should be interesting) .

http://halr9000.com/article/531

Matt
  • 1,931
  • 12
  • 20