diff --git a/manifests/init.pp b/manifests/init.pp index c11e94e..e361b6e 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -35,6 +35,9 @@ # @param manage_pwquality # Controls whether to manage pwquality.conf and pwquality.conf.d # +# @param manage_pwhistory +# Controls whether to manage pwhistory.conf and pwhistory.conf.d +# # @param package_name # String or Array of packages providing the pam functionality. If undef, # parameter is set based on the OS version. @@ -211,6 +214,7 @@ Boolean $limits_fragments_hiera_merge = false, Boolean $manage_faillock = false, Boolean $manage_pwquality = false, + Boolean $manage_pwhistory = false, Array $pam_d_login_oracle_options = [], Stdlib::Absolutepath $pam_d_login_path = '/etc/pam.d/login', String $pam_d_login_owner = 'root', @@ -307,6 +311,10 @@ include pam::pwquality } + if $manage_pwhistory { + include pam::pwhistory + } + if $manage_nsswitch { include nsswitch } diff --git a/manifests/pwhistory.pp b/manifests/pwhistory.pp new file mode 100644 index 0000000..518c22c --- /dev/null +++ b/manifests/pwhistory.pp @@ -0,0 +1,64 @@ +# @summary Manages pwhistory.conf settings. +# +# This class configures the /etc/security/pwhistory.conf file. +# +# @param config_file +# Path to the pwhistory.conf file. Defaults to '/etc/security/pwhistory.conf'. +# @param config_file_owner +# Owner of the pwhistory.conf file. Defaults to 'root'. +# @param config_file_group +# Group of the pwhistory.conf file. Defaults to 'root'. +# @param config_file_mode +# File mode for pwhistory.conf. Defaults to '0644'. +# @param config_file_source +# Optional: Specifies a source file for pwhistory.conf. If set, ignores template. +# @param config_file_template +# Optional: Specifies the template to use for pwhistory.conf. Defaults to 'pam/pwhistory.conf.erb'. +# @param remember +# The number of old passwords to remember. This value will be written to pwhistory.conf. +# If undef, the 'remember' option will be commented out in the generated config. +# @param enforce_for_root +# Boolean to enforce password history for the root user. If true, 'enforce_for_root' +# will be enabled in the config. If false or undef, it will be commented out. +# @param debug +#   Boolean to enable debugging logs. If true, 'debug' will be enabled in the config. +#   If false or undef, it will be commented out. +# @param retry +#   The number of times to prompt for the password. This value will be written to pwhistory.conf. +#   If undef, the 'retry' option will be commented out in the generated config. +# @param file +#   The directory where the last passwords are kept. This value will be written to pwhistory.conf. +#   If undef, the 'file' option will be commented out in the generated config. +# +class pam::pwhistory ( + Stdlib::Absolutepath $config_file = '/etc/security/pwhistory.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/pwhistory.conf.erb', + Optional[Integer[0]] $remember = undef, + Optional[Boolean] $enforce_for_root = undef, + Optional[Boolean] $debug = undef, + Optional[Integer[1]] $retry = undef, + Optional[Stdlib::Absolutepath] $file = undef, +) { + include pam + + if $config_file_source { + $_config_file_content = undef + } else { + $_config_file_content = template($config_file_template) + } + + file { 'pwhistory.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], + } +} diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 86160a7..5314cf9 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -288,6 +288,16 @@ it { is_expected.to contain_class('pam::pwquality') } end + context 'with manage_pwhistory parameter default value' do + it { is_expected.not_to contain_class('pam::pwhistory') } + end + + context 'with manage_pwhistory parameter set to true' do + let(:params) { { manage_pwhistory: true } } + + it { is_expected.to contain_class('pam::pwhistory') } + end + context 'with manage_nsswitch parameter default value' do it { is_expected.to contain_class('nsswitch') } end diff --git a/spec/classes/pwhistory_spec.rb b/spec/classes/pwhistory_spec.rb new file mode 100644 index 0000000..d3a55f0 --- /dev/null +++ b/spec/classes/pwhistory_spec.rb @@ -0,0 +1,308 @@ +require 'spec_helper' +require 'spec_platforms' + +describe 'pam::pwhistory' 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(:default_content) do + <<-END.gsub(%r{^\s+\|}, '') + |# This file is being maintained by Puppet. + |# DO NOT EDIT + |# + |# Configuration for remembering the last passwords used by a user. + |# + |# Enable the debugging logs. + |# Enabled if option is present. + |# debug + |# + |# root account's passwords are also remembered. + |# Enabled if option is present. + |# enforce_for_root + |# + |# Number of passwords to remember. + |# The default is 10. + |# remember = 10 + |# + |# Number of times to prompt for the password. + |# The default is 1. + |# retry = 1 + |# + |# The directory where the last passwords are kept. + |# The default is /etc/security/opasswd. + |# file = /etc/security/opasswd + END + end + + it { is_expected.to compile.with_all_deps } + it { is_expected.to contain_class('pam') } + + it do + is_expected.to contain_file('pwhistory.conf').with( + 'ensure' => 'file', + 'path' => '/etc/security/pwhistory.conf', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + 'content' => default_content, + ) + end + + package_name.sort.each do |pkg| + it { is_expected.to contain_file('pwhistory.conf').that_requires("Package[#{pkg}]") } + end + + context 'with config_file set to a valid path' do + let(:params) { { config_file: '/custom/path.conf' } } + + it { is_expected.to contain_file('pwhistory.conf').with_path('/custom/path.conf') } + end + + context 'with config_file_source set to a valid string' do + let(:params) { { config_file_source: 'puppet:///modules/pam/custom.conf' } } + + it { is_expected.to contain_file('pwhistory.conf').with_source('puppet:///modules/pam/custom.conf') } + it { is_expected.to contain_file('pwhistory.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('pwhistory.conf').with_mode('0242') } + end + + context 'with config_file_owner set to a valid string' do + let(:params) { { config_file_owner: 'user1' } } + + it { is_expected.to contain_file('pwhistory.conf').with_owner('user1') } + end + + context 'with config_file_group set to a valid string' do + let(:params) { { config_file_group: 'group1' } } + + it { is_expected.to contain_file('pwhistory.conf').with_group('group1') } + end + + context 'when all parameters are set' do + let(:params) do + { + remember: 5, + enforce_for_root: true, + debug: true, + retry: 2, + file: '/custom/opasswd', + } + end + + let(:content) do + <<-END.gsub(%r{^\s+\|}, '') + |# This file is being maintained by Puppet. + |# DO NOT EDIT + |# + |# Configuration for remembering the last passwords used by a user. + |# + |# Enable the debugging logs. + |# Enabled if option is present. + |debug + |# + |# root account's passwords are also remembered. + |# Enabled if option is present. + |enforce_for_root + |# + |# Number of passwords to remember. + |# The default is 10. + |remember = 5 + |# + |# Number of times to prompt for the password. + |# The default is 1. + |retry = 2 + |# + |# The directory where the last passwords are kept. + |# The default is /etc/security/opasswd. + |file = /custom/opasswd + END + end + + it { is_expected.to contain_file('pwhistory.conf').with_content(content) } + end + + context 'when remember is set' do + let(:params) { { remember: 7 } } + + let(:content) do + <<-END.gsub(%r{^\s+\|}, '') + |# This file is being maintained by Puppet. + |# DO NOT EDIT + |# + |# Configuration for remembering the last passwords used by a user. + |# + |# Enable the debugging logs. + |# Enabled if option is present. + |# debug + |# + |# root account's passwords are also remembered. + |# Enabled if option is present. + |# enforce_for_root + |# + |# Number of passwords to remember. + |# The default is 10. + |remember = 7 + |# + |# Number of times to prompt for the password. + |# The default is 1. + |# retry = 1 + |# + |# The directory where the last passwords are kept. + |# The default is /etc/security/opasswd. + |# file = /etc/security/opasswd + END + end + + it { is_expected.to contain_file('pwhistory.conf').with_content(content) } + end + + context 'when enforce_for_root is true' do + let(:params) { { enforce_for_root: true } } + + let(:content) do + <<-END.gsub(%r{^\s+\|}, '') + |# This file is being maintained by Puppet. + |# DO NOT EDIT + |# + |# Configuration for remembering the last passwords used by a user. + |# + |# Enable the debugging logs. + |# Enabled if option is present. + |# debug + |# + |# root account's passwords are also remembered. + |# Enabled if option is present. + |enforce_for_root + |# + |# Number of passwords to remember. + |# The default is 10. + |# remember = 10 + |# + |# Number of times to prompt for the password. + |# The default is 1. + |# retry = 1 + |# + |# The directory where the last passwords are kept. + |# The default is /etc/security/opasswd. + |# file = /etc/security/opasswd + END + end + + it { is_expected.to contain_file('pwhistory.conf').with_content(content) } + end + + context 'when debug is true' do + let(:params) { { debug: true } } + + let(:content) do + <<-END.gsub(%r{^\s+\|}, '') + |# This file is being maintained by Puppet. + |# DO NOT EDIT + |# + |# Configuration for remembering the last passwords used by a user. + |# + |# Enable the debugging logs. + |# Enabled if option is present. + |debug + |# + |# root account's passwords are also remembered. + |# Enabled if option is present. + |# enforce_for_root + |# + |# Number of passwords to remember. + |# The default is 10. + |# remember = 10 + |# + |# Number of times to prompt for the password. + |# The default is 1. + |# retry = 1 + |# + |# The directory where the last passwords are kept. + |# The default is /etc/security/opasswd. + |# file = /etc/security/opasswd + END + end + + it { is_expected.to contain_file('pwhistory.conf').with_content(content) } + end + + context 'when retry is set' do + let(:params) { { retry: 3 } } + + let(:content) do + <<-END.gsub(%r{^\s+\|}, '') + |# This file is being maintained by Puppet. + |# DO NOT EDIT + |# + |# Configuration for remembering the last passwords used by a user. + |# + |# Enable the debugging logs. + |# Enabled if option is present. + |# debug + |# + |# root account's passwords are also remembered. + |# Enabled if option is present. + |# enforce_for_root + |# + |# Number of passwords to remember. + |# The default is 10. + |# remember = 10 + |# + |# Number of times to prompt for the password. + |# The default is 1. + |retry = 3 + |# + |# The directory where the last passwords are kept. + |# The default is /etc/security/opasswd. + |# file = /etc/security/opasswd + END + end + + it { is_expected.to contain_file('pwhistory.conf').with_content(content) } + end + + context 'when file is set' do + let(:params) { { file: '/var/log/old_passwords' } } + + let(:content) do + <<-END.gsub(%r{^\s+\|}, '') + |# This file is being maintained by Puppet. + |# DO NOT EDIT + |# + |# Configuration for remembering the last passwords used by a user. + |# + |# Enable the debugging logs. + |# Enabled if option is present. + |# debug + |# + |# root account's passwords are also remembered. + |# Enabled if option is present. + |# enforce_for_root + |# + |# Number of passwords to remember. + |# The default is 10. + |# remember = 10 + |# + |# Number of times to prompt for the password. + |# The default is 1. + |# retry = 1 + |# + |# The directory where the last passwords are kept. + |# The default is /etc/security/opasswd. + |file = /var/log/old_passwords + END + end + + it { is_expected.to contain_file('pwhistory.conf').with_content(content) } + end + end + end +end diff --git a/templates/pwhistory.conf.erb b/templates/pwhistory.conf.erb new file mode 100644 index 0000000..7890a64 --- /dev/null +++ b/templates/pwhistory.conf.erb @@ -0,0 +1,44 @@ +# This file is being maintained by Puppet. +# DO NOT EDIT +# +# Configuration for remembering the last passwords used by a user. +# +# Enable the debugging logs. +# Enabled if option is present. +<% if @debug == true -%> +debug +<% else -%> +# debug +<% end -%> +# +# root account's passwords are also remembered. +# Enabled if option is present. +<% if @enforce_for_root == true -%> +enforce_for_root +<% else -%> +# enforce_for_root +<% end -%> +# +# Number of passwords to remember. +# The default is 10. +<% if @remember != nil -%> +remember = <%= @remember %> +<% else -%> +# remember = 10 +<% end -%> +# +# Number of times to prompt for the password. +# The default is 1. +<% if @retry != nil -%> +retry = <%= @retry %> +<% else -%> +# retry = 1 +<% end -%> +# +# The directory where the last passwords are kept. +# The default is /etc/security/opasswd. +<% if @file != nil -%> +file = <%= @file %> +<% else -%> +# file = /etc/security/opasswd +<% end -%>