Tutorial: Upgrading passwords to bcrypt


Foreman uses SHA1 for hashing user passwords and personal access tokens up to version 1.22 . Starting with version 1.23, Foreman now supports bcrypt password hash function which was designed for passwords from the very beginning. It has an unique feature of cost value which allows making the hashing algorithm slower and slower as CPUs are getting faster and faster. For more info read Wikipedia or google it.

What you need to do after upgrade or new install? Existing users still keep their passwords hashed with SHA1 while new users or those who changed password will take advantage of bcrypt. Therefore for existing deployments, all users should be asked to change passwords. It does not need to be a change actually, Foreman will not enforce a different password as well as it does not force users to change password after login. Do ask your users in other way (e-mail, etc).

Before proceeding, please review bcrypt cost value in the Administer - Settings section. The value does not need a change as Foreman performs a quick calibration test and sets default cost to be as slow as at least 50ms with minimum cost value 5 when this setting is not yet set manually. On my CPU (AMD Ryzen 1700 from 2018) these are rough numbers representing time to try one password if you want to set explicit value:

Bcrypt cost Time
9 31ms
10 61ms
11 123ms
12 247ms

Anything above is probably too much today. As you can see the time grows quite fast so there is enough room for future CPUs. Recommended minimum cost value is 10-11 today (time around 50-100ms) so the calibrated value should be something like that. It rare cases when Foreman hardware/VM was CPU-busy during database seed (when calibration happens) the cost value can be set to it’s minimum value (5) which is probably too weak. If usure set it to 1 to force calibration on the next restart.

Before setting the cost, it is important to understand that when the CPU needs 200ms to calculate the hash, every single user login action will also consume 200ms of CPU resource. Previously SHA1 was very fast (which was the actual problem we solved), around 1ms. Please keep in mind that API requests which are not using sessions (via hammer login) need to do password calculation on each request. Heavy API users might want to set the value to something from the lower range (7-9).

Never set high numbers like 15 as CPUs are not fast enough (2019) and this would cause a login action to take minutes instead few miliseconds. Amount of time spent in calculating hash can be exported via telemetry metric login_pwhash_duration. Keep in mind that the cost value is always a trade-off - more electricity spent, more costs, more time to change passwords when attackers grabs the database.

To get a list of users who still has SHA1 password hash do this (list password hash fields which do not start with $2$ which is the prefix for bcrypt):

# foreman-rake console
> User.unscoped.all.where("password_hash not like '$2$%'").pluck(:login)
=> ["admin", "org_admin", "myorg_manager", "secondorg_manager", "auditor"]

All these users can be easily emailed, if you created such a script please share it in this thread. This page is a wiki, feel free to improve the text when needed.

The PR is actually not yet merged, crossing my fingers for 1.23 tho:

The PR is in! Thanks @TimoGoebel, @tbrisker and others for review.

1 Like

It would be good to publish this as a blog post when 1.23 is out. That way, everyone with RSS enabled will be notified. Also we could add drawer notification recommending user to change the password, if they still use SHA1.

1 Like

Added it to the list of features: Foreman 1.23 schedule and planning and we can push this as a blogpost when RC is out.