Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for managing pwquality.conf #271

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ 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/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
8 changes: 8 additions & 0 deletions manifests/init.pp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
# in Hiera. This is useful for specifying fragments at different levels of
# the hierarchy and having them all included in the catalog.
#
# @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 +206,7 @@
Optional[Hash] $services = undef,
Optional[Hash] $limits_fragments = undef,
Boolean $limits_fragments_hiera_merge = 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 +315,10 @@
}
}

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],
}
}
10 changes: 10 additions & 0 deletions spec/classes/init_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,16 @@
end
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
175 changes: 175 additions & 0 deletions spec/classes/pwquality_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
require 'spec_helper'
require 'spec_platforms'

describe 'pam::pwquality' 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
|#
|difok = 1
|minlen = 8
|dcredit = 0
|ucredit = 0
|lcredit = 0
|ocredit = 0
|minclass = 0
|maxrepeat = 0
|maxsequence = 0
|maxclassrepeat = 0
|gecoscheck = 0
|dictcheck = 1
|usercheck = 1
|usersubstr = 0
|enforcing = 1
|retry = 1
END
end

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

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

it do
is_expected.to contain_file('pwquality.conf.d').with(
'ensure' => 'directory',
'path' => '/etc/security/pwquality.conf.d',
'owner' => 'root',
'group' => 'root',
'mode' => '0755',
'purge' => true,
'recurse' => true,
'ignore' => nil,
)
end

package_name.sort.each do |pkg|
it { is_expected.to contain_file('pwquality.conf').that_requires("Package[#{pkg}]") }
it { is_expected.to contain_file('pwquality.conf.d').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('pwquality.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('pwquality.conf').with_source('puppet:///pam/unit_tests.erb') }
it { is_expected.to contain_file('pwquality.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('pwquality.conf').with_mode('0242') }
end

context 'with config_d_dir set to a valid string' do
let(:params) { { config_d_dir: '/testing.d' } }

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

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

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

context 'with purge_config_d_dir set to a valid boolean false' do
let(:params) { { purge_config_d_dir: false } }

it { is_expected.to contain_file('pwquality.conf.d').with_purge(false) }
it { is_expected.to contain_file('pwquality.conf.d').with_recurse(false) }

context 'with purge_config_d_dir_ignore set to glob pattern' do
let(:params) { { purge_config_d_dir: true, purge_config_d_dir_ignore: '{foo,bar}.conf' } }

it { is_expected.to contain_file('pwquality.conf.d').with_ignore('{foo,bar}.conf') }
end

context 'with purge_config_d_dir_ignore set to array' do
let(:params) { { purge_config_d_dir: true, purge_config_d_dir_ignore: ['foo.conf', 'bar.conf'] } }

it { is_expected.to contain_file('pwquality.conf.d').with_ignore(['foo.conf', 'bar.conf']) }
end

context 'when non-default parameters passed' do
let(:params) do
{
difok: 0,
minlen: 10,
dcredit: 1,
ucredit: 2,
lcredit: 3,
ocredit: 4,
minclass: 5,
maxrepeat: 6,
maxsequence: 7,
maxclassrepeat: 8,
gecoscheck: 9,
dictcheck: 10,
usercheck: 11,
usersubstr: 12,
enforcing: 13,
badwords: ['foo', 'bar'],
dictpath: '/etc/dict',
retry: 14,
enforce_for_root: true,
local_users_only: true,
}
end
let(:content) do
<<-END.gsub(%r{^\s+\|}, '')
|# This file is being maintained by Puppet.
|# DO NOT EDIT
|#
|difok = 0
|minlen = 10
|dcredit = 1
|ucredit = 2
|lcredit = 3
|ocredit = 4
|minclass = 5
|maxrepeat = 6
|maxsequence = 7
|maxclassrepeat = 8
|gecoscheck = 9
|dictcheck = 10
|usercheck = 11
|usersubstr = 12
|enforcing = 13
|badwords = foo bar
|dictpath = /etc/dict
|retry = 14
|enforce_for_root
|local_users_only
END
end

it { is_expected.to contain_file('pwquality.conf').with_content(content) }
end
end
end
end
end
Loading
Loading