Commit 42bd36db authored by Fabien Combernous's avatar Fabien Combernous

Merge branch '98-add-task-create_admin' into 'master'

Resolve "Add task create_admin and remove parameter enable_manage_admins"

Closes #98

See merge request adullact/puppet-freeipa!99
parents b751d265 7658f979
Pipeline #6484 canceled with stages
in 4 minutes and 13 seconds
......@@ -2,6 +2,7 @@ fixtures:
repositories:
stdlib: 'https://github.com/puppetlabs/puppetlabs-stdlib.git'
epel: 'https://github.com/stahnma/puppet-module-epel.git'
ruby_task_helper: 'https://github.com/puppetlabs/puppetlabs-ruby_task_helper.git'
yumrepo_core:
repo: 'https://github.com/puppetlabs/puppetlabs-yumrepo_core.git'
puppet_version: ">= 6.0.0"
......@@ -43,7 +43,7 @@ acceptance with puppet5:
BEAKER_debug: 'true '
RBENV_VERSION: '2.5.1'
script:
- bundle exec rake beaker:default
- bundle exec rake spec_prep beaker:default
tags:
- puppet-tests
except:
......@@ -58,7 +58,7 @@ acceptance with puppet6:
BEAKER_debug: 'true '
RBENV_VERSION: '2.5.1'
script:
- bundle exec rake beaker:default
- bundle exec rake spec_prep beaker:default
tags:
- puppet-tests
except:
......
......@@ -32,3 +32,5 @@ Gemfile:
- gem: 'rspec'
- gem: 'rake'
- gem: 'beaker-vagrant'
- gem: 'bolt'
- gem: 'beaker-task_helper'
......@@ -43,6 +43,8 @@ group :development do
gem "rspec", require: false
gem "rake", require: false
gem "beaker-vagrant", require: false
gem "bolt", require: false
gem "beaker-task_helper", require: false
end
puppet_version = ENV['PUPPET_GEM_VERSION']
......
......@@ -43,15 +43,13 @@ Versions are given in `metadata.json` file.
### How does the module work.
Usually with a module, the desired state is described. If a value of parameter is changed, then during the next puppet run the node is modified to reach the desired state.
The version 3.x is a starting work to reach the target. But, the module is more an idempotent installer of FreeIPA.
So, to ensure that desired state described in code is applied on the node, puppet needs to login to kerberos. Puppet uses a fixed account `admin` to do this. It is possible to set the password of this account with parameter `freeipa::puppet_admin_password`. If `freeipa::enable_manage_admins` is true, the accounts of humans administrators are managed with hash `freeipa::humanadmins`. If you modify `freeipa::humanadmins`, next puppet run will take care to update the admins users on master node. The replication will to the job on replicas.
But, the module is more an idempotent installer of FreeIPA. So changing a value of parameter does not change the value on the node.
## Usage
### Example usage:
Creating an IPA master, with the WebUI proxied to `https://localhost:8440` and two admin accounts `jdupond` and `mgonzales`.
Creating an IPA master :
```puppet
class {'freeipa':
ipa_role => 'master',
......@@ -65,19 +63,6 @@ class {'freeipa':
enable_hostname => true,
manage_host_entry => true,
install_epel => true,
humanadmins => {
jdupond => {
ensure => 'present',
password => 'secret123',
},
mgonzales => {
ensure => 'present',
password => 'secret456',
},
hzimmer => {
ensure => 'absent',
},
},
}
```
......
......@@ -8,7 +8,6 @@
_Public Classes_
* [`freeipa`](#freeipa): Manages IPA masters, replicas and clients.
* [`freeipa::config::humanadmins`](#freeipaconfighumanadmins): This class manages admin accounts. It will create/give rights to any admin accounts set to be present. It will delete accounts set to be absent.
* [`freeipa::helpers::flushcache`](#freeipahelpersflushcache): Flushcache sss for Debian and RedHat only
* [`freeipa::install::autofs`](#freeipainstallautofs): Installs and start autofs
......@@ -22,9 +21,9 @@ _Private Classes_
* `freeipa::install::server::replica`: Installs freeipa server as replica
* `freeipa::install::sssd`: Install sssd package
**Defined types**
**Tasks**
* [`freeipa::config::humanadmin`](#freeipaconfighumanadmin): From FreeIPA master, creates or deletes admin account in FreeIPA.
* [`create_admin`](#create_admin): Create a new FreeIPA admin account
## Classes
......@@ -32,9 +31,6 @@ _Private Classes_
Parameters
----------
Also, triggers the install of the required dns server packages.
and passed to the IPA installer.
and passed to the IPA installer.
#### Examples
......@@ -53,7 +49,6 @@ class {'freeipa':
enable_hostname => true,
manage_host_entry => true,
install_epel => true,
humanadmins => { foo => { password => 'secret123', ensure => 'present'}, bar => { password => 'secret123', ensure => 'present'} },
}
```
......@@ -106,6 +101,7 @@ Default value: `false`
Data type: `Boolean`
If true, then the parameter '--setup-dns' is passed to the IPA server installer.
Also, triggers the install of the required dns server packages.
Default value: `true`
......@@ -146,6 +142,7 @@ Default value: $puppet_admin_password
Data type: `Boolean`
If true, then the parameter '--hostname' is populated with the parameter 'ipa_server_fqdn'
and passed to the IPA installer.
Default value: `true`
......@@ -154,6 +151,7 @@ Default value: `true`
Data type: `Boolean`
If true, then the parameter '--ip-address' is populated with the parameter 'ip_address'
and passed to the IPA installer.
Default value: `false`
......@@ -321,14 +319,6 @@ Name of the sssdtools package.
Default value: 'sssd-tools'
##### `humanadmins`
Data type: `Freeipa::Humanadmins`
Hash of admin accounts in freeipa. Uses the following schema : Hash[ String[1], Struct[{ password => String[1], Optional[ensure] => Enum['present','absent']}]]
Default value: {}
##### `install_ca`
Data type: `Boolean`
......@@ -337,41 +327,6 @@ If true, then the parameter '--setup-ca' is passed to the IPA server installer (
Default value: `true`
##### `enable_manage_admins`
Data type: `Boolean`
Default value: `true`
### freeipa::config::humanadmins
This class manages admin accounts. It will create/give rights to any admin accounts set to be present. It will delete accounts set to be absent.
#### Examples
#####
```puppet
class { 'freeipa::config::humanadmins' :
humanadmins => {
admin1 => {ensure=>'present', password=>'secreat123'},
admin2 => {ensure=>'absent'},
}
}
```
#### Parameters
The following parameters are available in the `freeipa::config::humanadmins` class.
##### `humanadmins`
Data type: `Freeipa::Humanadmins`
Hash defines desired admins of FreeIPA
### freeipa::helpers::flushcache
Flushcache sss for Debian and RedHat only
......@@ -396,37 +351,49 @@ Installs and start autofs
include freeipa::install::autofs
```
## Defined types
## Tasks
### freeipa::config::humanadmin
### create_admin
From FreeIPA master, creates or deletes admin account in FreeIPA.
Create a new FreeIPA admin account
#### Examples
**Supports noop?** false
#####
#### Parameters
```puppet
freeipa::config::humanadmin { 'myadmin' :
adminsettings => {
password => 'secret123',
ensure => 'present',
}
}
```
##### `operator_login`
#### Parameters
Data type: `String[1]`
FreeIPA login of operator running the task
##### `operator_password`
Data type: `String[1]`
Password of operator running the task
##### `login`
The following parameters are available in the `freeipa::config::humanadmin` defined type.
Data type: `String[1]`
##### `adminsettings`
Login name of created administrator account
Data type: `Freeipa::Humanadmin`
##### `firstname`
Hash of settings for one admin account
Data type: `String[1]`
Options:
First name of created administrator account
##### `lastname`
Data type: `String[1]`
Last name of created administrator account
##### `password`
Data type: `String[8]`
* **:ensure** `Enum['present','absent']`: Desired state
* **:password** `String[1]`: Password of this account
Password of created administrator account
# From FreeIPA master, creates or deletes admin account in FreeIPA.
#
# @summary From FreeIPA master, creates or deletes admin account in FreeIPA.
#
# @example
# freeipa::config::humanadmin { 'myadmin' :
# adminsettings => {
# password => 'secret123',
# ensure => 'present',
# }
# }
#
# @param adminsettings Hash of settings for one admin account
# @option adminsettings [Enum['present','absent']] :ensure Desired state
# @option adminsettings [String[1]] :password Password of this account
#
define freeipa::config::humanadmin(
Freeipa::Humanadmin $adminsettings,
) {
if $facts['iparole'] == 'master' or $freeipa::ipa_role == 'master' {
$_adminname = $name
# forge domain shaped for ldappasswd
$_dc_domain_split = regsubst($freeipa::domain, '([^.]+)\.*', 'dc=\1,', 'G')
$_dc = regsubst($_dc_domain_split, ',$', '')
$_ensure = $adminsettings['ensure'] ? {
Undef => 'present',
default => $adminsettings['ensure'],
}
Exec {
path => '/usr/local/bin/:/bin/:/sbin',
}
case $_ensure {
'present': {
$_adminpassword = $adminsettings['password']
exec { "ipa user-add ${_adminname}":
command => "ipa user-add ${_adminname} --first=${_adminname} --last=${_adminname} ",
unless => "kinit admin -k -t /home/admin/admin.keytab; ipa user-show ${_adminname} | grep login",
}
-> exec { "ipa group-add-member admins --users=${_adminname}":
command => "ipa group-add-member admins --users=${_adminname}",
unless => "kinit admin -k -t /home/admin/admin.keytab; ipa group-show admins | grep ${_adminname}",
}
-> exec { "ldappasswd uid=${_adminname},cn=users,cn=accounts,${_dc}":
command => "ldappasswd -Z -H ldap://localhost -x -D 'cn=Directory Manager' -w '${freeipa::directory_services_password}' -s '${_adminpassword}' 'uid=${_adminname},cn=users,cn=accounts,${_dc}'",
unless => "echo '${_adminpassword}' | kinit ${_adminname}"
}
}
'absent': {
exec { "ipa user-del ${_adminname}":
command => "ipa user-del ${_adminname}",
onlyif => "kinit admin -k -t /home/admin/admin.keytab; ipa user-show ${_adminname}",
}
}
default: { fail("unexpected value ${_ensure}") }
}
} else {
# manage accounts of human admins only on master
# replication will do the job on replicate
}
}
# @summary This class manages admin accounts. It will create/give rights to any admin accounts set to be present. It will delete accounts set to be absent.
#
# @example
# class { 'freeipa::config::humanadmins' :
# humanadmins => {
# admin1 => {ensure=>'present', password=>'secreat123'},
# admin2 => {ensure=>'absent'},
# }
# }
#
# @param humanadmins Hash defines desired admins of FreeIPA
#
class freeipa::config::humanadmins(
Freeipa::Humanadmins $humanadmins,
) {
# Loop through $humanadmins
$humanadmins.each | String $_adminname, Freeipa::Humanadmin $_adminsettings | {
freeipa::config::humanadmin { $_adminname :
adminsettings => $_adminsettings,
}
}
}
......@@ -14,7 +14,6 @@
# enable_hostname => true,
# manage_host_entry => true,
# install_epel => true,
# humanadmins => { foo => { password => 'secret123', ensure => 'present'}, bar => { password => 'secret123', ensure => 'present'} },
# }
#
# Parameters
......@@ -25,16 +24,19 @@
# @param directory_services_password Password which will be passed into the ipa setup's parameter named "--ds-password".
# @param autofs_package_name Name of the autofs package to install if enabled.
# @param client_install_ldaputils If true, then the ldaputils packages are installed if ipa_role is set to client.
# @param configure_dns_server If true, then the parameter '--setup-dns' is passed to the IPA server installer.
# Also, triggers the install of the required dns server packages.
# @param configure_dns_server
# If true, then the parameter '--setup-dns' is passed to the IPA server installer.
# Also, triggers the install of the required dns server packages.
# @param configure_ntp If false, then the parameter '--no-ntp' is passed to the IPA server installer.
# @param custom_dns_forwarders Each element in this array is prefixed with '--forwarder' and passed to the IPA server installer.
# @param principal_usedto_joindomain The principal (usually username) used to join a client or replica to the IPA domain.
# @param password_usedto_joindomain The password for the domain_join_principal.
# @param enable_hostname If true, then the parameter '--hostname' is populated with the parameter 'ipa_server_fqdn'
# and passed to the IPA installer.
# @param enable_ip_address If true, then the parameter '--ip-address' is populated with the parameter 'ip_address'
# and passed to the IPA installer.
# @param enable_hostname
# If true, then the parameter '--hostname' is populated with the parameter 'ipa_server_fqdn'
# and passed to the IPA installer.
# @param enable_ip_address
# If true, then the parameter '--ip-address' is populated with the parameter 'ip_address'
# and passed to the IPA installer.
# @param fixed_primary If true, then the parameter '--fixed-primary' is passed to the IPA installer.
# @param idstart From the IPA man pages: "The starting user and group id number".
# @param install_autofs If true, then the autofs packages are installed.
......@@ -56,7 +58,6 @@
# @param server_install_ldaputils If true, then the ldaputils packages are installed if ipa_role is not set to client.
# @param sssd_package_name Name of the sssd package.
# @param sssdtools_package_name Name of the sssdtools package.
# @param humanadmins Hash of admin accounts in freeipa. Uses the following schema : Hash[ String[1], Struct[{ password => String[1], Optional[ensure] => Enum['present','absent']}]]
# @param install_ca If true, then the parameter '--setup-ca' is passed to the IPA server installer (for replicas)
#
class freeipa (
......@@ -67,7 +68,6 @@ class freeipa (
Stdlib::IP::Address $ip_address,
Stdlib::Fqdn $ipa_master_fqdn,
Stdlib::Fqdn $realm = upcase($domain),
Freeipa::Humanadmins $humanadmins = {},
String $autofs_package_name = 'autofs',
Boolean $client_install_ldaputils = false,
Boolean $configure_dns_server = true,
......@@ -75,7 +75,6 @@ class freeipa (
Array[String] $custom_dns_forwarders = [],
String $principal_usedto_joindomain = 'admin',
String $password_usedto_joindomain = $puppet_admin_password,
Boolean $enable_manage_admins = true,
Boolean $enable_hostname = true,
Boolean $enable_ip_address = false,
Boolean $fixed_primary = false,
......
......@@ -108,12 +108,6 @@ class freeipa::install::server {
contain freeipa::helpers::flushcache
if $freeipa::enable_manage_admins and $freeipa::humanadmins.length > 0 {
contain freeipa::config::keytab
class {'freeipa::config::humanadmins':
humanadmins => $freeipa::humanadmins,
}
}
} else {
fail ("to change ipa_role from '${facts['iparole']}' to '${freeipa::ipa_role}' is not supported.")
}
......
require 'spec_helper_acceptance'
describe 'class freeipa' do
context 'with ipa_role master and no humanadmins defined' do
context 'with ipa_role master' do
hosts_as('master').each do |master|
pp = <<-EOS
class { 'freeipa':
......@@ -14,11 +14,9 @@ describe 'class freeipa' do
ip_address => '10.10.10.35',
enable_ip_address => true,
enable_hostname => true,
enable_manage_admins => true,
manage_host_entry => true,
install_epel => true,
ipa_master_fqdn => 'ipa-server-1.example.lan',
humanadmins => {},
}
EOS
......@@ -35,49 +33,6 @@ describe 'class freeipa' do
end
end
context 'with ipa_role master and some humanadmins defined' do
hosts_as('master').each do |master|
pp = <<-EOS
class { 'freeipa':
ipa_role => 'master',
domain => 'example.lan',
ipa_server_fqdn => 'ipa-server-1.example.lan',
puppet_admin_password => 's^ecr@et.ea;R/O*=?j!.QsAu+$',
directory_services_password => 's^ecr@et.ea;R/O*=?j!.QsAu+$',
install_ipa_server => true,
ip_address => '10.10.10.35',
enable_ip_address => true,
enable_hostname => true,
enable_manage_admins => true,
manage_host_entry => true,
install_epel => true,
ipa_master_fqdn => 'ipa-server-1.example.lan',
humanadmins => {
foo => {
ensure => 'present',
password => 's^ecr@et.ea;R/O*=?j!.QsAu+$',
},
bar => {
password => 's^ecr@et.ea;R/O*=?j!.QsAu+$',
ensure => 'present',
},
},
}
EOS
it 'creates humanadmins without error' do
apply_manifest_on(master, pp, catch_failures: true)
end
it 'creates humanadmins idempotently' do
apply_manifest_on(master, pp, catch_changes: true)
end
describe command('ipactl status') do
its(:exit_status) { is_expected.to be 0 }
end
end
end
context 'with ipa_role replica' do
hosts_as('replica').each do |replica|
it 'applies idempotently' do
......@@ -236,70 +191,4 @@ describe 'class freeipa' do
end
end
end
context 'update and delete on humain admins accounts' do
hosts_as('master').each do |master|
it 'kinit for account foo with old password is expected to work' do
pp = <<-EOS
exec { 'kinit foo':
path => '/bin/',
command => 'echo "s^ecr@et.ea;R/O*=?j!.QsAu+$" | kinit foo',
}
EOS
apply_manifest_on(master, pp, catch_failures: true)
end
it 'updates password account for foo and drops account for bar' do
pp = <<-EOS
class { 'freeipa':
ipa_role => 'master',
domain => 'example.lan',
ipa_server_fqdn => 'ipa-server-1.example.lan',
puppet_admin_password => 's^ecr@et.ea;R/O*=?j!.QsAu+$',
directory_services_password => 's^ecr@et.ea;R/O*=?j!.QsAu+$',
install_ipa_server => true,
ip_address => '10.10.10.35',
enable_ip_address => true,
enable_hostname => true,
enable_manage_admins => true,
manage_host_entry => true,
install_epel => true,
ipa_master_fqdn => 'ipa-server-1.example.lan',
humanadmins => {
foo => {
ensure => 'present',
password => 'newsecr@et',
},
bar => {
ensure => 'absent',
},
},
}
EOS
apply_manifest_on(master, pp, catch_failures: true)
apply_manifest_on(master, pp, catch_changes: true)
end
it 'kinit for account foo with new password and expected to work' do
pp = <<-EOS
exec { 'kinit foo':
path => '/bin/',
command => 'echo "newsecr@et" | kinit foo',
}
EOS
apply_manifest_on(master, pp, catch_failures: true)
end
it 'kinit for deleted account bar and expected to fail' do
pp = <<-EOS
exec { 'kinit bar':
path => '/bin/',
command => 'echo "s^ecr@et.ea;R/O*=?j!.QsAu+$" | kinit bar',
}
EOS
apply_manifest_on(master, pp, expect_failures: true)
end
end
end
end
require 'spec_helper_acceptance'
require 'beaker-task_helper/inventory'
require 'bolt_spec/run'
describe 'create_admin task' do
include Beaker::TaskHelper::Inventory
include BoltSpec::Run
def bolt_config
{ 'modulepath' => File.join(File.dirname(File.expand_path(__FILE__)), '../', 'fixtures', 'modules') }
end
def bolt_inventory
hosts_to_inventory
end
it 'creates admin account' do
# rubocop:disable Style/BracesAroundHashParameters
result = run_task(
'freeipa::create_admin',
'master',
{ 'operator_login' => 'admin', 'operator_password' => 's^ecr@et.ea;R/O*=?j!.QsAu+$', 'login' => 'jaimarre', 'firstname' => 'Jean', 'lastname' => 'Aimarre', 'password' => 'adminsecret' }
)
# rubocop:enable Style/BracesAroundHashParameters
expect(result.first).to include('status' => 'success')
end
end
require 'spec_helper'
describe 'freeipa::config::humanadmins' do
let(:params) do
{
humanadmins: {
admin1: {
ensure: 'present',
password: 'secret123'
}
}
}
end
on_supported_os.each do |os, os_facts|
context "on #{os}" do
let(:pre_condition) do
manifest = <<-EOS
class{ 'freeipa' :
ipa_role => 'master',
ipa_master_fqdn => 'master.example.lan',
ipa_server_fqdn => 'foo.example.lan',
domain => 'example.lan',
password_usedto_joindomain => 'foobartest',
puppet_admin_password => 'foobartest',
directory_services_password => 'foobartest',
ip_address => '10.10.10.35',
enable_manage_admins => false,
}
EOS
manifest
end
let(:facts) { os_facts }
it { is_expected.to compile }
end
end
end
......@@ -15,7 +15,6 @@ describe 'freeipa::install' do
puppet_admin_password => 'foobartest',
directory_services_password => 'foobartest',
ip_address => '10.10.10.35',
humanadmins => { foo => { password => 'vagrant123', ensure => 'present'}, bar => { password => 'vagrant123', ensure => 'present'} },
}
EOS
manifest
......
require 'spec_helper'
describe 'freeipa::config::humanadmin' do
let(:title) { 'admin1' }
let(:params) do
{
adminsettings: {
ensure: 'present',
password: 'secret123'
}
}
end
on_supported_os.each do |os, os_facts|
context "on #{os}" do
let(:pre_condition) do
manifest = <<-EOS
class{ 'freeipa' :
ipa_role => 'master',
ipa_master_fqdn => 'master.example.lan',
ipa_server_fqdn => 'foo.example.lan',
domain => 'example.lan',
password_usedto_joindomain => 'foobartest',
puppet_admin_password => 'foobartest',
directory_services_password => 'foobartest',
ip_address => '10.10.10.35',
enable_manage_admins => false,
}
EOS
manifest
end
let(:facts) { os_facts }
it { is_expected.to compile }
end
end
end
......@@ -3,6 +3,9 @@ require 'beaker-puppet'
require 'beaker/puppet_install_helper'
require 'beaker/module_install_helper'
require 'bolt/pal'
Bolt::PAL.load_puppet
run_puppet_install_helper
install_module_on(hosts)
install_module_dependencies_on(hosts)
......
require 'spec_helper'
describe 'Freeipa::Humanadmin' do
humanadmin = {
'ensure' => 'present',
'password' => 'secret123'
}
it { is_expected.to allow_value(humanadmin) }
end
require 'spec_helper'
describe 'Freeipa::Humanadmins' do
humanadmins = {
'admin1' => {
'ensure' => 'present',
'password' => 'secret123'
},
'admin2' => {
'password' => 'secret123'
},
'admin3' => {
'ensure' => 'absent'
}
}
it { is_expected.to allow_value(humanadmins) }
end
{
"puppet_task_version": 1,
"supports_noop": false,
"description": "Create a new FreeIPA admin account",
"parameters": {
"operator_login": {
"description": "FreeIPA login of operator running the task",
"type": "String[1]"
},
"operator_password": {
"description": "Password of operator running the task",
"type": "String[1]"
},
"login": {
"description": "Login name of created administrator account",
"type": "String[1]"
},
"firstname": {
"description": "First name of created administrator account",
"type": "String[1]"
},
"lastname": {
"description": "Last name of created administrator account",
"type"