Giter Club home page Giter Club logo

users-formula's Introduction

users-formula

Travis CI Build Status Semantic Release

Formula to configure users via pillar.

Table of Contents

General notes

See the full SaltStack Formulas installation and usage instructions.

If you are interested in writing or contributing to formulas, please pay attention to the Writing Formula Section.

If you want to use this formula, please pay attention to the FORMULA file and/or git tag, which contains the currently released version. This formula is versioned according to Semantic Versioning.

See Formula Versioning Section for more details.

Contributing to this repo

Commit message formatting is significant!!

Please see How to contribute for more details.

Available states

users

Configures a user's home directory, group, the user itself, secondary groups, and associated keys. Also configures sudo access, and absent users.

users.sudo

Ensures the sudo group exists, the sudo package is installed and the sudo file is configured.

users.bashrc

Ensures the bashrc file exists in the users home directory. Sets 'manage_bashrc: True' in pillar per user. Defaults to False.

users.profile

Ensures the profile file exists in the users home directory. Sets 'manage_profile: True' in pillar per user. Defaults to False.

users.vimrc

Ensures the vimrc file exists in the users home directory. Sets 'manage_vimrc: True' in pillar per user. Defaults to False. This depends on the vim-formula being available and pillar users:use_vim_formula: True.

users.user_files

Permits the abitrary management of files. See pillar.example for configuration details.

Overriding default values

In order to separate actual user account definitions from configuration the pillar users-formula was introduced:

users:
  myuser:
    # stuff

users-formula:
  lookup:
    root_group: toor
    shell: '/bin/zsh'

Testing

Linux testing is done with kitchen-salt.

Requirements

  • Ruby
  • Docker
$ gem install bundler
$ bundle install
$ bin/kitchen test [platform]

Where [platform] is the platform name defined in kitchen.yml, e.g. debian-9-2019-2-py3.

bin/kitchen converge

Creates the docker instance and runs the template main state, ready for testing.

bin/kitchen verify

Runs the inspec tests on the actual instance.

bin/kitchen destroy

Removes the docker instance.

bin/kitchen test

Runs all of the stages above in one go: i.e. destroy + converge + verify + destroy.

bin/kitchen login

Gives you SSH access to the instance for manual testing.

users-formula's People

Contributors

0xf10e avatar aboe76 avatar alxwr avatar arthurzenika avatar ashokrajar avatar auser avatar bkmit avatar dafyddj avatar daschatten avatar gravyboat avatar hatifnatt avatar imbarator avatar jasonvoor avatar javierbertoli avatar jochumdev avatar kossmac avatar madflojo avatar myii avatar nmadhok avatar noelmcloughlin avatar pprkut avatar puneetk avatar semantic-release-bot avatar spoage avatar stp-ip avatar tardypad avatar techhat avatar tiger-seo avatar whiteinge avatar wwentland avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

users-formula's Issues

Support for Gentoo

Apparently the Gentoo package names are constructed a bit differently from the other platforms... Here's the output from one of the nodes running state.highstate:

          ID: bash
    Function: pkg.installed
      Result: False
     Comment: Package 'bash' not found (possible matches: app-shells/bash)
     Changes:   
----------
          ID: sudo
    Function: pkg.installed
      Result: False
     Comment: Package 'sudo' not found (possible matches: app-admin/sudo)
     Changes:   
----------
          ID: sudoer-defaults
    Function: file.append
        Name: /etc/sudoers
      Result: False
     Comment: One or more requisite failed
     Changes:   

Patch coming soon...

pubkey and privkey don't obey newline rules

this pillar file will generate an error:

--- 
users: 
  foo: 
    name: foo
    shell: /bin/false
    ssh_keys: 
      privkey: |
        -----BEGIN RSA PRIVATE KEY-----
        foo
        -----END RSA PRIVATE KEY-----
      pubkey: "ssh-rsa somekey [email protected]"

error:

    Data failed to compile:
----------
    Rendering SLS "base:users" failed: Unknown yaml render error; line 52

---
[...]
    - user: foo
    - group: foo
    - mode: 600
    - contents: -----BEGIN RSA PRIVATE KEY-----
foo <======================

The solution is to use contents_pillar (0.17.0+).

bashrc.sls not included

HI,
I'm beginner with salt and I try to configure a user here's my pillar:

users:
  ## Full list of pillar values
  clement:
    fullname: Clement COHEN
    password:########
    enforce_password: False
    # WARNING: If 'empty_password' is set to True, the 'password' statement
    # will be ignored by enabling password-less login for the user.
    empty_password: False
    home: /home/clement
    createhome: true
    roomnumber: "A-1"
    workphone: "#####"
    homephone: "#####"
    manage_vimrc: True
    manage_bashrc: True
    manage_profile: True
   ...

I try to include it in init.sls

{% set used_bashrc = [] %}
{%- if 'manage_bashrc' in user %}
{%- do used_bashrc.append(1) %}
{%- endif %}
{%- endfor %}

{%- if used_bashrc %}
include:
  - users.bashrc
{% endif %}

but i've an error :

    Data failed to compile:
----------
    Rendering SLS "base:users" failed: Conflicting ID 'include'

I also edit the file in users/files/bashrc/bashrc

if I don't include it, It do nothing (the bashrc file is not copied)

remove_groups causes a failure unless set to True

Hi,

I'm seeing a failure regarding the remove_groups setting.

Here's my pillar to start with:

users:
  ed:
    fullname: My Full Name

And here's what Salt replies:

minion:
    Data failed to compile:
----------
    Improperly formatted top file matcher in saltenv OrderedDict([('remove_groups', False)]): False file

The minion generates this yaml, taken directly from the debug logs so including the log message before and after:

Rendered data from file: /var/cache/salt/minion/files/base/users/init.sls:
# vim: sts=2 ts=2 sw=2 et ai









users_ed_user:

  file.directory:
    - name: /home/ed
    - user: ed
    - group: ed
    - mode: 0750
    - require:
      - user: users_ed_user
      - group: ed
  group.present:
    - name: ed

  user.present:
    - name: ed
    - home: /home/ed
    - shell: /bin/bash
    - gid_from_name: True

    - fullname: My Full Name




    - remove_groups: False
    - groups:
      - ed


    - require:
      - group: ed
























users_/etc/sudoers.d/ed:
  file.absent:
    - name: /etc/sudoers.d/ed


#
# if not salt['cmd.has_exec']('git')
# fails even if git is installed
#
# this doesn't work (Salt bug), therefore need to run state.apply twice
#include:
#  - users
#
#git:
#  pkg.installed:
#    - require_in:
#      - sls: users
#











[DEBUG   ] Results of YAML rendering:
OrderedDict([('users_ed_user', OrderedDict([('file.directory', [OrderedDict([('name', '/home/ed')]), OrderedDict([('user', 'ed')]), OrderedDict([('group', 'ed')]), OrderedDict([('mode', 750)]), OrderedDict([('require', [OrderedDict([('user', 'users_ed_user')]), OrderedDict([('group', 'ed')])])])]), ('group.present', [OrderedDict([('name', 'ed')])]), ('user.present', [OrderedDict([('name', 'ed')]), OrderedDict([('home', '/home/ed')]), OrderedDict([('shell', '/bin/bash')]), OrderedDict([('gid_from_name', True)]), OrderedDict([('fullname', 'My Full Name')]), OrderedDict([('remove_groups', False)]), OrderedDict([('groups', ['ed'])]), OrderedDict([('require', [OrderedDict([('group', 'ed')])])])])])), ('users_/etc/sudoers.d/ed', OrderedDict([('file.absent', [OrderedDict([('name', '/etc/sudoers.d/ed')])])]))])

If I comment out the remove_groups line in the User.sls, or set the pillar file to:

users:
  ed:
    fullname: My Full Name
    remove_groups: True

then the issue goes away and the system works fine.

This is my versions:

Salt Version:
           Salt: 2016.11.4

Dependency Versions:
           cffi: Not Installed
       cherrypy: Not Installed
       dateutil: Not Installed
      docker-py: Not Installed
          gitdb: Not Installed
      gitpython: Not Installed
          ioflo: Not Installed
         Jinja2: 2.7.2
        libgit2: 0.20.0
        libnacl: Not Installed
       M2Crypto: Not Installed
           Mako: Not Installed
   msgpack-pure: Not Installed
 msgpack-python: 0.4.6
   mysql-python: Not Installed
      pycparser: Not Installed
       pycrypto: 2.6.1
   pycryptodome: 3.4.3
         pygit2: 0.20.3
         Python: 2.6.9 (unknown, Sep  1 2016, 23:34:36)
   python-gnupg: 0.3.8
         PyYAML: 3.11
          PyZMQ: 14.5.0
           RAET: Not Installed
          smmap: Not Installed
        timelib: Not Installed
        Tornado: 4.2.1
            ZMQ: 4.0.5

System Versions:
           dist:
        machine: x86_64
        release: 4.4.10-22.54.amzn1.x86_64
         system: Linux
        version: Not Installed

And for the minion:

Salt Version:
           Salt: 2016.11.4

Dependency Versions:
           cffi: Not Installed
       cherrypy: Not Installed
       dateutil: Not Installed
      docker-py: Not Installed
          gitdb: Not Installed
      gitpython: Not Installed
          ioflo: Not Installed
         Jinja2: 2.8.1
        libgit2: Not Installed
        libnacl: Not Installed
       M2Crypto: Not Installed
           Mako: Not Installed
   msgpack-pure: Not Installed
 msgpack-python: 0.4.6
   mysql-python: Not Installed
      pycparser: Not Installed
       pycrypto: 2.6.1
   pycryptodome: 3.4.3
         pygit2: Not Installed
         Python: 2.6.9 (unknown, Sep  1 2016, 23:34:36)
   python-gnupg: 0.4.0
         PyYAML: 3.11
          PyZMQ: 14.5.0
           RAET: Not Installed
          smmap: Not Installed
        timelib: Not Installed
        Tornado: 4.2.1
            ZMQ: 4.0.5

System Versions:
           dist:
        machine: x86_64
        release: 4.9.20-11.31.amzn1.x86_64
         system: Linux
        version: Not Installed

Any ideas what's going on?

Add support for ssh_auth_sources.absent

With ssh_auth_sources we can append the multiple ssh public keys. But once the keys are added it's there forever unless manually removed.

Like ssh_auth.absent we need support for ssh_auth_sources.absent too.

why ?
In a cloud environment most of the time it happens that only one user is present and access is controlled by ssh keys and not individual user. So we allow users to upload the public ssh key as a file and read from the file. ssh_auth.absent can't read file so we need support for ssh_auth_sources.absent.

Rendering SLS "base:users" failed: Jinja variable 'dict object' has no attribute 'user'; line 41

I'm getting the following error when running salt-call -l debug state.highstate

local:
    Data failed to compile:
----------
    Rendering SLS "base:users" failed: Jinja variable 'dict object' has no attribute 'user'; line 41

---
[...]
{% for name, user in pillar.get('users', {}).items()
        if user.absent is not defined or not user.absent %}
{%- if user == None -%}
{%- set user = {} -%}
{%- endif -%}
{%- set current = salt.user.info(name) -%}    <======================
{%- set home = user.get('home', current.get('home', "/home/%s" % name)) -%}

{%- if 'prime_group' in user and 'name' in user['prime_group'] %}
{%- set user_group = user.prime_group.name -%}
{%- else -%}
[...]
---

Any suggestions? I'm running a pretty basic Salt configuration:

root@mgt:/srv# tree
.
├── formulas
│   └── users-formula
│       ├── LICENSE
│       ├── pillar.example
│       ├── README.rst
│       └── users
│           ├── bashrc.sls
│           ├── files
│           │   ├── bashrc
│           │   │   └── bashrc
│           │   ├── profile
│           │   │   └── profile
│           │   ├── user
│           │   └── vimrc
│           │       └── vimrc
│           ├── googleauth.sls
│           ├── init.sls
│           ├── map.jinja
│           ├── profile.sls
│           ├── sudo.sls
│           ├── user_files.sls
│           └── vimrc.sls
├── pillar
│   ├── top.sls
│   └── users.sls
└── salt
    └── top.sls

10 directories, 17 files

Manage SFTP users

Hello,

Actually this formula doesn't manage sftp users correctly, since they need specific perrmissions for home (and subfirs) and .ssh directories.
Would it be posible to add this feature ?

Google authentication not available on RedHat os_family

The google-authentication package is not present on CentOS 7, this is the output of yum:

# yum search google-authenticator
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: repo.bigstepcloud.com
 * epel: mirrors.coreix.net
 * extras: repo.bigstepcloud.com
 * updates: mirror.mhd.uk.as44574.net
Warning: No matches found for: google-authenticator
No matches found

A section to map.jinja like the following:

  'RedHat': {
    'sudoers_dir': '/etc/sudoers.d',
    'sudoers_file': '/etc/sudoers',
    'googleauth_dir': '',
    'root_group': 'root',
    'shell': '/bin/bash',
    'visudo_shell': '/bin/bash',
    'bash_package': 'bash',
    'sudo_package': 'sudo',
    'googleauth_package': '',
  },

and something like:

{% if googleauth_package is not none %} {# possibly just {% if googleauth_package %} ? #}
[...]
{% endif %}

to the googleauth.sls could avoid the execution of those sections but there would be no errors reported and it would break some other parts of the formula.

sudo state does not handle usernames containing periods

From the sudoers manpage.

The #includedir directive can be used to create a sudo.d directory that the system package manager can drop sudoers rules into as part of package installation. For example, given:

includedir /etc/sudoers.d

sudo will read each file in /etc/sudoers.d, skipping file names that end in '~' or contain a '.' character to avoid causing problems with package manager or editor temporary/backup files.

As a workaround, this formula should replace periods with underscores where appropriate.

optional_groups

Is it possible to add optional_groups as a setting? With groups setting the user can't be part of any groups not specified in the pillar. If a local admin adds a user to another group, next time highstate is run that local change is removed.

Commit d3e3122624 broken support for non default home dirs

In last commit d3e3122 in file user_files.sls line 10 {%- set home = user.get('home', "/home/%s" % username) -%} user.get always returns null, forcing use of default home /home/. In my case I manage root account with this formula and although I've home set to /root it still tries to use /home/root as a home dir for root user.

Please revert this commit

users.user_files does not work correctly when using gitfs backend

In the users.user_files state there is this code to get a list of directories matching "/users/files/user/":-

{% set userfile_dirs = salt['cp.list_master_dirs'](prefix='users/files/user/') -%}

If no explicit source path is specified in the pillar will try to match 'users/files/user/' ~ username against this list. If it finds no match, it will skip the user completely.

The problem is that when using gitfs, cp.list_master_dirs only lists local directories on the master so there's a good chance your salt://users/files will not be in that list. This means that the state will always do nothing.

The workaround is to specify an explicit source for each user, e.g. salt://users/files/user/joeblogs

Windows error when re-applying users: "if shell and lusr['shell'] != shell"

Salt-Master (salt 2017.7.4 (Nitrogen)) on Debian 9.3.0 netinstall VM.
Salt-Minion (salt 2017.7.4 (Nitrogen)) (just upgraded from 2017.7.2) on Windows 10 (version 1709 build 16289.248) default install on Dell XPS 13

   ----------
          ID: users_firstname.lastname_user
    Function: user.present
        Name: firstname.lastname
      Result: False
     Comment: An exception occurred in this state: Traceback (most recent call last):
                File "c:\salt\bin\lib\site-packages\salt\state.py", line 1843, in call
                  **cdata['kwargs'])
                File "c:\salt\bin\lib\site-packages\salt\loader.py", line 1795, in wrapper
                  return f(*args, **kwargs)
                File "c:\salt\bin\lib\site-packages\salt\states\user.py", line 485, in present
                  win_description)
                File "c:\salt\bin\lib\site-packages\salt\states\user.py", line 126, in _changes
                  if shell and lusr['shell'] != shell:
              KeyError: 'shell'
     Started: 09:48:29.202000
    Duration: 16.0 ms
     Changes:
    ----------
          ID: users_firstname.lastname_user
    Function: file.directory
        Name: /home/firstname.lastname
      Result: False
     Comment: One or more requisite failed: users.users_firstname.lastname_user
     Changes:

On the Minion, I observe in the Salt Minion debug logs that the system is trying to find a registry key that doesn't exist, a sequentially increasing 4-digit number for the Windows SID. My Pillar (Same error if Shell is omitted or defined as /bin/sh):

users:
  ## Minimal required pillar values
# auser:
#   fullname: A User

  ## Full list of pillar values
  firstname.lastname:
    fullname: Firsty Lasterson
    password: plaintestbullshit
    enforce_password: True
    # WARNING: If 'empty_password' is set to True, the 'password' statement
    # will be ignored by enabling password-less login for the user.
    empty_password: False
    hash_password: False
    prime_group:
      name: Administrators
    shell: ComSpec


    user_files:
      enabled: True
      # 'source' allows you to define an arbitrary directory to sync, useful to use for default files.
      # should be a salt fileserver path either with or without 'salt://'
      # if not present, it defaults to 'salt://users/files/user/<username>
      source: users/files/default
      template: jinja
      # You can specify octal mode for files and symlinks that will be copied. Since version 2016.11.0
      # it's possible to use 'keep' for file_mode, to preserve file original mode, thus you can save
      # execution bit for example.
      file_mode: keep
      sym_mode: 640

Resolve `git.config` error where minion does not have Git installed

Was running this formula on a fresh installation without Git installed. Got the following error:

    The minion function caused an exception: Traceback (most recent call last):
      File "/usr/lib/python2.7/dist-packages/salt/minion.py", line 1161, in _thread_return
        return_data = func(*args, **kwargs)
      File "/usr/lib/python2.7/dist-packages/salt/modules/state.py", line 681, in sls
        ret = st_.state.call_high(high_)
      File "/usr/lib/python2.7/dist-packages/salt/state.py", line 2067, in call_high
        ret = dict(list(disabled.items()) + list(self.call_chunks(chunks).items()))
      File "/usr/lib/python2.7/dist-packages/salt/state.py", line 1623, in call_chunks
        running = self.call_chunk(low, running, chunks)
      File "/usr/lib/python2.7/dist-packages/salt/state.py", line 1769, in call_chunk
        self._mod_init(low)
      File "/usr/lib/python2.7/dist-packages/salt/state.py", line 612, in _mod_init
        self.states['{0}.{1}'.format(low['state'], low['fun'])]  # pylint: disable=W0106
      File "/usr/lib/python2.7/dist-packages/salt/utils/lazy.py", line 90, in __getitem__
        raise KeyError(key)
    KeyError: 'git.config'

Installed Git (using git-formula) and then all OK.

So suggest that the following needs to be added somewhere:

include:
  - git

Some issues with this:

  1. This is introducing a dependency on git-formula
  2. Won't be required in all cases, due to {% if 'gitconfig' in user %} -- so perhaps best to put under this conditional

Happy to submit a PR if required.

sudo_rules are generated each time

Hi,

Running Ubuntu Server 14.04 on my test server and I noticed that my sudo_rules for my users are generated every time.

  test:
    fullname: Test Test
    password: xxxx
    sudouser: True
    sudo_rules:
      - ALL=(ALL:ALL) ALL
    shell: /bin/bash
    ssh_auth:
      - ssh-rsa xxxxx

Running salt 2014.1.5

I got the message for every run

----------
          ID: validate test sudo rule 0 test ALL=(ALL:ALL) ALL
    Function: cmd.run
        Name: visudo -cf - <<<"$rule"
      Result: True
     Comment: Command "visudo -cf - <<<"$rule"" run
     Changes:   
              ----------
              pid:
                  16196
              retcode:
                  0
              stderr:

              stdout:
                  stdin: parsed OK
----------

ssh_auth.absent doesn't work if createHome is False

In ssh_auth.absent there is a require for "file: users_{{ name }}_user", but this resource is not created if createHome is False. This can happen (as it's my case) when the home directory is maintained by another tool and has to be ignored by Saltstack.

Is there another way of using ssh_auth.absent without having to use createHome?

prime_group needs gid as a number

When you want to set a different prime group to a user, you have to set the group name and gid. If you don´t set the gid it will fail.
It would be great if you can just tell the name of the group and everything goes smooth.

Rendering fails if 'user_files' used with omitted 'home' attribute

Pillar

users:
  salttestuser:
    fullname: Salt Test User
    password: test123
    user_files:
      enabled: True
      source: salt://users/files/user/salttestuser

Running:
root@saltmaster # salt 'somehost' state.apply users test=True
Result:

somehost:
    - Rendering SLS 'base:users.user_files' failed: Jinja variable 'dict object' has no attribute 'home'

This can be fixed by changing

name: {{ user.home }}

to

name: {{ salt['pillar.get']( username ~ 'user:home', '/home/' ~ username )}}

in 'user_files.sls'. With this change we have default path for home directory if custom path doesn't set in pillar file.
I'm pretty new to Salt so there can be better solution. I will made commit for this.

sudo_rules not working properly?

Hey guys,

Thanks for this great formula, I'm trying to use it for a project and here is my sudo_rules:

    sudouser: True
    sudo_rules:
      - amontalban ALL=(ALL) NOPASSWD: ALL
    sudo_defaults:
      - '!requiretty'

But I get the following error when running this:

----------
          ID: users_sudoer-amontalban
    Function: file.managed
        Name: /etc/sudoers.d/amontalban
      Result: True
     Comment: File /etc/sudoers.d/amontalban exists with proper permissions. No changes made.
     Started: 12:15:25.924476
    Duration: 2.619 ms
     Changes:   
----------
          ID: validate amontalban sudo rule 0 amontalban {'amontalban ALL=(ALL) NOPASSWD': 'ALL'}
    Function: cmd.run
        Name: visudo -cf - <<<"$rule" | { read output; if [[ $output != "stdin: parsed OK" ]] ; then echo $output ; fi }
      Result: False
     Comment: Failed parsing script output! Stdout must be JSON or a line of name=value pairs.
     Started: 12:15:25.929092
    Duration: 21.522 ms
     Changes:   
----------
          ID: validate amontalban sudo Defaults 0 amontalban !requiretty
    Function: cmd.run
        Name: visudo -cf - <<<"$rule" | { read output; if [[ $output != "stdin: parsed OK" ]] ; then echo $output ; fi }
      Result: True
     Comment: 
     Started: 12:15:25.953956
    Duration: 11.935 ms
     Changes:   
----------
          ID: users_/etc/sudoers.d/amontalban
    Function: file.managed
        Name: /etc/sudoers.d/amontalban
      Result: False
     Comment: One or more requisite failed: users.validate amontalban sudo rule 0 amontalban {'amontalban ALL=(ALL) NOPASSWD': 'ALL'}
     Started: 
    Duration: 
     Changes:   
----------

However if I check the syntax it's ok:

root@testing:/etc/sudoers.d# visudo -cf - <<< "amontalban ALL=(ALL) NOPASSWD: ALL"
stdin: parsed OK

So probably I'm not doing the right thing with the sudo_rules syntax or . Can anyone point me to the right direction?

Thanks!

Unable to specify port for ssh_known_hosts

This just started happening after upgrading to 2015.8:
I have the following clause in my users pillar:

    ssh_known_hosts:
      slsapp.com:
        port: 1234
        fingerprint: xx:xx:xx
        enc: ssh-dss

This results in:

          ID: users_ssh_known_hosts_username_0
    Function: ssh_known_hosts.present
        Name: slsapp.com
      Result: False
     Comment: argument port can not be used in conjunction with argument hash_known_hosts

hash_known_hosts is not present, so I'm not sure what is going on here. I tried to explicitly set hash_known_hosts to False in case it was the default, but it didn't help.

Add sudo_rules for a user without making them a sudoer

Currently, it does not appear to be possible to add specific sudo rules for a user without making them a full sudoer.

I ran across this use case while configuring my Git server, where I want the git user to be able to run a specific salt-call command without being able to do anything else. I followed through the logic in users/init.sls, and found that the sudo_rules and sudo_defaults state directives are only formatted if the user is also a sudoer.

For the time being, I am using this approach, but it is somewhat less secure than I would like.

gitconfig not run though git get installed

Having git installed (and modules refreshed) used to work to get gitconfig installed in a single run, but since #169 , the gitconfig is not even tryed anymore.

(dummy example, not tested as it)

# git/install_reload
git:
  pkg.installed: []

reload_modules:
  module.run:
  - name: saltutil.refresh_modules
include:
  - git.install_reload
  - users

The sls checks the presence of git before doing anything. If pkg is installed by prior states, it would not be checked/updated...

Ideas:

  • Check git presence with if/unless clause, having it done runtime, but doesn't check if module is reloaded
  • Check at runtime, forcing a refresh_modules if it was not present at sls parsing
  • Simple have a pillar to force bypass the check.

Any suggestions?

Provide a state to require new password on first login

We have users we are creating sometimes and for some reasons we don't want to store their hashed passwords into Salt, and we don't rely (yet) on central authentication.

In this case, what we often do is to require them to change their password on the very first login, and since to change your password you first have to know the previous one, we also set up an empty password by default (in this case, passwd doesn't ask for the old password). Since we rely on SSH key authentication for the initial authentication, this trade-off is acceptable, I guess.

Currently, our state looks like this:

{% if name != 'root' and 'password' not in user %}
{{ name }}_user_reset_password:
  cmd.run:
   - name: usermod -p "" {{ name }} && chage -d 0 {{ name }}
   - onlyif: grep --quiet "^{{ name }}:!:" /etc/shadow
   - require:
     - user: {{ name }}
{% endif %}

This does the following:

  • ensure the password is really empty and change the expiration date to require a password change on login. The order of these operations are important, if you do it on the reverse order, the expiration date is set somewhere in the future due to the usermod call.
  • the state is only run if there's no password set (at all) for this user, otherwise the state will keep resetting the password. It's a complicated way to say to run the state only once just after the user has been initially created.

I think this state would fit into this formula, and I'll be glad to offer a pull request to add this. Any comments are welcome (if that fits, and how to provide a pillar configuration to configure this).

Directives for sudo_rules and sudo_defaults appear commented out

Hi all, I'm a bit confused. I'm trying to apply sudo_rules and sudo_defaults, but noticed that the state declarations appear to be commented out in users/init.sls. These comments were added in 819d73a, and their functionality doesn't appear to be replicated anywhere else. Can someone explain why this was?

better ssh_auth handling

instead of keeping a list of pubkeys in a yaml file, it would be great if this formula could take advantage of file.managed and grab keys from elsewhere on the local FS or remotely.

suggestion: document pillar logic

it would be helpful to have some examples of logic in the pillar file.

i.e. adding a user to only one host, enabling sudo for a user on only some hosts, etc.

lacks documentation

Trying to guess the usage of this formula based on the pillar example is extremely frustrating, and the "official" doc is a dev doc for making new formulas, with barely any relevant information on how to use existing formulas.

While most of you probably already figured out how to use formulas, new users probably have a terrible time trying to use formulas.

"users_ssh_keys_files_{{ name }}_{{ key_name }}_pub" state cannot handle multi-line public keys

If a public key is defined in a YAML dict as the following:

users:
  example:
    ssh_keys_pillar:
      example: users_example_ssh_keys

users_example_ssh_keys:
  example:
    pubkey: |
      ---- BEGIN SSH2 PUBLIC KEY ----
      Vovwv3IxmU/CIwUPXFx352UtdlpVPo2WADlkFzVxgJFegmOGLP0svKejmFLdoz0nKzSJ6jy+I85U
      2gmSu4tvPZ0WSy4Ctgd6OOfBBAAl2rcvsMQlsjmQpI5Ewl/LjI+KL/pEAWaC++RSgohFMcPqiLci
      bvjMusWHu2kpwNw8jN1NaT6CT0eCTCVeScaQDSmeEAsW7l32mgKucHL/GmklFZA6BD4aodVriyYp
      ybqwFpJY0KN8tzkdgIhKkwsKXY/ULA7J9ZsmyLWAnU1GarsyB29wLeY2YE0ZhxHCf3OOX6RyO+wA
      /vKp756HbiU6pd6DOoHPKgyS5DAC2x5kLyvEUUrQ/eGST4YHNqRJNmmAfpNtnoMc8HcKPmBgLkq+
      +qSxRe8ofYLN0AmtqxjTF9ObqAcWjCL7Yk0vyBMEl6v+MQ62yNzvb2KESk1AmedDLO+lYUTC/qX1
      fg5mq9gWLI2PJImrSVRSSNYGLgCN+k0xtBBYL0ZZ+1ManfWSZzuREaF/YgbJXv8eTw52fTSwuiDB
      ---- END SSH2 PUBLIC KEY ----
    privkey: |
      (etc.)

Then when run on a minion, the users SLS will generate the following error at render-time:

local:
    Data failed to compile:
----------
    Rendering SLS 'users' failed: could not found expected ':'; line 198

---
[...]
  file.managed:
    - name: /home/example/.ssh/example.pub
    - contents: |
        ---- BEGIN SSH2 PUBLIC KEY ----
Vovwv3IxmU/CIwUPXFx352UtdlpVPo2WADlkFzVxgJFegmOGLP0svKejmFLdoz0nKzSJ6jy+I85U
2gmSu4tvPZ0WSy4Ctgd6OOfBBAAl2rcvsMQlsjmQpI5Ewl/LjI+KL/pEAWaC++RSgohFMcPqiLci
<======================
bvjMusWHu2kpwNw8jN1NaT6CT0eCTCVeScaQDSmeEAsW7l32mgKucHL/GmklFZA6BD4aodVriyYp
ybqwFpJY0KN8tzkdgIhKkwsKXY/ULA7J9ZsmyLWAnU1GarsyB29wLeY2YE0ZhxHCf3OOX6RyO+wA
/vKp756HbiU6pd6DOoHPKgyS5DAC2x5kLyvEUUrQ/eGST4YHNqRJNmmAfpNtnoMc8HcKPmBgLkq+
+qSxRe8ofYLN0AmtqxjTF9ObqAcWjCL7Yk0vyBMEl6v+MQ62yNzvb2KESk1AmedDLO+lYUTC/qX1
fg5mq9gWLI2PJImrSVRSSNYGLgCN+k0xtBBYL0ZZ+1ManfWSZzuREaF/YgbJXv8eTw52fTSwuiDB
[...]

---

`enforce_password: False` is ignored

UPDATE: I renamed the problem report. See discussion below. The root cause is a render error in the formula.

users-formula doesn't offer a way to set enforce_password to False, so to set an initial password for accounts managed via the formula, one must run a separate user.present state. I would much prefer to do this via the formula.

Empty passwords

Is there a way to set empty passwords for users? I couldn't see anything like that in the pillar.

sudo forcing to use bash

As bash is not included on all the systems (freebsd for example) i suggest to change this part in init.sls:

{% if 'sudo_rules' in user %}
{% for rule in user['sudo_rules'] %}
"validate {{ name }} sudo rule {{ loop.index0 }} {{ name }} {{ rule }}":
  cmd.run:
    - name: 'result=`echo "$rule" | visudo -cf -`; if [ "$result" != "stdin: parsed OK" ]; then echo $result; fi'
    - stateful: True
    - shell: /bin/sh
    - env:
      # Specify the rule via an env var to avoid shell quoting issues.
      - rule: "{{ name }} {{ rule }}"
    - require_in:
      - file: {{ users.sudoers_dir }}{{ name }}
{% endfor %}

And to remove the bash as required in sudo.sls

# Ensure availability of bash
bash-package:
  pkg.installed:
    - name: {{ users.bash_package }}

Warning from users_sudoer-{{ name }} with newer Salt versions

On Salt 2016.3.2 (from the Saltstack PPA, specifically 2016.3.2+ds-1), Ubuntu 14.04, this formula started emitting a new warning on a highstate run:

[WARNING ] State for file: /etc/sudoers.d/(USERNAME) - Neither 'source' nor 'contents' nor 'contents_pillar' nor 'contents_grains' was defined, yet 'replace' was set to 'True'. As there is no source to replace the file with, 'replace' has been set to 'False' to avoid reading the file unnecessarily.

Explicitly setting replace: false makes the warning go away but also suppresses adding the "File managed by Salt (users-formula)" disclaimer.

Private SSH key via Salt fileserver

Correct me if I'm wrong, but the users-formula seems to support putting a user's private SSH key in salt://keys/{{ user['privkey'] }}. Wouldn't that expose the private key to any minion through the Salt fileserver, thus creating a big security problem?

incorrect reporting of sudo rules checks when running in a test mode

When running state.highstate test=true users-formula reports changes when no changes are required.

salt-ssh testhost state.highstate test=true
testhost:
  Name: visudo -cf - <<<"$rule" | { read output; if [[ $output != "stdin: parsed OK" ]] ; then echo $output ; fi } - Function: cmd.run - Result: Differs

This behavior is a bit annoying when checking multiple hosts in a test=true mode.
If I understand rightly it's not a bug of salt, because it executes cmd.run while testing sudo rule.

Remove trailing slash from sudoers_dir to avoid no-op diff

Currently this is what happens the first time the state is run:

----------
          ID: sudoer-defaults
    Function: file.append
        Name: /etc/sudoers
      Result: None
     Comment: File /etc/sudoers is set to be updated
     Started: 13:23:28.848581
    Duration: 6.53 ms
     Changes:
              ----------
              diff:
                  ---
                  +++
                  @@ -28,3 +28,4 @@
                   # See sudoers(5) for more information on "#include" directives:

                   #includedir /etc/sudoers.d
                  +#includedir /etc/sudoers.d/

vimrc state does not work

The vimrc state fails.

vimrc.sls

include:
  - users
  - vim

ERROR

    Specified SLS vim in saltenv base is not available on the salt master or through a configured fileserver

Posibility to include * files per user

Something along the lines of

files:
this/be/a/path:
- mode: 644
- source: salt://path/to/source

And it would include it as { home.dir } / { file.path }

Changing the sudo configuration for a user only appends the changes

When changing the sudo configuration for a user the previous configuration will remain in the file /etc/sudoers.d/username and the new configuration will only be appended.
The formula should instead be able to state the contents of the file. As it is the only way to, for example, reduce a user privileges is to completely delete the user and then re-create it with less privileges.

Default shell in FreeBSD

I would leave the default shell of freebsd at /bin/csh
Many users prefer to leave /usr in a partition itself.
If you start the machine in rescue mode and /usr is not mounted for some reason your user will not be able to log in to the machine.
If you like me use scrambled root passwords or no password login at all for the root user you will be unable to log in to the machine (brcause you can not suid yourself).

Users/Groups already exist Errors/state failures

Is there any pillar to workaround ERRORS/failed states if users already exist? I want to ensure oracle user, and oracle/dba groups, are present in any database but salt only checks locally

(see also saltstack/salt#45345 and saltstack/salt#45142)

  oracle:
    empty_password: True
    home: /home/oracle
    uid: 501
    shell: /bin/bash
    prime_group:
      name: oracle
   {% if not salt['cmd.run']('getent group oracle', output_loglevel='quiet') %}
      gid: 501
   {% endif %}
    optional_groups:
      - dba
      - oracle

Thanks
Noel

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.