├── README.mkd ├── files └── home │ └── default │ ├── .bash_aliases │ ├── .bash_logout │ ├── .bashrc │ └── .profile ├── lib ├── facter │ ├── etcgroup.rb │ └── etcpasswd.rb └── puppet │ └── parser │ └── functions │ ├── array_index.rb │ ├── array_length.rb │ └── array_slice.rb ├── manifests ├── classes │ └── users.pp ├── definitions │ ├── gidsanity.pp │ ├── lookup.pp │ ├── lookupkey.pp │ ├── masskeys.pp │ ├── massuseraccount.pp │ ├── uidsanity.pp │ ├── useraccount.pp │ └── userkey.pp └── init.pp └── scripts └── findDirs.sh /README.mkd: -------------------------------------------------------------------------------- 1 | # users puppet module # 2 | 3 | Manages user configuration. 4 | 5 | Supported corrective actions under: Debian. 6 | 7 | ## Classes ## 8 | 9 | * users 10 | 11 | ### users ### 12 | 13 | Realize all useraccount, massuseraccount and lookup defines tagged with 14 | 'administrators'. Also, realize User, Group, File and Exec likewise 15 | tagged, to handle exceptional cases. 16 | 17 | ## Definitions ## 18 | 19 | * users::account 20 | * users::gidsanity 21 | * users::lookup 22 | * users::lookupkey 23 | * users::masskeys 24 | * users::massuseraccount 25 | * users::uidsanity 26 | 27 | ### users::account ### 28 | 29 | Create a user account with a primary group of the same name. If uid is provided and the 30 | client supports the custom facts provided with this module, do some sanity checking 31 | beforehand, moving users and groups with conflicting guids to the same guids + 10000. 32 | 33 | Note that just like user name and primary group name are kept the same, uid and gid 34 | are kept equal. 35 | 36 | Also copy a tree of files in one of two ways: 37 | 38 | 1. If there's a "managed" directory from one of the options below, use it and control 39 | file content. The file paths checked for are absolute, so it may need changing if the 40 | default file server path is different. Also, it uses a script at 41 | `/etc/puppet/modules/users/scripts` to check for these files, which may also need changing 42 | depending on the module path and module name. 43 | 44 | * `/etc/puppet/files/users/home/managed/host/${username}.$fqdn` 45 | * `/etc/puppet/files/users/home/managed/host/${username}.$hostname` 46 | * `/etc/puppet/files/users/home/managed/domain/${username}.$domain` 47 | * `/etc/puppet/files/users/home/managed/env/${username}.$environment` 48 | * `/etc/puppet/files/users/home/managed/user/${username}` 49 | * `/etc/puppet/files/users/home/managed/skel` 50 | 51 | 2. Otherwise, use one of the directories below as a default (modified files do 52 | not get replaced). 53 | 54 | * `puppet:///files/users/home/default/host/${username}.$fqdn` 55 | * `puppet:///files/users/home/default/host/${username}.$hostname` 56 | * `puppet:///files/users/home/default/domain/${username}.$domain` 57 | * `puppet:///files/users/home/default/env/${username}.$environment` 58 | * `puppet:///files/users/home/default/user/${username}` 59 | * `puppet:///files/users/home/default/skel` 60 | * `puppet:///files/users/home/default/skel` 61 | * `puppet:///users/home/default/skel` 62 | 63 | In neither case will other files be purged. Also, there is no mode control, though all 64 | files will be created with user and group onwership. 65 | 66 | Also ensures that the .ssh directory and .bash_history will be kept with appropriate 67 | permissions. 68 | 69 | Example: 70 | 71 | @users::useraccount { "bob": 72 | ensure => present, 73 | fullname => "Uncle Bob", 74 | uid => 1000, 75 | groups => [ "wheel" ], # Extra groups, defaults to none 76 | shell => '/bin/bash', # default value 77 | password => 'hash', 78 | } 79 | 80 | ### users::gidsanity ### 81 | 82 | Checks that no other group is using this gid, and, if it is, moves it 83 | up 10000. 84 | 85 | Also, if the group exists but doesn't presently have this 86 | gid, pre-emptively change group owner ship of all files in the home 87 | directory with the current gid, so that they'll be correct after the 88 | group id was corrected (elsewhere). 89 | 90 | ### users::lookup ### 91 | 92 | Add a user through extdata lookup. The user is added with the extra 93 | groups provided, but name, uid and password come from the csv file. 94 | 95 | Example: 96 | 97 | @users::lookup { 'username': 98 | ensure => present, # default value 99 | groups => [], # default value 100 | } 101 | 102 | CSV file: 103 | 104 | username_account,uid,Full Name,hashed password 105 | 106 | ### users::lookupkey ### 107 | 108 | Add a key to a user's authorized_keys file through extdata lookup. It 109 | supports arbitrary number of options, and //requires// a comment field, 110 | which will be prepended with the username to avoid problems with it 111 | being used as primary key on ssh_authorized_keys when multiple users 112 | are using the same key. 113 | 114 | Options containing double quotes should be enclosed in double quotes 115 | themselves, and its own double quotes doubled (see example). 116 | 117 | The CSV format was designed to be almost equal to authorized_keys itself, 118 | with just the need to replace spaces separating options, key type, key 119 | and comment with commas, plus the above mentioned double quote handling. 120 | 121 | Example: 122 | 123 | @users::lookupkey { 'username': 124 | ensure => present, # default value 125 | } 126 | 127 | CSV file: 128 | 129 | username_sshkey,"from=""a.b.c.d""",no-port-forwarding,ssh-dss,key,comment 130 | 131 | 132 | 133 | ### users::userkey### 134 | 135 | Add a key to user's authorized keys file through direct passing. 136 | Default comment on key is "default-key" and default type is "ssh-rsa". 137 | 138 | Example: 139 | 140 | @users::userkey { 'username': 141 | ensure => present, 142 | key => "key", 143 | } 144 | 145 | 146 | 147 | ### users::masskeys ### 148 | 149 | Add keys to user's authorized_keys files through extdata lookup. See 150 | users::lookupkey for more details. 151 | 152 | Example: 153 | 154 | @users::masskeys { 'group': 155 | ensure => present, # default value 156 | } 157 | 158 | CSV file: 159 | 160 | group_sshkeys,username 161 | username_sshkey,"from=""a.b.c.d""",no-port-forwarding,ssh-dss,key,comment 162 | 163 | 164 | ### users::massuseraccount ### 165 | 166 | Adds users through extdata lookup. The users are added with the extra 167 | groups provided, but name, uid and password come from the csv files, 168 | as well as the list of users. 169 | 170 | Example: 171 | 172 | @users::massuseraccount { 'group': 173 | ensure => present, # default value 174 | groups => [], # default value 175 | } 176 | 177 | CSV file: 178 | 179 | group_accounts,username 180 | username_account,uid,Full Name,hashed password 181 | 182 | ### users::uidsanity ### 183 | 184 | Checks that no other user is using this uid, and, if it is, moves it 185 | up 10000. 186 | 187 | -------------------------------------------------------------------------------- /files/home/default/.bash_aliases: -------------------------------------------------------------------------------- 1 | alias usersearch='ldapsearch -x -h pdc.ebc -b ou=Usuarios,dc=radiobras,dc=local -LLL -s children' 2 | alias ccat='highlight -A --force' 3 | -------------------------------------------------------------------------------- /files/home/default/.bash_logout: -------------------------------------------------------------------------------- 1 | # ~/.bash_logout: executed by bash(1) when login shell exits. 2 | 3 | # when leaving the console clear the screen to increase privacy 4 | 5 | if [ "$SHLVL" = 1 ]; then 6 | [ -x /usr/bin/clear_console ] && /usr/bin/clear_console -q 7 | fi 8 | -------------------------------------------------------------------------------- /files/home/default/.bashrc: -------------------------------------------------------------------------------- 1 | # ~/.bashrc: executed by bash(1) for non-login shells. 2 | # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) 3 | # for examples 4 | 5 | # If not running interactively, don't do anything 6 | [ -z "$PS1" ] && return 7 | 8 | # don't put duplicate lines in the history. See bash(1) for more options 9 | # don't overwrite GNU Midnight Commander's setting of `ignorespace'. 10 | export HISTCONTROL=$HISTCONTROL${HISTCONTROL+,}ignoredups 11 | # ... or force ignoredups and ignorespace 12 | export HISTCONTROL=ignoreboth 13 | 14 | # append to the history file, don't overwrite it 15 | shopt -s histappend 16 | 17 | # for setting history length see HISTSIZE and HISTFILESIZE in bash(1) 18 | 19 | # check the window size after each command and, if necessary, 20 | # update the values of LINES and COLUMNS. 21 | shopt -s checkwinsize 22 | 23 | # make less more friendly for non-text input files, see lesspipe(1) 24 | [ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" 25 | 26 | # set variable identifying the chroot you work in (used in the prompt below) 27 | if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then 28 | debian_chroot=$(cat /etc/debian_chroot) 29 | fi 30 | 31 | # set a fancy prompt (non-color, unless we know we "want" color) 32 | case "$TERM" in 33 | xterm-color) color_prompt=yes;; 34 | esac 35 | 36 | # uncomment for a colored prompt, if the terminal has the capability; turned 37 | # off by default to not distract the user: the focus in a terminal window 38 | # should be on the output of commands, not on the prompt 39 | force_color_prompt=yes 40 | 41 | if [ -n "$force_color_prompt" ]; then 42 | if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then 43 | # We have color support; assume it's compliant with Ecma-48 44 | # (ISO/IEC-6429). (Lack of such support is extremely rare, and such 45 | # a case would tend to support setf rather than setaf.) 46 | color_prompt=yes 47 | else 48 | color_prompt= 49 | fi 50 | fi 51 | 52 | # If there's git available, get the branch on the prompt 53 | if type -t __git_ps1 >/dev/null; then 54 | GITPS1='$(__git_ps1)' 55 | fi 56 | 57 | if [ "$color_prompt" = yes ]; then 58 | PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[0;31m\]'"$GITPS1"'\[\033[00m\]\$ ' 59 | else 60 | PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w'"$GITPS1"'\$ ' 61 | fi 62 | unset color_prompt force_color_prompt 63 | 64 | # If this is an xterm set the title to user@host:dir 65 | case "$TERM" in 66 | xterm*|rxvt*) 67 | PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" 68 | ;; 69 | *) 70 | ;; 71 | esac 72 | 73 | # Alias definitions. 74 | # You may want to put all your additions into a separate file like 75 | # ~/.bash_aliases, instead of adding them here directly. 76 | # See /usr/share/doc/bash-doc/examples in the bash-doc package. 77 | 78 | if [ -f ~/.bash_aliases ]; then 79 | . ~/.bash_aliases 80 | fi 81 | 82 | # enable color support of ls and also add handy aliases 83 | if [ -x /usr/bin/dircolors ]; then 84 | eval "`dircolors -b`" 85 | # You may uncomment the following lines if you want `ls' to be colorized: 86 | export LS_OPTIONS='--color=auto' 87 | 88 | alias grep='grep --color=auto' 89 | alias fgrep='fgrep --color=auto' 90 | alias egrep='egrep --color=auto' 91 | fi 92 | 93 | alias ls='ls $LS_OPTIONS' 94 | #alias dir='dir --color=auto' 95 | #alias vdir='vdir --color=auto' 96 | 97 | # some more ls aliases 98 | alias ll='ls $LS_OPTIONS -l' 99 | alias la='ls $LS_OPTIONS -lA' 100 | alias l='ls $LS_OPTIONS -CF' 101 | 102 | # enable programmable completion features (you don't need to enable 103 | # this, if it's already enabled in /etc/bash.bashrc and /etc/profile 104 | # sources /etc/bash.bashrc). 105 | if [ -f /etc/bash_completion ]; then 106 | . /etc/bash_completion 107 | fi 108 | 109 | # Some more alias to avoid making mistakes: 110 | # alias rm='rm -i' 111 | # alias cp='cp -i' 112 | # alias mv='mv -i' 113 | 114 | EDITOR=/usr/bin/vim; export EDITOR 115 | LESS=-eiMqFWXR; export LESS 116 | PAGER=/usr/bin/less; export PAGER 117 | 118 | -------------------------------------------------------------------------------- /files/home/default/.profile: -------------------------------------------------------------------------------- 1 | # ~/.profile: executed by the command interpreter for login shells. 2 | # This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login 3 | # exists. 4 | # see /usr/share/doc/bash/examples/startup-files for examples. 5 | # the files are located in the bash-doc package. 6 | 7 | # the default umask is set in /etc/profile; for setting the umask 8 | # for ssh logins, install and configure the libpam-umask package. 9 | #umask 022 10 | 11 | # if running bash 12 | if [ -n "$BASH_VERSION" ]; then 13 | # include .bashrc if it exists 14 | if [ -f "$HOME/.bashrc" ]; then 15 | . "$HOME/.bashrc" 16 | fi 17 | fi 18 | 19 | # set PATH so it includes user's private bin if it exists 20 | if [ -d "$HOME/bin" ] ; then 21 | PATH="$HOME/bin:$PATH" 22 | fi 23 | -------------------------------------------------------------------------------- /lib/facter/etcgroup.rb: -------------------------------------------------------------------------------- 1 | # etcgroup.rb 2 | 3 | Facter.add("etcgroup") do 4 | setcode do 5 | File.read('/etc/group') 6 | end 7 | end 8 | 9 | -------------------------------------------------------------------------------- /lib/facter/etcpasswd.rb: -------------------------------------------------------------------------------- 1 | # etcpasswd.rb 2 | 3 | Facter.add("etcpasswd") do 4 | setcode do 5 | File.read('/etc/passwd') 6 | end 7 | end 8 | 9 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/array_index.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | newfunction(:array_index, :type => :rvalue) do |args| 3 | array = args[0] 4 | index = args[1].to_i 5 | array[index] 6 | end 7 | end 8 | 9 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/array_length.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | newfunction(:array_length, :type => :rvalue) do |args| 3 | array = args[0] 4 | array.length 5 | end 6 | end 7 | 8 | -------------------------------------------------------------------------------- /lib/puppet/parser/functions/array_slice.rb: -------------------------------------------------------------------------------- 1 | module Puppet::Parser::Functions 2 | newfunction(:array_slice, :type => :rvalue) do |args| 3 | array = args[0] 4 | from = args[1].to_i 5 | to = args[2].to_i 6 | array[from .. to] 7 | end 8 | end 9 | 10 | -------------------------------------------------------------------------------- /manifests/classes/users.pp: -------------------------------------------------------------------------------- 1 | class users { 2 | # Default ways to add administrators 3 | Users::Massuseraccount <| tag == 'administrators' |> 4 | Users::Lookup <| tag == 'administrators' |> 5 | Users::Useraccount <| tag == 'administrators' |> 6 | Users::Masskeys <| tag == 'administrators' |> 7 | Users::Lookupkey <| tag == 'administrators' |> 8 | 9 | # Also realize users, groups, files and execs tagged with administrators 10 | User <| tag == 'administrators' |> 11 | Group <| tag == 'administrators' |> 12 | File <| tag == 'administrators' |> 13 | Exec <| tag == 'administrators' |> 14 | } 15 | 16 | -------------------------------------------------------------------------------- /manifests/definitions/gidsanity.pp: -------------------------------------------------------------------------------- 1 | define users::gidsanity($groupname) { 2 | $gid = $name 3 | if $etcgroup != '' { 4 | case $operatingsystem { 5 | "Debian": { 6 | # Always move the group id before fixing it, but this won't work on older versions of puppet client 7 | if versioncmp($puppetversion, '0.25') >= 0 { 8 | Exec <| tag == "movegid_$name" |> -> Exec <| tag == "fixgid_$name" |> 9 | } 10 | 11 | # Check if there's some other group with the desired gid 12 | $whohas = regsubst($etcgroup, ".*^([^:]*):[^:]*:$gid:.*", '\1', 'M') 13 | $intruder = $whohas ? { 14 | $etcgroup => '', 15 | default => $whohas, 16 | } 17 | 18 | case $intruder { 19 | # Gid not in use 20 | '' : { 21 | debug("gid $gid is not in use") 22 | } 23 | 24 | # Gid already correctly assigned 25 | $username: { 26 | debug("gid $gid already belong to $username") 27 | } 28 | 29 | # Gid with another group -- change the other group's gid to gid + 10000, and fix /home ownership 30 | default : { 31 | # Sanity must be done before affected groups, but it won't work on older versions of puppet client 32 | if versioncmp($puppetversion, '0.25') >= 0 { 33 | Exec <| tag == "movegid_$name" |> -> Group <| title == "$intruder" or title == "$groupname" |> 34 | } 35 | 36 | # Move group and fix ownership 37 | $newgid = $gid + 10000 38 | exec { "/usr/sbin/groupmod -g $newgid $intruder && /usr/bin/test ! -d /home/$intruder || /usr/bin/find /home/$intruder -gid $gid -exec /bin/chgrp $newgid {} \\;": 39 | logoutput => on_failure, 40 | tag => "movegid_$name", 41 | } 42 | } 43 | } 44 | 45 | # Check if the group exists with a distinct gid 46 | $mygid = regsubst($etcgroup, ".*^$groupname:[^:]*:([^:]*):.*", '\1', 'M') 47 | $currentgid = $mygid ? { 48 | $etcgroup => '', 49 | default => $mygid, 50 | } 51 | 52 | case $currentgid { 53 | # Group not created 54 | '' : { 55 | debug("group $username doesn't exist") 56 | } 57 | 58 | # Group already correctly assigned 59 | $gid : { 60 | debug("$username already has gid $gid") 61 | } 62 | 63 | # Group with different gid -- fix /home ownership in advance (groupmod doesn't fix /home) 64 | default: { 65 | # Sanity must be done before affected groups, but it won't work on older version of puppet client 66 | if versioncmp($puppetversion, '0.25') >= 0 { 67 | Exec <| tag == "fixgid_$name" |> -> Group <| title == "$groupname" |> 68 | } 69 | 70 | # Move group and fix ownership 71 | exec { "/usr/bin/test ! -d /home/$groupname || /usr/bin/find /home/$groupname -gid $currentgid -exec /bin/chgrp $gid {} \\;": 72 | logoutput => on_failure, 73 | tag => "fixgid_$name", 74 | } 75 | } 76 | } 77 | } 78 | } 79 | } else { 80 | fail("etcpasswd fact not available") 81 | } 82 | } 83 | 84 | # vim modeline - have 'set modeline' and 'syntax on' in your ~/.vimrc. 85 | # vi:syntax=puppet:filetype=puppet:ts=4:et: 86 | -------------------------------------------------------------------------------- /manifests/definitions/lookup.pp: -------------------------------------------------------------------------------- 1 | define users::lookup($ensure = present, $groups = []) { 2 | # Waiting for fix #5127 3 | $data = extlookup("${name}_account") 4 | $uid = array_index($data, 0) 5 | $fullname = array_index($data, 1) 6 | $password = array_index($data, 2) 7 | 8 | users::useraccount { "$name": 9 | ensure => $ensure, 10 | fullname => $fullname, 11 | uid => $uid, 12 | groups => $groups, 13 | password => $password, 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /manifests/definitions/lookupkey.pp: -------------------------------------------------------------------------------- 1 | define users::lookupkey($ensure = present) { 2 | # Waiting for fix #5127 3 | $data = extlookup("${name}_sshkey") 4 | $type = array_index($data, "-3") 5 | $key = array_index($data, "-2") 6 | $comment = array_index($data, "-1") 7 | $rest = array_slice($data, 0, "-4") 8 | $options = array_length($rest) ? { 9 | 0 => absent, 10 | default => $rest, 11 | } 12 | 13 | ssh_authorized_key { "${name}_${comment}": 14 | ensure => $ensure, 15 | key => "$key", 16 | type => "$type", 17 | user => "$name", 18 | options => $options, 19 | target => "/home/${name}/.ssh/authorized_keys", 20 | require => [ User["$name"], File["/home/${name}/.ssh"], ], 21 | } 22 | } 23 | 24 | # vi:syntax=puppet:filetype=puppet:ts=4:et: 25 | -------------------------------------------------------------------------------- /manifests/definitions/masskeys.pp: -------------------------------------------------------------------------------- 1 | define users::masskeys($ensure = present) { 2 | $accounts = extlookup("${name}_sshkeys") 3 | users::lookupkey { $accounts: 4 | ensure => $ensure, 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /manifests/definitions/massuseraccount.pp: -------------------------------------------------------------------------------- 1 | define users::massuseraccount($ensure = present, $groups = []) { 2 | $accounts = extlookup("${name}_accounts") 3 | users::lookup { $accounts: 4 | ensure => $ensure, 5 | groups => $groups, 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /manifests/definitions/uidsanity.pp: -------------------------------------------------------------------------------- 1 | define users::uidsanity($username) { 2 | $uid = $name 3 | if $etcpasswd != '' { 4 | case $operatingsystem { 5 | "Debian": { 6 | # Check if there's some other group with the desired gid 7 | $whohas = regsubst($etcpasswd, ".*^([^:]*):[^:]*:$uid:.*", '\1', 'M') 8 | $intruder = $whohas ? { 9 | $etcpasswd => '', 10 | default => $whohas, 11 | } 12 | 13 | case $intruder { 14 | # Uid not in use 15 | '' : { 16 | debug("uid $uid is not in use") 17 | } 18 | 19 | # Uid already correctly assigned 20 | $username: { 21 | debug("uid $uid already belong to $username") 22 | } 23 | 24 | # Uid with another user -- change the other users's uid to uid + 10000 25 | default : { 26 | # Sanity must be done before affected users, but it won't work with older puppet clients 27 | if versioncmp($puppetversion, '0.25') >= 0 { 28 | Exec <| tag == "moveuid_$name" |> -> User <| title == "$intruder" or title == "$username" |> 29 | } 30 | 31 | # Move conflicting user's uid 32 | $newuid = $uid + 10000 33 | exec { "/usr/sbin/usermod -u $newuid $intruder": 34 | logoutput => on_failure, 35 | tag => "moveuid_$name", 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } else { 42 | fail("etcpasswd fact not available") 43 | } 44 | } 45 | 46 | # vim modeline - have 'set modeline' and 'syntax on' in your ~/.vimrc. 47 | # vi:syntax=puppet:filetype=puppet:ts=4:et: 48 | -------------------------------------------------------------------------------- /manifests/definitions/useraccount.pp: -------------------------------------------------------------------------------- 1 | define users::useraccount ( $ensure = present, $fullname, $uid = '', $groups = [], $shell = '/bin/bash', $password = '') { 2 | $username = $name 3 | # This case statement will allow disabling an account by passing 4 | # ensure => absent, to set the home directory ownership to root. 5 | case $ensure { 6 | present: { 7 | $home_owner = $username 8 | $home_group = $username 9 | } 10 | default: { 11 | $home_owner = "root" 12 | $home_group = "root" 13 | } 14 | } 15 | 16 | # Default user settings 17 | user { "$username": 18 | ensure => $ensure, 19 | gid => $username, 20 | groups => $groups, 21 | comment => "$fullname,,,", 22 | home => "/home/$username", 23 | shell => $shell, 24 | allowdupe => false, 25 | managehome => true, 26 | } 27 | 28 | # Default group settings 29 | group { "$username": 30 | ensure => $ensure, 31 | allowdupe => false, 32 | } 33 | 34 | # Ordering of dependencies, just in case 35 | case $ensure { 36 | present: { User <| title == "$username" |> { require => Group["$username"] } } 37 | absent: { Group <| title == "$username" |> { require => User["$username"] } } 38 | } 39 | 40 | # Set password if available 41 | if $password != '' { 42 | User <| title == "$username" |> { password => $password } 43 | } 44 | 45 | # uid/gid management 46 | if $uid != '' { 47 | # Manage uid if etcpasswd is available 48 | if $etcpasswd != '' { 49 | User <| title == "$username" |> { uid => $uid } 50 | users::uidsanity { "$uid": username => $username } 51 | } 52 | 53 | # Manage gid if etcgroup is available 54 | if $etcgroup != '' { 55 | User <| title == "$username" |> { gid => $uid } 56 | Group <| title == "$username" |> { gid => $uid } 57 | users::gidsanity { "$uid": groupname => $username } 58 | } 59 | } 60 | 61 | case $ensure { 62 | present: { 63 | if versioncmp($puppetversion, '0.25') >= 0 { 64 | $managedDirs = [ 65 | "/etc/puppet/files/users/home/managed/host/${username}.$fqdn", 66 | "/etc/puppet/files/users/home/managed/host/${username}.$hostname", 67 | "/etc/puppet/files/users/home/managed/domain/${username}.$domain", 68 | "/etc/puppet/files/users/home/managed/env/${username}.$environment", 69 | "/etc/puppet/files/users/home/managed/user/${username}", 70 | "/etc/puppet/files/users/home/managed/skel", 71 | ] 72 | 73 | case generate('/etc/puppet/modules/users/scripts/findDirs.sh', $managedDirs) { 74 | '': { 75 | file { "/home/${username}": 76 | ensure => $ensure ? { 77 | present => directory, 78 | absent => absent, 79 | }, 80 | owner => $home_owner, 81 | group => $home_group, 82 | #mode => 644, # Cannot apply mode, or it will change ALL files 83 | recurse => remote, 84 | replace => false, 85 | ignore => [ '*.git', '*.swp', '*.un~' ], 86 | source => [ 87 | "puppet:///files/users/home/default/host/${username}.$fqdn", 88 | "puppet:///files/users/home/default/host/${username}.$hostname", 89 | "puppet:///files/users/home/default/domain/${username}.$domain", 90 | "puppet:///files/users/home/default/env/${username}.$environment", 91 | "puppet:///files/users/home/default/user/${username}", 92 | "puppet:///files/users/home/default/skel", 93 | "puppet:///users/home/default", 94 | ], 95 | sourceselect => all, 96 | require => User["${username}"], 97 | } 98 | } 99 | default: { 100 | file { "/home/${username}": 101 | ensure => $ensure ? { 102 | present => directory, 103 | absent => absent, 104 | }, 105 | owner => $home_owner, 106 | group => $home_group, 107 | #mode => 644, # Cannot apply mode, or it will change ALL files 108 | recurse => remote, 109 | replace => true, 110 | force => true, 111 | ignore => '.git', 112 | source => [ 113 | "puppet:///files/users/home/managed/host/${username}.$fqdn", 114 | "puppet:///files/users/home/managed/host/${username}.$hostname", 115 | "puppet:///files/users/home/managed/domain/${username}.$domain", 116 | "puppet:///files/users/home/managed/env/${username}.$environment", 117 | "puppet:///files/users/home/managed/user/${username}", 118 | "puppet:///files/users/home/managed/skel", 119 | ], 120 | sourceselect => all, 121 | require => User["${username}"], 122 | } 123 | } 124 | } 125 | } else { 126 | file { "/home/${username}": 127 | ensure => $ensure ? { 128 | present => directory, 129 | absent => absent, 130 | }, 131 | owner => $home_owner, 132 | group => $home_group, 133 | mode => 644, # Cannot apply mode, or it will change ALL files 134 | require => User["${username}"], 135 | } 136 | } 137 | 138 | file { "/home/${username}/.bash_history": 139 | mode => 600, 140 | owner => $home_owner, 141 | group => $home_group, 142 | require => File["/home/${username}"], 143 | } 144 | 145 | file { "/home/${username}/.ssh": 146 | ensure => directory, 147 | owner => $home_owner, 148 | group => $home_group, 149 | mode => 700, 150 | require => File["/home/${username}"], 151 | } 152 | } 153 | } 154 | } 155 | 156 | # vim modeline - have 'set modeline' and 'syntax on' in your ~/.vimrc. 157 | # vi:syntax=puppet:filetype=puppet:ts=4:et: 158 | -------------------------------------------------------------------------------- /manifests/definitions/userkey.pp: -------------------------------------------------------------------------------- 1 | define users::userkey($key, $ensure = present, $type = "ssh-rsa", $comment = "default-key" ) { 2 | if ($key != "" ) { 3 | ssh_authorized_key { "${title}_${comment}": 4 | ensure => $ensure, 5 | key => $key, 6 | type => $type, 7 | user => $name, 8 | options => $options, 9 | require => [ User[$name], File["/home/${name}/.ssh"], ], 10 | } 11 | } 12 | } 13 | # vi:syntax=puppet:filetype=puppet:ts=4:et: 14 | -------------------------------------------------------------------------------- /manifests/init.pp: -------------------------------------------------------------------------------- 1 | import "classes/*.pp" 2 | import "definitions/*.pp" 3 | -------------------------------------------------------------------------------- /scripts/findDirs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for dir in "$@" 4 | do 5 | ls -d "$dir" 2>/dev/null 6 | done 7 | 8 | exit 0 9 | 10 | --------------------------------------------------------------------------------