Automatic root passwords with Salt
The technical task is quite simple - to make automatic password rotation. Instead of storing it somewhere, delivering it somehow - you can greatly simplify it and generate it using an algorithm.
There are many benefits from this:
- no need to think about how to generate and rotate passwords (especially for new or dynamic hosts)
- the frequency of changing the password depends entirely on the formula
- predictability for history
- the raw password is not stored anywhere
What I came to:
- I don’t need unique passwords for each host.
- hosts are divided into groups and each group has its own seed (generated by:
openssl rand -base64 24
) - the algorithm is based on the username, seed and date
- the date is chosen based on the year and week number (i.e. the password will change every Sunday)
- the hash is cut to 15 characters. This is done specifically for several reasons:
- so that it can be quickly entered into the console when something goes wrong
- a similar algorithm is used to update passwords in IPMI (most have a 15 character limit)
The saltstack formula is as follows:
{% set password_seed = salt['pillar.get']('host:password:seed') %}
{% set curtime = None | strftime('%Y%V') %}
{% set password_plain = salt['hashutil.md5_digest']('-'.join(['root', password_seed, curtime]))[:15] %}
{{ tpldot }}.user.root:
user.present:
- name: root
- password: {{ password_plain }}
- hash_password: True
Let’s show the state:
root@bastion01:~# salt-call state.show_sls users.root --out yaml
local:
users.user.root:
user:
- name: root
- password: c8f867fcb4047cf
- hash_password: true
- present
- order: 10000
__sls__: users.root
__env__: base
For completeness, let’s show how to get this password via python:
#!/usr/bin/env python3
from datetime import datetime
import hashlib
SEED = '__SECRET__'
date = datetime.now().strftime("%Y%V")
plain = f'root-{SEED}-{date}'
passwordHash = hashlib.md5(plain.encode()).hexdigest()[:15]
print('password:', passwordHash)
p.s. I have password authorization over the network disabled, and the only way to get into the machine via password is through the console (IPMI).
p.s.s. In production for over 2 years. Works on 1000+ servers and is divided into 30+ host groups (each group has its own seed)