From d7ff5a35d6d0a4ce03cd7fa1e96d0c0d65bfe046 Mon Sep 17 00:00:00 2001 From: "A. Karl Kornel" <akkornel@stanford.edu> Date: Thu, 18 Aug 2016 15:01:02 -0700 Subject: [PATCH] =?UTF-8?q?sudo:=20Update=20from=20Karl=E2=80=99s=20dev=20?= =?UTF-8?q?work?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.sudo | 38 ++++++++++++++++++++ manifests/sudo.pp | 92 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 114 insertions(+), 16 deletions(-) create mode 100644 README.sudo diff --git a/README.sudo b/README.sudo new file mode 100644 index 0000000..c145aef --- /dev/null +++ b/README.sudo @@ -0,0 +1,38 @@ +This README file explains how to use base::sudo. + +base::sudo can be used to enable and configure sudo for a system, with or +without Duo. + +base::sudo is a parameterized class. If you include or require it without any +parameters, the only thing that happens is, the sudo package is installed. On +Debian systems, that means anyone in the local "sudo" group has sudo access. On +RHEL-family systems, that means anyone in the local "wheel" group has sudo +access. To set the sudo timeout (which defaults to 30 minutes), set the +$timeout parameter. + +WARNING: Without any parameters, this configuration means that, when you use +sudo, you will be sending your password over the wire, and it will sit in +memory on that remote system (which may be swapped to disk). + +base::sudo also supports using Duo two-factor as the authentication method, +instead of password. To enable this, set the "duo" parameter to true, and set +the "duo_sudoers" parameter to the list of people who will have this sudo +access. + +TIP: If you have a base::user class that defines your list of root users, you +could simply pass that list into base::sudo. + +WARNING: To be clear, setting the "duo" parameter to true will completely +disable password-based authentication for sudo! + +There are two additional Duo-related parameters that you should look at: + +duo_fail_secure: If you set this to true, and the Duo service is +unavailable or blocked, the sudo will fail. Normally, the sudo would succeed. +This parameter does not apply if the Duo service is working: If you fail to +answer a Duo call/push, or you deny the Duo call/push, then your sudo would +still fail. + +duo_gecos: If your local username on a system matches your username in Duo, +then set this to false. The default is to take your Duo username from the +GECOS field of the passwd file (Puppet calls this field the "comment" field). diff --git a/manifests/sudo.pp b/manifests/sudo.pp index 41ad965..d59394e 100644 --- a/manifests/sudo.pp +++ b/manifests/sudo.pp @@ -3,7 +3,17 @@ # $duo: enable pam_duo for sudo. Defaults to false. # # $duo_sudoers: A list of users that are allowed to call sudo. -# Defaults to the empty array. +# Defaults to the empty array. Only used when $duo is set to true. +# +# $duo_fail_secure: A boolean, normally false. If set to false, a Duo +# timeout will cause the Duo step to be skipped. If set to true, a Duo timeout +# will cause the Duo step to fail (which means sudo will be blocked). Only +# used when $duo is set to true. +# +# $duo_gecos: A boolean, normally true. If false, then Duo will will use the +# user's username. If true, then Duo will use the contents of the user's GECOS +# field as their username. This is important if you are using an alternate +# account. # # $timeout: how long (in minutes) between requiring a new Duo re-auth. # Default: 30 @@ -35,37 +45,87 @@ # } class base::sudo( - $duo = false, - $duo_sudoers = [], - $timeout = 30, - $debuild = false, + $duo = false, + $duo_sudoers = [], + $duo_fail_secure = false, + $duo_gecos = true, + $timeout = 30, + $debuild = false, ){ + # Install the sudo package package { 'sudo': ensure => installed } - # If duo is enabled, require base::duo and set up the - # sudoers file. + # Configure a default timeout + file_line { 'Set sudo timeout': + ensure => present, + path => '/etc/sudoers', + line => "Defaults timestamp_timeout = $timeout", + match => '^Defaults\ +timestamp_timeout', + } + + # If duo is enabled, require base::duo and set up the sudoers file. if ($duo) { - include base::duo + # Validate $duo_fail_secure and $duo_gecos + # base::duo::config does this too, but by doing it here it is clearer to + # clients where the problem is! + if !is_bool($duo_fail_secure) { + fail('base::sudo::duo_fail_secure must be true or false') + } + if !is_bool($duo_gecos) { + fail('base::sudo::duo_gecos must be true or false') + } + + # Install the Duo config, passing the GECOS and fail-secure settings through + base::duo::config { '/etc/security/pam_duo_su.conf': + ensure => present, + use_gecos => $duo_gecos, + fail_secure => $duo_fail_secure, + } # Install the pam.d configuration that requires Duo on sudo. file {'/etc/pam.d/sudo': ensure => present, content => template('base/sudo/etc/pam.d/sudo.erb'), - require => Class['base::duo'], + require => Package['sudo'], + } + + # Make sure that the sudoers.d directory exists, and is read + # This is done on alot of OSes already, but not all. + file { '/etc/sudoers.d': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0750', + require => Package['sudo'], + } + file_line { 'Add sudoers.d includedir': + ensure => present, + path => '/etc/sudoers', + line => "#includedir /etc/sudoers.d", + require => File['/etc/sudoers.d'], } # Install the suoders file. This takes the array $duo_sudoers # and puts it into /etc/sudoers.d/duo - if (downcase($::osfamily) =~ /^debian$/) { - file {'/etc/sudoers.d/duo': - ensure => present, - content => template('base/sudo/etc/sudoers.d/duo.erb'), - require => Package['sudo'], + file {'/etc/sudoers.d/duo': + ensure => present, + content => template('base/sudo/etc/sudoers.d/duo.erb'), + require => File_line['Add sudoers.d includedir'] + } + } + + # If we're not using Duo, we still might need to update the sudoers file + else { + # Debian's config is fine, but we need to enable wheel in RHEL systems + if $::osfamily == 'RedHat' { + file_line { 'Enable wheel sudoers': + ensure => present, + path => '/etc/sudoers', + line => '%wheel ALL=(ALL) ALL', + match => '# %wheel ALL=(ALL) ALL', } - } else { - fail("base::sudo with duo does not yet support ${::osfamily}.") } } } -- GitLab