Faidon Liambotis has uploaded a new change for review. https://gerrit.wikimedia.org/r/107848
Change subject: (WIP) Refactor admins.pp into an admin module ...................................................................... (WIP) Refactor admins.pp into an admin module (this is WORK IN PROGRESS and UNTESTED) Refactor the huge often unmanageable admins.pp into a new "admins" module. Several enhancements have been introduced: - Split of code, logic & data, with generic abstractions and code-agnostic data structures (hashes) for users, group memberships, ssh keys & sudo policies. This can in the future be combined with Hiera, LDAP or stdlib's json import to completely isolate the data import functionality. - Tie Unix groups with our arbitrary class groupings; grouping users together in a class now means grouping them in a Unix group too. - Introduce a "revoked" group; users included in this group are revoked of access, with this group being applied on all hosts, rather than just hosts that may had access before. - Completely manage SSH keys and groups memberships; users cannot add unpuppetized keys to their user accounts anymore. - A new, generic, "account" definition to handle all things related to an account (user, group, home directory, SSH key) - Integration with sudo policies, effectively replacing sudo.pp Change-Id: I6e5e2d636f0f8d47a134feca0c0386881476366b --- A modules/admins/manifests/account.pp A modules/admins/manifests/data.pp A modules/admins/manifests/group.pp A modules/admins/manifests/init.pp A modules/admins/manifests/sudo.pp A modules/admins/manifests/user.pp A modules/admins/templates/sudo/sudoers.erb 7 files changed, 433 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/operations/puppet refs/changes/48/107848/1 diff --git a/modules/admins/manifests/account.pp b/modules/admins/manifests/account.pp new file mode 100644 index 0000000..27b1cf9 --- /dev/null +++ b/modules/admins/manifests/account.pp @@ -0,0 +1,127 @@ +# == Define: admins::account +# +# A defined type for user account management. It creates (or deletes) at least +# a User resource, plus virtual resources for the group, home directory and SSH +# authorized key of the user. +# +# WARNING: this is designed to NOT play well with local modifications. It will +# overwrite at least group membership & SSH keys. It's also intentionally # +# simple, not supporting configurations that are of no use for the setup it was +# created (passwords, system users etc.) +# +# === Parameters +# +# [*ensure*] +# Add or remove the user account, with "present" or "absent" respectively. +# Defaults to present. +# +# [*username*] +# The username of the user to be created. +# Defaults to the title of the account resource. +# +# [*realname*] +# The gecos realname for the user. +# +# [*uid*] +# The UID to set for the new account. +# +# [*gid*] +# Sets the primary group of this user. +# +# [*groups*] +# An array of additional groups to add the user to. +# Defaults to an empty array. +# +# [*ssh_keys*] +# An array of strings containing the SSH public keys. +# Defaults to an empty array. +# +# [*shell*] +# The login shell. +# The default is '/bin/bash' +# + +define admins::account( + $ensure, + $realname, + $uid, + $gid, + $groups=[], + $ssh_keys=[], + $shell='/bin/bash' + $username=$title, +) { + validate_re($ensure, '^(present|absent)$') + + $ensure_dir = $ensure ? { + 'absent' => 'absent', + 'present' => 'directory', + } + + user { $username: + ensure => $ensure, + name => $username, + uid => $uid, + comment => $realname, + gid => $gid, + groups => $groups, + membership => 'inclusive', + shell => $shell, + managehome => false, # we do it manually below + allowdupe => false, + } + + case $ensure { + 'present': { + Group[$gid] -> User[$username] + } + 'absent': { + User[$username] -> Group[$gid] + } + default: {} + } + + @group { $gid: + ensure => $ensure, + name => $gid, + allowdupe => false, + } + + @file { "/home/${username}": + ensure => $ensure_dir, + source => [ + "puppet:///modules/account/home/${username}/", + 'puppet:///modules/account/home/skel/', + ], + sourceselect => 'first', + recurse => 'remote', + mode => '0644', + owner => $username, + group => $gid, + require => [ User[$username], Group[$gid] ], + tag => 'account/home' + } + + # use regular file resources instead of the special ssh_authorized_keys + # resources since we *exclusively* manage ssh keys and do not coexist + # with local ones + + $ssh_authorized_keys = join($ssh_keys, "\n") + + # XXX: move under /etc/ssh/userkeys + @file { "/home/${username}/.ssh": + ensure => $ensure_dir, + owner => $username, + group => $gid, + mode => '0700', + tag => 'account/home' + } + @file { "/home/${username}/.ssh/authorized_keys": + ensure => $ensure, + owner => $username, + group => $gid, + mode => '0600', + content => $ssh_authorized_keys, + tag => 'account/home' + } +} diff --git a/modules/admins/manifests/data.pp b/modules/admins/manifests/data.pp new file mode 100644 index 0000000..da6f922 --- /dev/null +++ b/modules/admins/manifests/data.pp @@ -0,0 +1,202 @@ +# XXX: this is just for illustrative purposes. + +class admins::data { + $gids = { + 'wikidev' => 500, + 'roots' => 501, + 'mortals' => 502, + 'restricted' => 503, + 'labs' => 504, + 'jenkins' => 505, + 'dctech' => 506, + 'globaldev' => 507, + 'privatedata' => 508, + 'fr-tech' => 509, + 'parsoid' => 510, + 'search' => 538, + 'l10nupdate' => 10002, # XXX: move to another module + 'file_mover' => 30001, # XXX: used by fundraising, move to another module + 'revoked' => 600, + } + + $members = { + 'wikidev' => [], + 'ops' => [ + 'akosiaris', + 'andrewb', + 'ariel', + 'bblack', + 'catrope', + 'cmjohnson', + 'dzahn', + 'faidon', + 'gage', + 'jgreen', + 'laner', + 'lcarr', + 'marc', + 'mark', + 'midom', + 'ori', + 'otto', + 'robh', + 'springle', + 'tstarling', + ], + 'mortals' => [ + 'aaron', + 'abaso', + 'andrew', + 'anomie', + 'aude', # RT 6460 + 'awight', + 'awjrichards', + 'bd808', + 'brion', # RT 4798 + 'bsitu', + 'cmcmahon', + 'csteipp', + 'demon', + 'ebernhardson', # RT 5717 + 'gdubuc', # RT 6619 + 'gjg', + 'gwicke', + 'halfak', + 'hashar', + 'kaldari', + 'kartik', # RT 6533 + 'khorn', + 'krinkle', + 'manybubbles', # RT 5691 + 'maxsem', + 'mflaschen', + 'mholmquist', + 'mhoover', + 'milimetric', # RT 5982 + 'mlitn', + 'mwalker', # RT 4747 + 'nikerabbit', + 'pgehres', + 'reedy', + 'rmoen', + 'robla', + 'spage', + 'ssastry', # RT 5512 + 'sumanah', # RT 3752 + 'tfinc', # RT 5485 + 'yurik', # RT 4835, RT 5069 + ], + 'restricted' => [ + 'avar', + 'dab', + 'dartar', + 'diederik', + 'erik', + 'ezachte', + 'ironholds', # RT 5935 + 'jamesofu', + 'khorn', + 'mgrover', # RT 4600 + 'qchris', # RT 5403 + 'rainman', + 'spetrea', # RT 5406 + 'ssastry', # RT 5512 + 'tnegrin', # RT 5391 + 'tparscal', + ], + 'labs' => [ + 'mhoover', + ], + 'jenkins' => [ + 'demon', + 'hashar', + 'krinkle', + 'reedy', + 'mholmquist', + ], + 'dctech'=> [ + 'sbernardin', + ], + 'globaldev' => [ + 'erosen', + 'haithams', + 'handrade', + ], + 'privatedata' => [ + 'erosen', + 'haithams', # RT 3219 + 'handrade', # RT 4726 + 'ezachte', + 'milimetric', + 'diederik', + 'dartar', + 'spetrea', + 'yurik', # RT 4835 + 'howief', # RT 3576 + 'mgrover', # RT 4600 + 'mwalker', # RT 5038 + 'awight', # RT 5048 + 'abaso', # RT 5446 + 'qchris', # RT 5474 + 'tnegrin', # RT 5391 + 'nuria', # RT 6617 + ], + 'fr-tech' => [ + 'awight', + 'khorn', + 'pgehres', + 'mwalker', + 'ssmith', + ], + 'parsoid' => [ + 'gwicke', + 'catrope', + 'ssastry', + ], + 'revoked' => [ + 'asher', + 'ashields', + 'austin', + 'bastique', + 'ben', + 'daniel', + 'dsc', + 'fvassard', + 'jeluf', + 'kate', + 'neilk', # RT 2345 + 'nimishg', + 'olivneh', # renamed to 'ori' + 'pdhanda', + 'preilly', + 'py', + 'raindrift', # RT 3088 + 'ram', + 'rcole', + 'sara', + 'zak', + ], + } + + $sudo = { + '%ops' => { + privileges => [ 'ALL=(ALL) NOPASSWD: ALL' ], + }, + '%parsoid' => { + privileges => [ 'ALL=(parsoid) NOPASSWD: ALL' ], + }, + } + + $users = { + 'faidon' => { + realname => 'Faidon Liambotis', + uid => 592, + gid => 'wikidev', + groups => [ 'ops' ] + ssh => [ + 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/m5mZhy2bpvmBNzaLLhlqhjLuuGd5vNGgAtRKmvfa+nbHi7upm8d/e1RoSGVueXSVdjcVYfqqfNnJQ9GIC9flhgVhTwz1zezCEWREqMQ3XuauqAr+Tb/031BtgLCHfTmUjdsDKTigwTMPOnRG+DNo+ZHyxfpTCP5Oy6TChcK6+Om247eiXEhHZNL8Sk0idSy2mSJxavzs25F/lsGjsl4YyVV3jNqgVqoz3Evl1VO0E3xlbOOeWeJnROq+g2JJqZfoCtdAYidtg8oJ6yBKJHoxynqI6EhBJtnwulIXGTZmdY2cMJwT2YpkqljQFBwtWIy/T+WNkZnLuJXT4DRlBb1F faidon@wmf', + ], + }, + # XXX + } +} diff --git a/modules/admins/manifests/group.pp b/modules/admins/manifests/group.pp new file mode 100644 index 0000000..30978a4 --- /dev/null +++ b/modules/admins/manifests/group.pp @@ -0,0 +1,19 @@ +define admins::group( + $ensure='present', +) { + admins::user { $admins::members[$title]: + ensure => $ensure, + } + + # realize Group, plus assign a gid from our admins map + Group <| title == $title |> { + gid => $admins::gids[$title], + } + + $sudo_group = "%${title}" + if has_key($admins::sudo, $sudo_group) { + create_resources(sudo, $admins::sudo[$sudo_group], { + ensure => $ensure, + }) + } +} diff --git a/modules/admins/manifests/init.pp b/modules/admins/manifests/init.pp new file mode 100644 index 0000000..8731e28 --- /dev/null +++ b/modules/admins/manifests/init.pp @@ -0,0 +1,56 @@ +class admins { + include admins::data + + # used as primary gid for most groups; may be redefined elsewhere + @group { 'wikidev': + ensure => present, + name => 'wikidev', + allowdupe => false, + } + Group <| title == 'wikidev' |> { + gid => $admins::gids['wikidev'], + } + + # remove everyone that's a member of the special-named group "revoked" + admins::group { 'revoked': + ensure => absent, + } + + # ugh, this is ugly. create home directories + if !defined(Class['nfs::home']) { + File <| tag == 'account/home' |> + } +} + +# compatibility classes for migration; too ugly to follow autoload pattern +class admins::roots inherits admins { + # note the "ops" instead of "roots" + admins::group { 'ops': } +} +class admins::mortals inherits admins { + admins::group { 'mortals': } +} +class admins::restricted inherits admins { + admins::group { 'restricted': } +} +class admins::labs inherits admins { + admins::group { 'labs': } +} +class admins::jenkins inherits admins { + admins::group { 'jenkins': } +} +class admins::dctech inherits admins { + admins::group { 'dctech': } +} +class admins::globaldev inherits admins { + admins::group { 'globaldev': } +} +class admins::privatedata inherits admins { + admins::group { 'privatedata': } +} +class admins::fr-tech inherits admins { + admins::group { 'fr-tech': } +} +class admins::parsoid inherits admins { + admins::group { 'parsoid': } +} diff --git a/modules/admins/manifests/sudo.pp b/modules/admins/manifests/sudo.pp new file mode 100644 index 0000000..a6b10be --- /dev/null +++ b/modules/admins/manifests/sudo.pp @@ -0,0 +1,19 @@ +define admins::sudo( + $privileges=[], + $ensure='present', +) { + + $lhs = $title + $filename = $title ? { + /^%(.*)/ => "group-${1}", + default => $0, + } + + file { "/etc/sudoers.d/${filename}": + ensure => $ensure, + owner => 'root', + group => 'root', + mode => '0440', + content => template("${module_name}/sudo/sudoers.erb"), + } +} diff --git a/modules/admins/manifests/user.pp b/modules/admins/manifests/user.pp new file mode 100644 index 0000000..619621b --- /dev/null +++ b/modules/admins/manifests/user.pp @@ -0,0 +1,5 @@ +define admins::user($ensure='present') { + create_resources('admins::account', $admins::users[$title], { + ensure => $ensure, + }) +} diff --git a/modules/admins/templates/sudo/sudoers.erb b/modules/admins/templates/sudo/sudoers.erb new file mode 100644 index 0000000..3bf3649 --- /dev/null +++ b/modules/admins/templates/sudo/sudoers.erb @@ -0,0 +1,5 @@ +# This file is managed by Puppet! + +<% privileges.each do |privilege| -%> +<%= lhs %> <%= privilege %> +<% end -%> -- To view, visit https://gerrit.wikimedia.org/r/107848 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I6e5e2d636f0f8d47a134feca0c0386881476366b Gerrit-PatchSet: 1 Gerrit-Project: operations/puppet Gerrit-Branch: production Gerrit-Owner: Faidon Liambotis <fai...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits