New Feature: Maven Settings Password Encryption

February 3rd, 2009 By oleg

The problem of eliminating clear text passwords from all media has a long history of failure and success. In the first years of the HTTP protocol, designers, despite existence of asymmetric encryption, decided not to use anything. Later, having been burned by cleartext passwords, they added base64 encoding. Which, as one may guess, did not fool anyone in the business of retrieving those passwords.

Luckily – Netscape introduced the SSL tunnel for HTTP, which was widely and enthusiastically accepted. This eliminated some of the threats, but had nothing to do with protecting the password storage.  Most systems that interact with an authenticated service over HTTP still have to figure out a way to store these credentials.  The alternative is for the serivce in question to use something like OAUTH or a distributed ticketing system (ala Facebook or Twitter).   But, for most systems that need to interact with an authenticate service of HTTP this is a serious problem.   If you need to deploy to an authenticated repository manager like Nexus, how do you avoid putting your password into your build?

The Problem with settings.xml

Maven repository access uses a plaintext password over HTTP (preferably HTTPS) and most people have a situation when passwords are kept in the open in the settings.xml file.   If you use settings.xml as designed, you’ll have a clear security vulnerability if your settings.xml is publicly accessible. There was a long discussion on the codehaus confluence about this issue last August.

settings.xml contains two very distinct types of content serving two distinct purposes: the servers section really stores credentials while the rest of the file is all about profile customizations.  The servers section contains all the private data, while the rest is more or less open.   If you are using the settings.xml file as documented and as recommended, you’ll have a situation where one part of the file should not be widely distributed and the other part of the file must be widely distributed for a build to work.  This creates an inconvenience as some manual work is required to share your organization’s setting.xml between developers.  If you check a global settings.xml into Subversion, do you check in the passwords as well?   If every potential attacker knows that the ~/.m2/settings.xml contains sensitive credential information, is this really an acceptable security risk?

Having such a file on your single-user laptop or private machine is likely an acceptable (but not ideal) risk. But, putting this file on a shared box like a Continuous Integration or shared build machine where any individual with malicious intent can compromise your repositories in no time is totally unacceptable.

To mitigate these risks, it’s recommended to store all private data in ~/.m2/settings.xml and all the rest – in ${maven.home}/conf/settings.xml. But here is the problem again – if you upgrade maven and put it into another folder, you have to also move the global settings.xml. Or – if switching between several versions of maven – having to maintain all those separate settings.xml files in-sync presents a major inconvenience, to say more.

New Feature: Maven Settings Password Encryption

To address these issues, I added password encryption to maven 2.1.x trunk. This is a very straightforward change, which I ported from a change I made to maven 2.0.8 in 2007 but never committed before. This feature checks the passwords when in memory, and decrypts them if they have the pattern {xxx}. I also provided a CLI to encrypt any string.

Details: the encryption is using JDK’s AES 128 cipher and PBE SHA256 key preparation, which I took from a very interesting not-yet-commons-ssl project – APL-2.0 based.

To use it, you need to first generate a master password – with:

java -jar ${maven.home}/lib/maven-uber.jar \
           org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher -m

It will ask for master password and will output the encrypted version of it. Store this string in ~/.m2/settings-security.xml:

<settingsSecurity>
  <master>{jSMOWnoPFgsHVpMvz5VrIt5kRbzGpI8u+9EF1iFQyJQ=}</master>
</settingsSecurity>

After that – you can encrypt regular passwords and store them in settings.xml. Run:

java -jar ${maven.home}/lib/maven-uber.jar \
          org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher -p

Supply the password and then store the output string in settings:

<server>
    <id>my.server</id>
    <username>foo</username>
    <password>{COQLCE6DU6GtcS5P=}</password>
</server>

That’s all – you can start deploying to the server right away – Maven will decrypt it on the fly. You can stop worrying about mvn help:effective-settings or release POM exposing your passwords – they show up encrypted there.

Summary and Best Practices

Remember – the weak spots in this schema are:

  • The master password is only propected by the Operating System’s access rules: always restrict access to ~/.m2 – make it readable and by owner only
  • The server password is decrypted in memory and consumed by wagon provider, so if somebody can scan the memory or intercept the wire transmission (if it’s not encrypted), they can compromise your server.

To address the use case, where several people share one account, or you’d like to have security above OS access – you can use master password relocation feature – use xml like:

<settingsSecurity>
  <relocation>/Volumes/mySecureUsb/secret/settings-security.xml</relocation>
</settingsSecurity>

and store the real master password on a usb drive. In this case – only a person with that drive can deploy to the server.

 

How-To, Maven, Sonatype ,

This website uses IntenseDebate comments, but they are not currently loaded because either your browser doesn't support JavaScript, or they didn't load fast enough.

  1. james
    February 3rd, 2009 at 15:40 | #1

    Whats to stop a user on a CI system changing their deployment server URL and then just retreiving the password from a dummy server. It is alas no more than security through obscurity.

    • February 3rd, 2009 at 17:07 | #2

      Nothing, I tried to make it clear in the posting – the default solution addresses only local box use cases, and maybe – not all of them – please see the Confluence discussion I mentioned at the beginning.

      Even the local encryption can be called "strong" only if one uses the relocation feature and maintains a good master password.

      But what's there is just a tip of the iceberg, I really implemented a framework, that will allow us to enhance this feature a way beyond the current solution. This is a necessary baby step, what happens to address some of the most urgent use cases. And it leads towards more mature solutions. I will discuss those in the future postings on the subject.

  2. Brian Jackson
    February 3rd, 2009 at 16:15 | #3

    I love the concept but not the implementation. Why can't you simplify the command? How about make it a Maven plugin so users can run something like "mvn security:master" and "mvn security:password" so that it fits in with all the already established Maven conventions? How many times am I going to have to google for this command because I'll never remember it?

    • February 3rd, 2009 at 16:48 | #4

      Brian – I briefly mentioned it in the JIRA, but not in this post, my bad. Yes – I already have the plugin that eliminates the need for CLI. This CLI is just a temporary ugly tool to close the loop, it enables us use it right away.

      The plugin addresses the use cases you mentioned, so you are right on the money!

  3. February 3rd, 2009 at 16:44 | #5

    I briefly mentioned it in the JIRA,but not in this post: yes – I already have the plugin that eliminates the need for CLI. This CLI is just a temporary ugly tool to close the loop, it enables us use it right away.

    With the plugin I will cover the mentioned use cases, you are right on the target!

  4. February 3rd, 2009 at 19:29 | #6

    In the latest trunk – settings-security.xml's root tag is renamed to <settingsSecurity>

  1. No trackbacks yet.