Best way to change users UID and GID?

534 views
Skip to first unread message

Marc Evans

unread,
Dec 20, 2013, 10:27:27 AM12/20/13
to salt-...@googlegroups.com
Hello,

I am new to using salt. I have about 50 systems that have been hand managed over time and are quite inconsistent as a result. One of the first things that I would like to do is to craft consistent /etc/passwd and /etc/group contents. What this implies is that many UID and GID settings for various entries will get changed. When such changes occur I need to then change associated UID/GID on all of the filesystems contents to match. What I am looking for is a best practice recommendation for performing that work.

At this moment I have a users.sls formula that leverages pillar information for the users. That works great for creating new users, and to some degree even works for changing existing users. What is mainly missing is hooking the filesystem actions, e.g. run something like:

    find / -not -path /proc/\* -a -gid {{ old_gid }} | xargs chgrp {{ new_gid }}

after a change to /etc/group or similar to a change to /etc/passwd.

1) How do I hook into the process to take action when a change to UID or GID is made?
2) Is there a way for me to know the before and after values of the UID or GID that is being changed?

For reference, the formula that I am using (and happy to take suggestions for change) is:

{% for username, user in pillar.get('users', {}).items() %}
{{ username }}:

  group:
    - present
    - name: {{ username }}
    - gid: {{ user['gid'] }}

  user:
    - present
    - fullname: {{ user['fullname'] }}
    - name: {{ username }}
    - shell: /bin/bash
    {% if user['home'] is defined %}
    - home: {{ user['home'] }}
    {% else %}
    - home: /home/{{ username }}
    {% endif %}
    - password: {{ user['crypt'] }}
    - uid: {{ user['uid'] }}
    - gid: {{ user['gid'] }}
    {% if 'groups' in user %}
    - groups:
      {% for group in user['groups'] %}
      - {{ group }}
      {% endfor %}
    - require:
      {% for group in user['groups'] %}
      - group: {{ group }}
      {% endfor %}
    {% endif %}

  {% if 'pub_ssh_keys' in user %}
  ssh_auth:
    - present
    - user: {{ username }}
    - names:
    {% for pub_ssh_key in user['pub_ssh_keys'] %}
      - {{ pub_ssh_key }}
    {% endfor %}
    - require:
      - user: {{ username }}
  {% endif %}

{% endfor %}

Thanks in advance for suggestions.

- Marc

Peter Niederwieser

unread,
Dec 20, 2013, 10:58:06 AM12/20/13
to salt-...@googlegroups.com
You should be able to trigger the `find` command as follows:

cmd:
  - wait
  - name: find / -not -path /proc/\* -a -gid {{ old_gid }} | xargs chgrp {{ new_gid }}
  - watch: 
    - group: {{ username }}

However, I'm not sure if `group.present` and `user.present` can cope with changing uids/gids. From what I remember, they fail if an entity with the same name but different id already exists.

Cheers,
Peter

Marc Evans

unread,
Dec 22, 2013, 10:17:31 AM12/22/13
to salt-...@googlegroups.com
I think I am getting closer thanks to the help from Peter. The problem that I am stuck on is how to have multiple cmd.wait_script. When I try the sls shown below only the second cmd.wait_script is actually used, the other one disappears. Clearly I am not grasping the syntax of an sls file adequately, but the many variations that I have attempted are worse. Does anyone have a suggestion? Also, is there a better way to deal with the /tmp/*.bak files that I force to be created?

$ cat users.sls
/tmp/passwd.bak:
  file.copy:
    - source: /etc/passwd
    - force: true
  cmd.wait_script:
    - source: salt://users/chuid.sh
    - name: export PASSWD_BACKUP=/tmp/passwd.bak && sh /var/cache/salt/minion/scripts/chuid.sh {{ username }} {{ username }}
    - watch:
      - user: {{ username }}

  cmd.wait_script:
    - source: salt://users/chgid.sh
    - name: export GROUP_BACKUP=/tmp/group.bak && sh /var/cache/salt/minion/scripts/chgid.sh {{ username }} {{ username }}

    - watch:
      - group: {{ username }}

{% endfor %}

Thanks in advance - Marc

Ethan Erchinger

unread,
Dec 22, 2013, 11:28:47 AM12/22/13
to salt-...@googlegroups.com
Add a new id declaration for each cmd.wait_script, instead of including it all under "{{ username }}:".  Something like:

{{ username }}_chuid:
  cmd.wait_script:
   ...
{{ username }}_chgid:
  cmd.wait_script:
   ...

{% endfor %}

Marc Evans

unread,
Dec 23, 2013, 9:27:49 AM12/23/13
to salt-...@googlegroups.com
Thank you Ethan, your suggestion worked well.

For anyone stumbling onto this thread in the future, I am attaching the files involved which you may find useful.

- Marc
users.sls
chuid.sh
chgid.sh

Marc Evans

unread,
Jan 3, 2014, 10:31:28 AM1/3/14
to salt-...@googlegroups.com
We have found a problem in the chuid.sh and chgid.sh scripts referenced above and modified them to avoid the problem. Specifically the prior versions cause suid and sgid bits to be lost for files operated upon. Please find replacement scripts attached here.

- Marc
chuid.sh
chgid.sh
Reply all
Reply to author
Forward
0 new messages