Saltstack Official Users Formula
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
6.0KB

  1. # vim: sts=2 ts=2 sw=2 et ai
  2. {% from "users/map.jinja" import users with context %}
  3. {% set used_sudo = False %}
  4. {% for name, user in pillar.get('users', {}).items() if user.absent is not defined or not user.absent %}
  5. {%- if user == None -%}
  6. {%- set user = {} -%}
  7. {%- endif -%}
  8. {%- set home = user.get('home', "/home/%s" % name) -%}
  9. {%- if 'prime_group' in user and 'name' in user['prime_group'] %}
  10. {%- set user_group = user.prime_group.name -%}
  11. {%- else -%}
  12. {%- set user_group = name -%}
  13. {%- endif %}
  14. {% for group in user.get('groups', []) %}
  15. {{ name }}_{{ group }}_group:
  16. group:
  17. - name: {{ group }}
  18. - present
  19. {% endfor %}
  20. {{ name }}_user:
  21. {% if user.get('createhome', True) %}
  22. file.directory:
  23. - name: {{ home }}
  24. - user: {{ name }}
  25. - group: {{ user_group }}
  26. - mode: {{ user.get('user_dir_mode', '0750') }}
  27. - require:
  28. - user: {{ name }}
  29. - group: {{ user_group }}
  30. {%- endif %}
  31. group.present:
  32. - name: {{ user_group }}
  33. {%- if 'prime_group' in user and 'gid' in user['prime_group'] %}
  34. - gid: {{ user['prime_group']['gid'] }}
  35. {%- elif 'uid' in user %}
  36. - gid: {{ user['uid'] }}
  37. {%- endif %}
  38. user.present:
  39. - name: {{ name }}
  40. - home: {{ home }}
  41. - shell: {{ user.get('shell', users.get('shell', '/bin/bash')) }}
  42. {% if 'uid' in user -%}
  43. - uid: {{ user['uid'] }}
  44. {% endif -%}
  45. {% if 'password' in user -%}
  46. - password: '{{ user['password'] }}'
  47. {% endif -%}
  48. {% if 'prime_group' in user and 'gid' in user['prime_group'] -%}
  49. - gid: {{ user['prime_group']['gid'] }}
  50. {% else -%}
  51. - gid_from_name: True
  52. {% endif -%}
  53. {% if 'fullname' in user %}
  54. - fullname: {{ user['fullname'] }}
  55. {% endif -%}
  56. {% if not user.get('createhome', True) %}
  57. - createhome: False
  58. {% endif %}
  59. {% if 'expire' in user -%}
  60. - expire: {{ user['expire'] }}
  61. {% endif -%}
  62. - remove_groups: {{ user.get('remove_groups', 'False') }}
  63. - groups:
  64. - {{ user_group }}
  65. {% for group in user.get('groups', []) -%}
  66. - {{ group }}
  67. {% endfor %}
  68. - require:
  69. - group: {{ user_group }}
  70. {% for group in user.get('groups', []) -%}
  71. - group: {{ group }}
  72. {% endfor %}
  73. user_keydir_{{ name }}:
  74. file.directory:
  75. - name: {{ user.get('home', '/home/{0}'.format(name)) }}/.ssh
  76. - user: {{ name }}
  77. - group: {{ user_group }}
  78. - makedirs: True
  79. - mode: 700
  80. - require:
  81. - user: {{ name }}
  82. - group: {{ user_group }}
  83. {%- for group in user.get('groups', []) %}
  84. - group: {{ group }}
  85. {%- endfor %}
  86. {% if 'ssh_keys' in user %}
  87. {% set key_type = 'id_' + user.get('ssh_key_type', 'rsa') %}
  88. user_{{ name }}_private_key:
  89. file.managed:
  90. - name: {{ user.get('home', '/home/{0}'.format(name)) }}/.ssh/{{ key_type }}
  91. - user: {{ name }}
  92. - group: {{ user_group }}
  93. - mode: 600
  94. - show_diff: False
  95. - contents_pillar: users:{{ name }}:ssh_keys:privkey
  96. - require:
  97. - user: {{ name }}_user
  98. {% for group in user.get('groups', []) %}
  99. - group: {{ name }}_{{ group }}_group
  100. {% endfor %}
  101. user_{{ name }}_public_key:
  102. file.managed:
  103. - name: {{ user.get('home', '/home/{0}'.format(name)) }}/.ssh/{{ key_type }}.pub
  104. - user: {{ name }}
  105. - group: {{ user_group }}
  106. - mode: 644
  107. - show_diff: False
  108. - contents_pillar: users:{{ name }}:ssh_keys:pubkey
  109. - require:
  110. - user: {{ name }}_user
  111. {% for group in user.get('groups', []) %}
  112. - group: {{ name }}_{{ group }}_group
  113. {% endfor %}
  114. {% endif %}
  115. {% if 'ssh_auth' in user %}
  116. {% for auth in user['ssh_auth'] %}
  117. ssh_auth_{{ name }}_{{ loop.index0 }}:
  118. ssh_auth.present:
  119. - user: {{ name }}
  120. - name: {{ auth }}
  121. - require:
  122. - file: {{ name }}_user
  123. - user: {{ name }}_user
  124. {% endfor %}
  125. {% endif %}
  126. {% if 'ssh_auth.absent' in user %}
  127. {% for auth in user['ssh_auth.absent'] %}
  128. ssh_auth_delete_{{ name }}_{{ loop.index0 }}:
  129. ssh_auth.absent:
  130. - user: {{ name }}
  131. - name: {{ auth }}
  132. - require:
  133. - file: {{ name }}_user
  134. - user: {{ name }}_user
  135. {% endfor %}
  136. {% endif %}
  137. {% if 'sudouser' in user and user['sudouser'] %}
  138. {% if not used_sudo %}
  139. {% set used_sudo = True %}
  140. include:
  141. - users.sudo
  142. {% endif %}
  143. sudoer-{{ name }}:
  144. file.managed:
  145. - name: {{ users.sudoers_dir }}/{{ name }}
  146. - user: root
  147. - group: {{ users.root_group }}
  148. - mode: '0440'
  149. {% if 'sudo_rules' in user %}
  150. {% for rule in user['sudo_rules'] %}
  151. "validate {{ name }} sudo rule {{ loop.index0 }} {{ name }} {{ rule }}":
  152. cmd.run:
  153. - name: 'visudo -cf - <<<"$rule" | { read output; if [[ $output != "stdin: parsed OK" ]] ; then echo $output ; fi }'
  154. - stateful: True
  155. - shell: {{ users.visudo_shell }}
  156. - env:
  157. # Specify the rule via an env var to avoid shell quoting issues.
  158. - rule: "{{ name }} {{ rule }}"
  159. - require_in:
  160. - file: {{ users.sudoers_dir }}/{{ name }}
  161. {% endfor %}
  162. {{ users.sudoers_dir }}/{{ name }}:
  163. file.managed:
  164. - contents: |
  165. {%- for rule in user['sudo_rules'] %}
  166. {{ name }} {{ rule }}
  167. {%- endfor %}
  168. - require:
  169. - file: sudoer-defaults
  170. - file: sudoer-{{ name }}
  171. {% endif %}
  172. {% else %}
  173. {{ users.sudoers_dir }}/{{ name }}:
  174. file.absent:
  175. - name: {{ users.sudoers_dir }}/{{ name }}
  176. {% endif %}
  177. {% endfor %}
  178. {% for name, user in pillar.get('users', {}).items() if user.absent is defined and user.absent %}
  179. {{ name }}:
  180. {% if 'purge' in user or 'force' in user %}
  181. user.absent:
  182. {% if 'purge' in user %}
  183. - purge: {{ user['purge'] }}
  184. {% endif %}
  185. {% if 'force' in user %}
  186. - force: {{ user['force'] }}
  187. {% endif %}
  188. {% else %}
  189. user.absent
  190. {% endif -%}
  191. {{ users.sudoers_dir }}/{{ name }}:
  192. file.absent:
  193. - name: {{ users.sudoers_dir }}/{{ name }}
  194. {% endfor %}
  195. {% for user in pillar.get('absent_users', []) %}
  196. {{ user }}:
  197. user.absent
  198. {{ users.sudoers_dir }}/{{ user }}:
  199. file.absent:
  200. - name: {{ users.sudoers_dir }}/{{ user }}
  201. {% endfor %}
  202. {% for group in pillar.get('absent_groups', []) %}
  203. {{ group }}:
  204. group.absent
  205. {% endfor %}