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

Reply via email to