Securing Passwords in settings.xml (MNG-553)
Goal
Provide a way for securing passwords in settings.xml, instead of just storing it in plain text.
Design
- Password Obfuscation
- Provide a plugin which a user can use to obfuscate their passwords and use this generated secured password in their settings.xml file.
- Implement reading of obfuscated passwords in Maven (plexus? or maven-core?)
- add a flag/parameter to enable the use of obfuscated passwords in Maven during the build. Add an <obfuscation> parameter in the settings.xml, as suggested by Benjamin (see comment below). In this case, Maven would check first the value of this parameter and perform un-obfuscation to the password if specified.
- or, use a keyword prepended to the password to tell Maven that the password is obfuscated (like what Jetty does). For example, <password>OBF:securedPassword</password> with 'OBF:' as the keyword.
- Prompt for a password if none is found in the settings.xml. Use a parameter like the --non-interactive flag of the maven-release-plugin in order to disable this. (Already handled by Wagon as pointed out by Brett)
- Password Encryption
This can be implemented in two ways:- Using a keystore for the server passwords
- Interactive:
- Use plexus-password-store (http://svn.codehaus.org/plexus/archive/plexus-sandbox/trunk/plexus-components/plexus-password-store) to create the key store where the server credentials would be stored. Maven can also use this component for accessing the keystore as specified in the next point.
- In Maven:
- Add a parameter to tell Maven the location of the keystore. (Ex. -DkeystoreLocation=/path/to/keystore)
- If the keystore location parameter is specified, Maven would disregard the <password> set in the settings.xml file (if there is any) and prompt for the master password of the keystore. The server credentials will be retrieved from the keystore if the entered master password is correct. Use the retrieved credentials to access the secured server.
- Otherwise, use the <password> (if there is any) set in the settings.xml file. (Take into account password obfuscation here if it will be implemented.)
- Non-interactive:
- Same implementation as 'Interactive', except that the master password for the keystore can be set via a command-line parameter instead of Maven prompting for it. The drawback here is that the master password would be in plain text.
- Interactive:
- Using password-based encryption on the password in <settings.xml> (see Oleg's comment below)
- Using a keystore for the server passwords
Limitation(s)
Password Encryption:
- <password> in settings.xml would be disregarded if the server credentials would be retrieved from the key store.
25 Comments
Benjamin Bentmann
Regarding the flag/parameter to enable obfuscation: How about just extending the settings model such that the user can control the obfuscation method per server, proxy etc:
The addition would require an update to Maven anyway so one could also update the settings parser.
Brett Porter
Would it be better to have a plugin instead of a utility JAR? That might be helpful to the Jetty folks too, so it'd be good to check in with them.
I agree with either using OBF:* or the <obfuscatedPassword /> suggestion of Benjamin.
I believe prompting is already handled by Wagon so isn't needed at this stage. This also means the implementation is probably all within the settings reader.
Maria Odea B. Ching
I agree, adding an <obfuscation> parameter and using a plugin instead of a utility jar sounds reasonable. I've added these in the design doc above. I've also commented that the password prompting is already handled by Wagon. Thanks for your comments and suggestions..
Benjamin Bentmann
Is that really necessary? I mean, once you have a dedicated parameter like <obfuscation> along the password string, why not trust its value? If it's not working, it's a misconfiguration by the user and he/she should fix it. So I believe a single attempt to authentificate is always sufficient. For the approach with "OBF:securedPassword", one wouldn't do this second trial either in case the first one failed, would one?
Maria Odea B. Ching
Yes, it shouldn't. Sorry, I just forgot to remove that part in the design doc. I was originally thinking when I written the first draft that the parameter/flag that will be used is a command-line flag that would tell maven to un-obfuscate the password(s) in the settings.xml. I was considering the scenario of "what if not all the passwords were obfuscated" that's why I had that part in the doc. Anyway, what you suggested about adding an <obfuscation> parameter made much more sense..
Maria Odea B. Ching
Note: The above proposal does not yet take into account what Oleg already implemented in plexus-cipher. Maybe he can shed some light where the plexus-cipher would fit in?
Olle Jonsson
What I did was:
The encrypted password looks like this:
It may take me a day or two to restore all these, all the pieces are here and there. As I was not a Maven comitter at the time - I could not put then all into Maven
Maria Odea B. Ching
Ok, thanks Oleg I guess we can move the components into one location once you've located them and start from there?
Olle Jonsson
Maria, I found the maven plugin, and plexus-cipher. Those are the two big ones, we can change the rest really easy.
Olle Jonsson
I added maven-crypto-plugin to Sonatype.org SVN under plugins/trunk.
My previous implementation details: I kept master password encrypted in the settings.xml. When thre was a need to use it, I first searched settings.xml for a dummy server id="dummy.master.server" and used that password as a master. Otherwise I asked user for it and stored it in settings before proceeding.
I will check with my schedule if I can be available this week for this project. If I do - I will try to recreate my old code.
Brett Porter
Sorry Oleg, I'm a bit confused by your last statement... does this rewrite settings.xml with a password in plaintext?
In some ways I like the simplified encryption handling proposed here - though the keystore has advantages too (for example, the ability to use the OS X keystore as someone pointed out in the issue, and not needing to deal with encrypted passwords at all). Without going overboard, being able to make the "provider" replaceable would also be important for consumers of the embedder, so the IDE integration can store passwords somewhere else, etc.
Deng, what about the simpler obfuscated passwords as a simple first step - is that still being considered?
BTW, Given the availability of the Maven 2.1.x branch now it'd be great to have this put into the core settings handling rather than having to configure a plugin, IMO.
Unknown User (ddimitrov)
Hello,
I am not sure whether the current proposal addresses the following use cases, so I'm listing them here:
Probably #3, #4 and #5 can be somehow handled by the same VM options.
Olle Jonsson
The I propose to do it - no, it always keeps encrypted passwords in settings.xml and if there is a request for a password -it's intercepted, and, if password exists but is not encrypted, it gets encrypted. If it does not exist - user is prompted for one.
Plugin is necessary as it allows user manipulate those passwords - add/change them
It's exactly the same amount of work because because encryption itself has already been implemented (same as the entire described encryption schema, by the way )
Brett Porter
Right... sorry if I'm being dense, but the two bits I don't get there are:
1. "if password exists but is not encrypted, it gets encrypted" - that means it is in the settings.xml unencrypted, and gets encrypted and settings.xml gets written again?
2. where does the master password get stored? It seems to be in plain text in a dummy server from the description (or prompted). This is the big question for me - how do we avoid having to type this too much, but still avoid opening it all up?
Totally agree - I was thinking more of the "intercept" bit on loading/using the settings being built in
Thanks!
Olle Jonsson
Dimitar - great questions.
settings.xml is by definition a single user's config. storage. I think more general approach would be a team server approach - minimum information is stored per user, the rest comes from an outside source, so that you don't have maintain 30 copies of any other configurations in the settings and yet preserve one settings.xml per user, but here it only stores passwords for this single user.
With the above approach env. does not have to be public, users have their individual passwords.
I tried it - it's not portable across platforms, especially windows. Better option is standardize on, say, PGP and pass a master key ID from keyring
Agree, see my previous comment - answers to Brett
Command line issue again - not portable. Better use PGP.
Overall, again - great questions, those are the use cases I would like to address!
Olle Jonsson
Yes, it does
In settings.xml - see one of my comments above - search by "master password encrypted". Each user has their own settings.xml and master password.
Unknown User (ddimitrov)
Hi Oleg, thanks for the answers.
Just to clear it up:
A company I worked in had a policy that all release build has to be made from specific account on specific machine. Everybody had access to the account, but only the release manager knew the password for the deployment connection. In such case, if we store the private key in the account's PGP keyring and the passphrase in the user's settings.xml file, then everybody would be able to upload/change the builds on the staging server.
Does it make sense or is it an isolated case?
Olle Jonsson
Dimitar,
In the setup you just described,
The first one seems cleaner to me.
Unknown User (ddimitrov)
Oleg, I agree that #1 looks better to me as well.
Olle Jonsson
But all that nice group stuff is only possible if we standardize on something like PGP or Java sec - we need a standard security storage.
PGP as OpenPGP is much more broadly used so to me it seem the only valid choice. GPG implements it, Bouncy Castle has it, I think it's a winner
Maria Odea B. Ching
Hi Oleg, thanks for adding the maven-crypto-plugin I just have some questions about some of the things mentioned above:
And if the password is encrypted, then ask for or get the master password to decrypt it and use the decrypted password to access the server?
Sorry, I think I misunderstood this part.. I originally thought that the master password for decrypting the <server> password will always be prompted when Maven executes. In the above implementation, you mean the master password will be set as an encrypted password of another <server> entry in the settings.xml?
Olle Jonsson
If encrypted master password is in settings.xml, and secret material used to encrypt it is in the code - it's obfuscation, if we have external source for it (ask user, get from external keystore) - it's real encryption.
Big problem with it - users run Maven tens and hundreds times a day, there is no way they will tolerate typing the password that many times, so - really - the only way to address this, is an OS session piggy back.
As we also need be portable across platforms, solution seem obvious: either java keyring or adapter to existing keyring solution. Here - GPG's OpenPGP seem very attractive.
Personally - I don't like JNI because of maintenance costs, so I am wide open to suggestions: how to store secret material in OS user session. Once we find solution - it's downhill from there.
Maria Odea B. Ching
I've been looking for other alternatives on how or where we can store the master password and so far I have found none I have also been looking at the gpg-agent which is the one that caches the GPG passphrase.
Olle Jonsson
I am adding a solution to the above described problem to 2.1.x.
I already implemented the encryption (AES 128, with SHA256-based PBE) as well as an IT for MNG-553. I will try to commit it today.
Solution is the one I described at the beginning of this thread and implemented for 2.0.7 code base back in 2007. I now modified my code to account for the use cases described here and get rid of BouncyCastle provider, that was adding 1.6M to the footprint
Olle Jonsson
I updated MNG-553 with a short documentation of the solution