Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Saltstack sample of using states and pillars for users
Here is a sample of how I am currently dealing with users.
Big thanks to uggedal! I used his user states as an example: https://github.com/uggedal/states
###
# How to create password hashes
###
python -c "import crypt; print crypt.crypt('password', '\$6\$SALTsalt\$')"
###
# top.sls in pillars
###
base:
'*':
- groups
- users
###
# users.sls
###
users:
user1:
fullname: Robert Hernandez
uid: 5000
gid: 5000
shell: /bin/bash
home: /home/user1
groups:
- wheel
- admin
password: $6$SALTsalt$UiZikbV3VeeBPsg8./Q5DAfq9aj7CVZMDU6ffBiBLgUEpxv7LMXKbcZ9JSZnYDrZQftdG319XkbLVMvWcF/Vr/
enforce_password: True
key.pub: True
user2:
fullname: Joe Smith
uid: 5031
gid: 5031
shell: /bin/bash
home: /home/user2
password: $6$SALTsalt$UiZikbV3VeeBPsg8./Q5DAfq9aj7CVZMDU6ffBiBLgUEpxv7LMXKbcZ9JSZnYDrZQftdG319XkbLVMvWcF/Vr/
groups:
- admin
key.pub: True
###
# groups.sls
###
groups:
admin:
gid: 6010
###
# top.sls in states
###
base:
"*":
- groups
- users
###
# groups.sls
###
{% for group, args in pillar['groups'].iteritems() %}
{{ group }}:
group.present:
- name: {{ group }}
{% if 'gid' in args %}
- gid: {{ args['gid'] }}
{% endif %}
{% endfor %}
###
# users.sls
###
{% for user, args in pillar['users'].iteritems() %}
{{ user }}:
group.present:
- gid: {{ args['gid'] }}
user.present:
- home: {{ args['home'] }}
- shell: {{ args['shell'] }}
- uid: {{ args['uid'] }}
- gid: {{ args['gid'] }}
{% if 'password' in args %}
- password: {{ args['password'] }}
{% if 'enforce_password' in args %}
- enforce_password: {{ args['enforce_password'] }}
{% endif %}
{% endif %}
- fullname: {{ args['fullname'] }}
{% if 'groups' in args %}
- groups: {{ args['groups'] }}
{% endif %}
- require:
- group: {{ user }}
{% if 'key.pub' in args and args['key.pub'] == True %}
{{ user }}_key.pub:
ssh_auth:
- present
- user: {{ user }}
- source: salt://users/{{ user }}/keys/key.pub
{% endif %}
{% endfor %}
@cmeisinger

This comment has been minimized.

Copy link

@cmeisinger cmeisinger commented Apr 9, 2013

Thanks for the example, truly helpful. :) One thing that bit me when testing this was that pillar data wasn't available when testing via salt * state.sls . Once I ran it through highstate though, it worked like a charm!

@me-vlad

This comment has been minimized.

Copy link

@me-vlad me-vlad commented Sep 9, 2013

For password hashes with random salt you can use one-liner:

python -c "import crypt; print(crypt.crypt('password', crypt.mksalt(crypt.METHOD_SHA512)))"

If salt arg not provided for crypt.crypt(), the strongest method available will be used.

@fangpenlin

This comment has been minimized.

Copy link

@fangpenlin fangpenlin commented Jun 21, 2014

Thanks, this is really helpful. Here I share a better script for creating hashed password

import os
import sys
import hashlib
import getpass
import crypt

# crypt cannot generate correct result under OSX,
# so we need to ensure this is running under linux
if sys.platform != 'linux2':
    print 'Can only be ran under Linux'
    sys.exit(-1)

salt = hashlib.sha1(os.urandom(64)).hexdigest()
insalt = '$6${}$'.format(salt)
password = getpass.getpass('Password: ')
repeat = getpass.getpass('Repeat: ')
if password != repeat:
    print 'Password does not match'
    sys.exit(-1)
hashed = crypt.crypt(password, insalt)
print hashed
@bgdnlp

This comment has been minimized.

Copy link

@bgdnlp bgdnlp commented Apr 9, 2015

Commenting because this is one of top results on Google for 'saltstack generate password hash'. Note that the one-liner above is for Python >= 3.3 and will generate a salted hash using SHA512.

According to the documentation, Python's crypt() is an interface to OS's crypt() function. Also:
If salt is not specified or is None, the strongest
available method will be selected and a salt generated. Otherwise,
salt may be one of the crypt.METHOD_* values, or a string as
returned by crypt.mksalt().

So, simply executing
python3.4 -c "import crypt; print(crypt.crypt('password'))"
will generate a salted hash of 'password', using the strongest method available to the current OS. Which beats the script that is restricted to Linux only (why? there are others that work just fine), provided Python >= 3.3 is available. The script works on Python < 3.3 though.

@maschinetheist

This comment has been minimized.

Copy link

@maschinetheist maschinetheist commented Jun 30, 2015

Is there a way to create just a user and make his primary group to be an already existing group? I've been hacking away on this for the past few hours but can't seem to get it done. The state creates a group with a name based on the username.

EDIT: I seem to have figured that out:

{% for user, args in pillar['users'].iteritems() %}
{{ user }}:
  user.present:
    - home: {{ args['home'] }}
    - shell: {{ args['shell'] }}
    - uid: {{ args['uid'] }}
    - gid: {{ args['gid'] }}
{% if 'password' in args %}
    - password: {{ args['password'] }}
{% if 'enforce_password' in args %}
    - enforce_password: {{ args['enforce_password'] }}
{% endif %}
{% endif %}
    - fullname: {{ args['fullname'] }}
{% if 'groups' in args %}
    - groups: {{ args['groups'] }}
{% endif %}

{% if 'key.pub' in args and args['key.pub'] == True %}
{{ user }}_key.pub:
  ssh_auth:
    - present
    - user: {{ user }}
    - source: salt://users/{{ user }}/keys/key.pub
{% endif %}
{% endfor %}
@yogeshraheja

This comment has been minimized.

Copy link

@yogeshraheja yogeshraheja commented Nov 11, 2016

Very informative example, Thank you.

I am facing some issues, I am working on multiple CM tools and all worked fine for me in Puppet and Chef. Recently doing POC on salt and stuck at password level. Though all worked fine but I am unable to use the password for login (infact /etc/shadow is also empty at password field). Could someone have a look:

[root@salt users]# cat /srv/salt/top.sls
base:
'':
- users
[root@salt users]# cat /srv/salt/users/init.sls
{% for user, args in pillar.get('users', {}).items() %}
{{user}}:
user.present:
- uid: {{ args['uid'] }}
{% if 'shell' in args %}
- shell: {{ args['shell'] }}
{% if 'passwd' in args %}
- passwd: {{ args['passwd'] }}
{% endif %}
{% endif %}
{% endfor %}
[root@salt users]# cat /srv/pillar/top.sls
base:
'
':
- users
[root@salt users]# cat /srv/pillar/users/init.sls
users:
test10:
uid: 3333
shell: /sbin/nologin
test11:
uid: 3334
passwd: '$6$somesalt!$3UQn7wIuHJUkfawfTqftXADbm88MhnV/hYIcDStmcVTEzWyO4ovUe9bYcpL1Nl5ae1wagxAJEqfTMyf1dsMGA1'
test12:
uid: 3335
[root@salt users]#

PS: I tried with multiple password options, nothing worked for me.

Regards,
Yogesh Raheja

@smitelli

This comment has been minimized.

Copy link

@smitelli smitelli commented Jan 12, 2017

@yogeshraheja I think you want password, not passwd.

Also be aware that there is hash_password, which is false by default. hash_password: False means that password is already hashed, but hash_password: True means that password is stored in plaintext and must be hashed by the underlying module.

@pasanmdev

This comment has been minimized.

Copy link

@pasanmdev pasanmdev commented May 23, 2018

@UtahDav Thanks for this sharing, It really saved my day :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.