Skip to content

Commit

Permalink
Support managing faillock.conf and pwquality.conf
Browse files Browse the repository at this point in the history
  • Loading branch information
treydock committed Mar 12, 2024
1 parent 3c0c3a3 commit 9636c5d
Show file tree
Hide file tree
Showing 9 changed files with 586 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ though generally include things such as the following.
The management of `/etc/security/access.conf` can be controlled by the
`pam::manage_accesslogin` parameter (enabled by default).

The management of `/etc/security/faillock.conf` can be controlled by the
`pam::manage_faillock` parameter (disabled by default).

The management of `/etc/security/pwquality.conf` and `/etc/security/pwquality.conf.d`
can be controlled by the `pam::manage_pwquality` parameter (disabled by default).

### Setup requirements
This module requires `stdlib`. When deployed by default it will require
`nsswitch`. See below for more information.
Expand Down
75 changes: 75 additions & 0 deletions manifests/faillock.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# @summary Manage faillock.conf
#
# @param config_file
# The faillock config path
# @param config_file_owner
# The faillock config owner
# @param config_file_group
# The faillock config group
# @param config_file_mode
# The faillock config mode
# @param config_file_template
# The faillock config template
# @param config_file_source
# The faillock config source
# @param dir
# The faillock 'dir' config option
# @param audit_enabled
# The faillock 'audit' config option
# @param silent
# The faillock 'silent' config option
# @param no_log_info
# The faillock 'no_log_info' config option
# @param local_users_only
# The faillock 'local_users_only' config option
# @param deny
# The faillock 'deny' config option
# @param fail_interval
# The faillock 'fail_interval' config option
# @param unlock_time
# The faillock 'unlock_time' config option
# @param even_deny_root
# The faillock 'even_deny_root' config option
# @param root_unlock_time
# The faillock 'root_unlock_time' config option
# @param admin_group
# The faillock 'admin_group' config option
#
class pam::faillock (
Stdlib::Absolutepath $config_file = '/etc/security/faillock.conf',
String[1] $config_file_owner = 'root',
String[1] $config_file_group = 'root',
Stdlib::Filemode $config_file_mode = '0644',
String[1] $config_file_template = 'pam/faillock.conf.erb',
Optional[Stdlib::Filesource] $config_file_source = undef,
Stdlib::Absolutepath $dir = '/var/run/faillock',
Optional[Boolean] $audit_enabled = undef,
Optional[Boolean] $silent = undef,
Optional[Boolean] $no_log_info = undef,
Optional[Boolean] $local_users_only = undef,
Integer[0] $deny = 3,
Integer[0] $fail_interval = 900,
Integer[0] $unlock_time = 600,
Optional[Boolean] $even_deny_root = undef,
Integer[0] $root_unlock_time = $unlock_time,
Optional[String[1]] $admin_group = undef,
) {
include pam

if $config_file_source {
$_config_file_content = undef
} else {
$_config_file_content = template($config_file_template)
}

file { 'faillock.conf':
ensure => 'file',
path => $config_file,
owner => $config_file_owner,
group => $config_file_group,
mode => $config_file_mode,
content => $_config_file_content,
source => $config_file_source,
require => Package[$pam::package_name],
}
}
16 changes: 16 additions & 0 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
# in Hiera. This is useful for specifying fragments at different levels of
# the hierarchy and having them all included in the catalog.
#
# @param manage_faillock
# Controls whether to manage faillock.conf
#
# @param manage_pwquality
# Controls whether to manage pwquality.conf and pwquality.conf.d
#
# @param package_name
# String or Array of packages providing the pam functionality. If undef,
# parameter is set based on the OS version.
Expand Down Expand Up @@ -203,6 +209,8 @@
Optional[Hash] $services = undef,
Optional[Hash] $limits_fragments = undef,
Boolean $limits_fragments_hiera_merge = false,
Boolean $manage_faillock = false,
Boolean $manage_pwquality = false,
Array $pam_d_login_oracle_options = [],
Stdlib::Absolutepath $pam_d_login_path = '/etc/pam.d/login',
String $pam_d_login_owner = 'root',
Expand Down Expand Up @@ -311,6 +319,14 @@
}
}

if $manage_faillock {
include pam::faillock
}

if $manage_pwquality {
include pam::pwquality
}

if $manage_nsswitch {
include nsswitch
}
Expand Down
136 changes: 136 additions & 0 deletions manifests/pwquality.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# @summary Manage pwquality.conf
#
# @example
# This class is included by the pam class for platforms which use it.
#
# @param config_file
# Path to pwquality.conf.
# @param config_file_owner
# Owner for pwquality.conf
# @param config_file_group
# Group for pwquality.conf
# @param config_file_mode
# Mode for config_file.
# @param config_file_source
# String with source path to a pwquality.conf
# @param config_file_template
# Template to render pwquality.conf
# @param config_d_dir
# Path to pwquality.conf.d directory.
# @param config_d_dir_owner
# Owner for pwquality.conf.d
# @param config_d_dir_group
# Group for pwquality.conf.d
# @param config_d_dir_mode
# Mode for pwquality.conf.d
# @param purge_config_d_dir
# Boolean to purge the pwquality.conf.d directory.
# @param purge_config_d_dir_ignore
# A glob or array of file names to ignore when purging pwquality.conf.d
#
# @param difok
# The pwquality.conf 'difok' option
# @param minlen
# The pwquality.conf 'minlen' option
# @param dcredit
# The pwquality.conf 'dcredit' option
# @param ucredit
# The pwquality.conf 'ucredit' option
# @param lcredit
# The pwquality.conf 'lcredit' option
# @param ocredit
# The pwquality.conf 'ocredit' option
# @param minclass
# The pwquality.conf 'minclass' option
# @param maxrepeat
# The pwquality.conf 'maxrepeat' option
# @param maxsequence
# The pwquality.conf 'maxsequence' option
# @param maxclassrepeat
# The pwquality.conf 'maxclassrepeat' option
# @param gecoscheck
# The pwquality.conf 'gecoscheck' option
# @param dictcheck
# The pwquality.conf 'dictcheck' option
# @param usercheck
# The pwquality.conf 'usercheck' option
# @param usersubstr
# The pwquality.conf 'usersubstr' option
# @param enforcing
# The pwquality.conf 'enforcing' option
# @param badwords
# The pwquality.conf 'badwords' option
# @param dictpath
# The pwquality.conf 'dictpath' option
# @param retry
# The pwquality.conf 'retry' option
# @param enforce_for_root
# The pwquality.conf 'enforce_for_root' option
# @param local_users_only
# The pwquality.conf 'local_users_only' option
#
class pam::pwquality (
Stdlib::Absolutepath $config_file = '/etc/security/pwquality.conf',
String[1] $config_file_owner = 'root',
String[1] $config_file_group = 'root',
Stdlib::Filemode $config_file_mode = '0644',
Optional[Stdlib::Filesource] $config_file_source = undef,
String[1] $config_file_template = 'pam/pwquality.conf.erb',
Stdlib::Absolutepath $config_d_dir = '/etc/security/pwquality.conf.d',
String[1] $config_d_dir_owner = 'root',
String[1] $config_d_dir_group = 'root',
Stdlib::Filemode $config_d_dir_mode = '0755',
Boolean $purge_config_d_dir = true,
Optional[Variant[String[1], Array[String[1]]]] $purge_config_d_dir_ignore = undef,
Integer[0] $difok = 1,
Integer[6] $minlen = 8,
Integer $dcredit = 0,
Integer $ucredit = 0,
Integer $lcredit = 0,
Integer $ocredit = 0,
Integer[0] $minclass = 0,
Integer[0] $maxrepeat = 0,
Integer[0] $maxsequence = 0,
Integer[0] $maxclassrepeat = 0,
Integer[0] $gecoscheck = 0,
Integer[0] $dictcheck = 1,
Integer[0] $usercheck = 1,
Integer[0] $usersubstr = 0,
Integer[0] $enforcing = 1,
Optional[Array[String[1]]] $badwords = undef,
Optional[Stdlib::Absolutepath] $dictpath = undef,
Integer[0] $retry = 1,
Optional[Boolean] $enforce_for_root = undef,
Optional[Boolean] $local_users_only = undef,
) {
include pam

if $config_file_source {
$_config_file_content = undef
} else {
$_config_file_content = template($config_file_template)
}

file { 'pwquality.conf':
ensure => 'file',
path => $config_file,
owner => $config_file_owner,
group => $config_file_group,
mode => $config_file_mode,
source => $config_file_source,
content => $_config_file_content,
require => Package[$pam::package_name],
}

file { 'pwquality.conf.d':
ensure => 'directory',
path => $config_d_dir,
owner => $config_d_dir_owner,
group => $config_d_dir_group,
mode => $config_d_dir_mode,
purge => $purge_config_d_dir,
recurse => $purge_config_d_dir,
ignore => $purge_config_d_dir_ignore,
require => Package[$pam::package_name],
}
}
101 changes: 101 additions & 0 deletions spec/classes/faillock_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
require 'spec_helper'
require 'spec_platforms'

describe 'pam::faillock' do
on_supported_os.each do |os, os_facts|
# this function call mimic hiera data, it is sourced in from spec/spec_platforms.rb
package_name = package_name(os)

context "on #{os}" do
let(:facts) { os_facts }
let(:content) do
<<-END.gsub(%r{^\s+\|}, '')
|# This file is being maintained by Puppet.
|# DO NOT EDIT
|#
|dir = /var/run/faillock
|deny = 3
|fail_interval = 900
|unlock_time = 600
|root_unlock_time = 600
END
end

it { is_expected.to compile.with_all_deps }
it { is_expected.to contain_class('pam') }

it do
is_expected.to contain_file('faillock.conf').with(
'ensure' => 'file',
'path' => '/etc/security/faillock.conf',
'source' => nil,
'content' => content,
'owner' => 'root',
'group' => 'root',
'mode' => '0644',
)
end

package_name.sort.each do |pkg|
it { is_expected.to contain_file('faillock.conf').that_requires("Package[#{pkg}]") }
end

context 'with config_file set to a valid path' do
let(:params) { { config_file: '/testing' } }

it { is_expected.to contain_file('faillock.conf').with_path('/testing') }
end

context 'with config_file_source set to a valid string' do
let(:params) { { config_file_source: 'puppet:///pam/unit_tests.erb' } }

it { is_expected.to contain_file('faillock.conf').with_source('puppet:///pam/unit_tests.erb') }
it { is_expected.to contain_file('faillock.conf').with_content(nil) }
end

context 'with config_file_mode set to a valid string' do
let(:params) { { config_file_mode: '0242' } }

it { is_expected.to contain_file('faillock.conf').with_mode('0242') }
end

context 'when config options are non-default' do
let(:params) do
{
dir: '/foo',
audit_enabled: true,
silent: true,
no_log_info: true,
local_users_only: true,
deny: 1,
fail_interval: 2,
unlock_time: 3,
even_deny_root: true,
root_unlock_time: 4,
admin_group: 'admins'
}
end
let(:content) do
<<-END.gsub(%r{^\s+\|}, '')
|# This file is being maintained by Puppet.
|# DO NOT EDIT
|#
|dir = /foo
|audit
|silent
|no_log_info
|local_users_only
|deny = 1
|fail_interval = 2
|unlock_time = 3
|even_deny_root
|root_unlock_time = 4
|admin_group = admins
END
end

it { is_expected.to contain_file('faillock.conf').with_content(content) }
end
end
end
end
20 changes: 20 additions & 0 deletions spec/classes/init_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,26 @@
end
end

context 'with manage_faillock parameter default value' do
it { is_expected.not_to contain_class('pam::faillock') }
end

context 'with manage_faillock parameter set to true' do
let(:params) { { manage_faillock: true } }

it { is_expected.to contain_class('pam::faillock') }
end

context 'with manage_pwquality parameter default value' do
it { is_expected.not_to contain_class('pam::pwquality') }
end

context 'with manage_pwquality parameter set to true' do
let(:params) { { manage_pwquality: true } }

it { is_expected.to contain_class('pam::pwquality') }
end

context 'with manage_nsswitch parameter default value' do
it { is_expected.to contain_class('nsswitch') }
end
Expand Down
Loading

0 comments on commit 9636c5d

Please sign in to comment.