Using RhodeCode Auth Tokens to replace SSH Keys

Published on January 03, 2017, by Marcin Kuzminski


SSH keys are handy when it comes to using them in Version Control Systems, in particular, they allow:

  • Passwordless operations when pushing or pulling (checkout in svn)
  • Easy integrations with scripts without storing credentials inside them
  • Stored keys limits usage to only VCS operations.

There are some disadvantages, however:

  • Users need to create a new keyset just for VCS operations. It's not recommended to use the same one that allows login to the machine for example.
  • Windows is always a problem to start using SSH keys for end users.
  • Some of the added features might not work with SSH, in particular, things like IP restrictions, Git LFS also is problematic.
  • Many companies block SSH ports on their infrastructure making usage of SSH keys problematic.

RhodeCode Auth Token authentication is an alternative solution

With RhodeCode Auth Token users can benefit from the advantages of using SSH keys, as well as remove the listed disadvantages.
RhodeCode Auth Token authentication system is similar to Google's app-specific passwords.
Each user is allowed to generate special auth tokens, that have a special role, and optionally expiration. There are several roles available:

  • API (limited to use with RhodeCode API)
  • VCS (limited to GIT/HG/SVN protocol operations only, users cannot log-in via web interface with it)
  • RSS (Allows access to RSS feeds ONLY, safe to put in your Outlook, or RSS browser in plaintext)
  • WEB (allowed to be used with a defined white-list of web interface endpoints. Meaning a raw-diff can be exposed by adding a GET flag on login-protected content. Users can expose raw-diffs to 3rd part code-review tool for example)

All of those tokens are generated as 40 char random hash, which is hard to memorize, similarly to SSH keys.
Tokens can be configured with pre-defined expiration, eg. 5min, 30days or never, and all of those can be revoked manually
from the web interface.

Tokens with an expiration date can be shared with external parties so
users never need to worry about remembering to revoke their access. This allows a high level of control usually not available
in other system that use SSH keys as an authentication method.

VCS tokens are the ones that could be used in exchange for SSH access. The most common use cases are:

  • allowing users to have passwordless operations for VCS
  • Integrate with 3rd part, like CI without storing any system passwords

Since those tokens are based on HTTP it's possible to keep additional security layer like IP restrictions and it's not affected by blocking SSH ports.
Tokens don't require any additional configuration on the client side, they are simply used as alternative passwords.

Configuring passwordless access

Using .netrc file for GIT, or .hgrc for Mercurial allow easy users to operate without typing their password each time.

For GIT (~/.netrc):

machine code.company.com  
login john  
password *token*  

For Mercurial (~/.hgrc):

[auth]
rc.prefix = code.company.com  
rc.username = john  
rc.password = \<token\>  

Edit: Added few notes based on feedback we recieved:

Git will not match the machine name in your .netrc if it has a username in it, so make sure you edit
your .git/config file in the root of your clone of the repository and remove the user and '@' part from any clone URL's
(URL fields) that look like https://user@machine.domain.com/... to make them look like http://machine.domain.com/...

Also it's recommended to add wrapper of git credentials helper to allow it to read .netrc file.

git config credential.helper "netrc -d -v"  

There are even safer solutions like keychain extensions which allows to store credentials inside system keychain on OSX or Windows

https://www.mercurial-scm.org/wiki/KeyringExtension
https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage

Scripts integration, CI servers

Auth tokens can be integrated into 3rd part scripts, one good example is how we used it in our internal
rhodecode-export script, we added a CLI parameter to the script which passes internally
the token to the call, so you use it like that:

example-script --auth-token=<token>  

In case you really don't want any traces of passoword on CLI this could be changed to:

rhodecode-export --auth-token-from-file=/path/to/file_with_token.txt  

So we can read the stored token from specified file.

Inside our example script we use the given token to run such example push call:

run_command("hg push admin:{token}@https://{server}/{repo}".format(auth_token, server_name, repository_name))  

In this example auth_token is extracted either from the CLI option, or read from file.

Another approach is to use the env parameters that are very common in UNIX world

RC_AUTH_TOKEN=<secret> example-script  

In this case for Python auth_token is then read from the environ variable

auth_token = sys.environ('RC_AUTH_TOKEN')  

Conclusion

We believe that our auth-tokens is a good alternative to using SSH keys. Moreover there are several advantages, firstly, combining this with
IP restriction means that even if your token is exposed, RhodeCode will report and block the usage of such token when used with a wrong IP address.
Tokens are also assigned with roles, so if you loose your RSS feed token stored in outlook it could never
be used to log-in to the web-interface. When your company uses LDAP, RhodeCode always checks the bound accounts, meaning that a token attached to a
disabled LDAP account will not work. It uses our standard authentication-plugin mechanism. Each plugin can be configured to
any standards that your company uses, just with a little bit of Python knowledge it's possible to fetch such tokens directly from your LDAP server.

To enable full usage of auth-tokens, please enable Rhodecode Token Auth under admin > authentication in your RhodeCode instance.