deric / puppet-accounts

Simple hierachical management of Linux user accounts, groups and SSH keys
https://forge.puppetlabs.com/deric/accounts
Apache License 2.0
34 stars 33 forks source link
account-management accounts groups hiera passwd puppet users

Puppet Accounts Management

Puppet
Forge Build Status Puppet Forge
Downloads

This is puppet module for managing user accounts, groups and setting ssh keys.

Version compatibility:

deric-accounts Puppet 3.x Puppet 4.x Puppet 5.x Puppet 6.x
1.5.x :heavy_check_mark: :heavy_check_mark: :question: :x:
2.0.x :question: :heavy_check_mark: :heavy_check_mark: :x:
2.1.x :question: :question: :heavy_check_mark: :heavy_check_mark:

Origin: https://github.com/deric/puppet-accounts

Basic usage:

class {'::accounts':}

or with pure YAML declaration make sure to use the hiera_include function e.g. in site.pp (see Hiera docs for details):

lookup('classes', {merge => unique}).include

and all other definition can be in YAML hierarchy:

classes:
  - '::accounts'
accounts::users:
  myuser:
    groups: ['users']

Hiera allows flexible account management, if you want to have a group defined on all nodes, just put in global hiera config, e.g. common.yml:

accounts::user_defaults:
  shell: '/bin/bash'
  # will delete all authorized keys that are not in Puppet
  purge_ssh_keys: true
accounts::groups:
  www-data:
    gid: 33
    # not necessarily complete list of memebers, you can assign users to the same group on
    # user's level using `groups: ['www-data']`
    members: ['john']

and user accounts:

accounts::users:
  john:
    comment: "John Doe"
    groups: ["sudo", "users"]
    shell: "/bin/bash"
    pwhash: "$6$GDH43O5m$FaJsdjUta1wXcITgKekNGUIfrqxYogW"
    ssh_keys:
      'john@doe': # an unique indentifier of a key
        type: "ssh-rsa"
        key: "a valid public ssh key string"
  alice:
    comment: "Alice"

For more examples see configuration used for tests.

Custom home

When no home is specified directory will be created in /home/{username}.

  alice:
    comment: 'Alice'
    home: '/var/alice'

Group management

By default each user has a group with the same name. You can change this with manage_group parameter:

accounts::users:
 john:
   manage_group: false
   groups:
     - 'users'
     - 'www-data'

Optionally you can assign user to other groups by supplying a groups array.

Primary group

Account's primary group can be configured using primary_group parameter:

accounts::users:
 john:
   # will create primary group `doe` instead of default `john` group
   primary_group: 'doe'
   manage_group: true
   groups:
     - 'sudo'

it can be defined numerically or as a group name. Setting directly gid parametr would have the same effect. Parameter manage_group is not considered when you set gid.

Account removal

Removing account could be done by setting ensure parameter to absent:

accounts::users:
 john:
   ensure: 'absent'
   managehome: true

If managehome is set to true (default), also home directory will be removed!

Root account

root home is set to /root unless defined otherwise (using home parameter). You can supply multiple keys for one account.

accounts::users:
  root:
    ssh_keys:
      'mykey1':
        type: 'ssh-rsa'
        key: 'AAAA....'
      'otherkey':
        type: 'ssh-dsa'
        key: 'AAAAB...'

Additional SSH key options

SSH allows providing many options regarding authorized keys, see SSH documentation for complete specification.

Options should be passed as an array:

accounts::users:
  foo:
    ssh_keys:
      'mykey1':
        type: 'ssh-rsa'
        key: 'AAAA....'
        options:
          - 'permitopen="10.4.3.29:3306"'
          - 'permitopen="10.4.3.30:5432"'
          - 'no-port-forwarding'
          - 'no-X11-forwarding'
          - 'no-agent-forwarding'
          - 'from="serverA,serverB"'
          - 'command="/path/to/script.sh arg1 $SSH_ORIGINAL_COMMAND"'

Password Management

You can either provide an already hashed password or you can let the module take care of hashing.

Providing hashed passwords from Hiera is secure by default. Please use something like hiera-eyaml or hiera-gpg for cleartext passwords within Puppet.

Example with pre-hashed password:

accounts::users:
  john:
    pwhash: "$6$GDH43O5m$FaJsdjUta1wXcITgKekNGUIfrqxYogW"

Example with cleartext password, using hiera-eyaml:

accounts::users:
  john:
    password: >
      ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQAw
      ...
      1yv7gBCuc3T2xV9gPYe+DrALDYB+]
   ensure: present

The password hashing salt is generated with fqdn_rand_string from stdlib the first time the user is created. After that, the salt is read by a custom fact and reused, even on password changes (which is ok, it's just a salt...). You may specify an explicit salt if needed (see variable doc below).

User

Example:

accounts::users:
 john:
   authorized_keys_file: '/home/.ssh/auth_file'
   managehome: true
   purge_ssh_keys: false
   pwhash: ''
   hushlogin: true

umask

Default permissions for creating new files are managed via ~/.bash_profile and ~/.bashrc.

accounts::users:
 john:
   manageumask: true
   umask: '022'

By default umask is not managed. Note that you can configure global umask for all users via accounts::config (see below).

Global settings

You can provide global defaults for all users:

accounts::user_defaults:
  shell: '/bin/dash'
  groups: ['users']
  hushlogin: true

Note that configuration from Hiera gets merged to with Puppet code.

System-wide configuration

Global settings affects also user accounts created outside of this module.

accounts::config:
  first_uid: 1000
  last_uid: 99999
  first_gid: 1000
  last_gid: 99999
  umask: '077'

Populate home folder

Allows fetching user's directory content from some storage:

accounts::users:
 john:
   populate_home: true
   home_directory_contents: 'puppet:///modules/accounts'

which default to puppet:///modules/accounts/{username}.

Testing

Which accounts will be installed on specific machine can be checked from command line:

$ hiera -y my_node.yml accounts::users --hash

where my_node.yml is a file which you get from facter running at some node:

$ facter -y > my_node.yml

Without Hiera

Using Hiera is optional (though prefered option), you can configure accounts directly from Puppet code:

class {'accounts':
  users => { 'john' => { 'comment' => 'John Doe' }}
}

When defining adding a user to multiple groups, we have to ensure, that all the groups exists first:

  class {'accounts':
    groups => {
      'users' => {
        'gid' => 100,
      },
      'puppet' => {
        'gid' => 111,
      }
    },
    users => { 'john' => {
      'shell'   => '/bin/bash',
      'groups'  => ['users', 'puppet'],
      'ssh_keys' => { 'johns_key' => {'type' => 'ssh-rsa', 'key' => 'public_ssh_key_xxx' }}
    }}
  }

Puppet compatibility

This modules heavily relies on Hiera functionality, thus it's recommended to use at least Puppet 3. Puppet 2.7 might work with hiera-puppet gem, but we don't test this automatically, see docs for more details.

Hiera configuration

Puppet 4.9 comes with Hiera 5 support. For earlier versions see Hiera 3 section.

Hiera 5

When migrating from Hiera 3 see the official guide:

hiera.yaml has slightly different syntax:

---
version: 5
defaults:  # Used for any hierarchy level that omits these keys.
  datadir: hieradata         # This path is relative to hiera.yaml's directory.
  data_hash: yaml_data  # Use the built-in YAML backend.

hierarchy:
  - name: "Common"
    path: "common.yaml"

Supported merge strategies are:

Using lookup_options you can define rules to use strategy that suits your needs.

---
lookup_options:
  "^accounts::(.*)":
    merge:
      strategy: deep
      # sort_merged_arrays: false
      # merge_hash_arrays: false

Hiera 3

For more complex hierarchies (defined in multiple files) deep_merge gem is needed, see Hiera docs.

gem install deep_merge

and update merge_behavior in your hiera.yaml, e.g.:

---
:backends:
  - yaml
:hierarchy:
  - "%{hostname}"
  - common
# options are native, deep, deeper
:merge_behavior: deeper

With Puppet librarian add one line to Puppetfile:

stable release:

mod 'deric-accounts'

development version (master branch from github):

mod 'deric-accounts', :git => 'https://github.com/deric/puppet-accounts.git'

and run

$ librarian-puppet install

Supported versions

Tests

Run tests with:

$ bundle install
$ bundle exec rake spec

Acceptance testing

Fastest way is to run tests on prepared Docker images:

BEAKER_set=debian9-5.5 bundle exec rake acceptance
BEAKER_set=centos7-3.8 bundle exec rake acceptance

For examining system state set Beaker's ENV variable BEAKER_destroy=no:

BEAKER_destroy=no BEAKER_set=debian9-6.3 bundle exec rake acceptance

and after finishing tests connect to container:

docker exec -it adoring_shirley bash

When host machine is NOT provisioned (puppet installed, etc.):

PUPPET_install=yes BEAKER_set=debian-8 bundle exec rake acceptance

Run on specific OS (see spec/acceptance/nodesets), to see available sets:

rake beaker:sets

License

Apache 2.0