Compare commits

...

98 Commits

Author SHA1 Message Date
Thomas Woerner
5dd5faccb0 New utils script to update module docs
Usage: sh utils/gen_modules_docs.sh
2019-07-23 10:01:59 +02:00
Thomas Woerner
040d95c519 utils/build-galaxy-release.sh: New build script for galaxy release
This script will to the following steps:

- Fix the galaxy release in galaxy.yml
- Remove emacs backup files
- Link module_utils, modules and action_plugins from roles to plugins/..
- Fix import prefix for module_utils
- Fix module prefixes in playbooks and example playbooks
- Build release using mazer
- Clean up again
2019-07-23 10:00:27 +02:00
Thomas Woerner
dc8964134b galaxy.yml: Use A.B.C as version, use new build script for release 2019-07-23 09:46:23 +02:00
Thomas Woerner
ceb6f41407 ipareplica_prepare: Update module documentation
The documentation of the module paramaters have been updated. The parameter
list has been updated and all parameters are providing a description and
the required argument has been updated to reflect current setting in the
module.

This one was missed in the big module update.
2019-07-23 09:27:10 +02:00
Thomas Woerner
d2e2fd6fdb Update READEME.md: Update galaxy information 2019-07-23 09:19:10 +02:00
Thomas Woerner
91e69e3dcc ipa[server,replica]: Set _packages_adtrust for Ubuntu
freeipa-server-trust-ad has been added to the package list for adtrust for
Ubuntu.
2019-07-23 08:40:47 +02:00
Thomas Woerner
743216b0db ipaclient: Fix typo in dnsok assignment for ipaclient_setup_nss
result_ipaclient_test.dnso has been used instead of
result_ipaclient_test.dnsok in the assignment of dnsok.
2019-07-22 18:52:23 +02:00
Thomas Woerner
7e8145e43a ipareplica_setup_custodia: create_replica only available in newer releases
The check for the existence of get_custodia_instance in custodiainstance
is not sufficient for the use od create_replica in CustodiaInstance. A new
check for create_replica in CustodiaInstance has been added.
2019-07-22 18:52:23 +02:00
Thomas Woerner
fbf6f23590 ipaserver_test: Initialize value from options.zonemgr
In the test of options.zonemgr the value has been be checked uninitialized.
2019-07-22 18:52:23 +02:00
Thomas Woerner
82f8dae540 ipaclient_setup_nss: paths.GETENT is not available before freeipa-4.6.90.pre1
Fallback for older releases has been added to use '/usr/bin/getent' if
paths.GETENT is not defined.
2019-07-22 18:52:23 +02:00
Thomas Woerner
184f6f08da iipaclient: RawConfigParser is not always provided by six.moves.configparser
six.moves.configparser does not always provide RawConfigParser.
2019-07-22 18:52:23 +02:00
Thomas Woerner
aff6d9005c ipareplica/tasks/install: Add space for ipareplica_pki_config_override 2019-07-22 18:52:23 +02:00
Thomas Woerner
830da6367e ipa[server,replica,client]: Update module documentation
The documentation of the module paramaters have been updated. The parameter
list has been updated and all parameters are providing a description and
the required argument has been updated to reflect current setting in the
modules.
2019-07-22 18:52:23 +02:00
Thomas Woerner
5d2736b144 ansible_ipa_server: Initialize .external_cert_files and .dirsrv_cert_files
These are set in the prepare step and used in the ds_init_info fuction.
2019-07-22 18:52:23 +02:00
Thomas Woerner
2b2fe198c5 ipaserver_prepare: Initialize options._subject_base and options._ca_subject
These are set by ca.install_check, but flake8 does not know about this.
2019-07-22 18:52:23 +02:00
Thomas Woerner
186d2373e6 ansible_ipa_replica: Dropped unused ds_init_info and krb_init_info functions
These functions are not used and therefore these functions have been
removed.
2019-07-22 18:52:23 +02:00
Thomas Woerner
c1b47ffe1b ipa[server,replica,client]: Update import and export of global module utils
All module_utils are now providing the __all__ structure. Alse the imports
in the modules have been updated to only import freeipa sturctures from
module_utils.
2019-07-22 18:52:23 +02:00
Thomas Woerner
2ba2b3cfee ipa[server,replica,client]: flake8 and pylint fixes
These are white space and line length changes to calm down pylint and flake8.
2019-07-22 18:52:15 +02:00
Thomas Woerner
bcd5c74f0d Update README.md 2019-07-19 16:43:22 +02:00
Thomas Woerner
f53254fe3d Update README.md 2019-07-19 13:41:20 +02:00
Thomas Woerner
5b2debfcea Update README.md 2019-07-19 13:30:18 +02:00
Thomas Woerner
829ffdb225 Update README.md: Add information about RPM package and galaxy. 2019-07-19 13:28:43 +02:00
Thomas Woerner
696e9ff500 Update README.md: Update lik for SERVER readme 2019-07-17 21:42:26 +02:00
Thomas Woerner
f9066fa55b ipaserver: Properly set settings related to pkcs12 files
Use and generation of dirsrv_pkcs12_info, http_pkcs12_info and
pkinit_pkcs12_info has been fixed in:

- ipaserver_setup_ds
- ipaserver_setup_http
- ipaserver_test
2019-07-17 19:39:43 +02:00
Thomas Woerner
03688da522 ipaserver_test: Properly initialize pin and cert_name variables
The variables dirsrv_cert_name, dirsrv_pin, http_cert_name, http_pin,
pkinit_cert_name and pkinit_pin have not been initialized properly.
2019-07-17 19:37:36 +02:00
Thomas Woerner
9d088983d9 ipaserver_setup_dns: Properly set ip_addresses, domain and realm
The parameters ip_addresses, domain and realm have not been properly set
for the setup of dns if _setup_dns as not enabled.
2019-07-17 19:34:42 +02:00
Thomas Woerner
b0da219bf5 module_utils/ansible_ipa_replica: Initialize skip_schema_check to None
This setting can not be set for replica deployments, but needs to be
initilized.
2019-07-17 19:30:32 +02:00
Thomas Woerner
8f8d65cab9 ipareplica_setup_ds: Do not trace back for ScriptError and RuntimeError 2019-07-17 19:29:09 +02:00
Thomas Woerner
18a07e2294 ipareplica_prepare: Fail with proper error messages
Some errors have been printed to the error log only and fail_json only got
an empty string as error message. This made the causes of the errors hard
to get.
2019-07-17 19:25:25 +02:00
Thomas Woerner
14cb100a91 ipareplica_prepare: Properly initialize pin and cert_name variables
The variables dirsrv_cert_name, dirsrv_pin, http_cert_name, http_pin,
pkinit_cert_name and pkinit_pin have not been initialized properly.
2019-07-17 19:23:59 +02:00
Thomas Woerner
6378d9b1dc ipareplica: Initialize dns.ip_addresses and dns.reverse_zones for dns setup
These two varibles in the dns binding are initialized in the installation
check in the install_check parts of ipareplica_prepare and used later on
in the dns configuration in ipareplica_setup_dns.
2019-07-17 19:17:31 +02:00
Thomas Woerner
a3578de4b2 ipareplica: Add support for pki_config_override
There is a new setting for the ipareplica role:

ipareplica_pki_config_override
2019-07-17 19:14:27 +02:00
Thomas Woerner
c045530cd4 ipaclient: Fix description of ipaclient_on_master in ipaclient README
The description of ipaclient_on_master in the ipaclient README was
providing the information that the flag is also used for relicas. This
is not correct and has been removed.
2019-07-17 19:08:49 +02:00
Thomas Woerner
419312c324 ipaclient/library/ipaclient_setup_nss: Add dnsok for no-sssd compatibility code
dnsok has been used unitialized in the compatilbility code without sssd.
2019-07-17 19:08:17 +02:00
Thomas Woerner
2d566825a3 ipa[server,replica,client]: No not use wildcard imports for modules
All module and module_utils scripts have been adapted to be able to only
import the symbols that are really needed and used.
2019-07-17 19:01:26 +02:00
Thomas Woerner
de9d8b50cf ipa[server,replica,client]: pylint fixes 2019-07-17 18:54:20 +02:00
Thomas Woerner
3a4cb6a732 ipa[server,replica,client]: Remove unused variables and wrong doc strings 2019-07-17 18:47:40 +02:00
Thomas Woerner
cb94c34503 ipaserver: Remove unused ipaserver/library/ipaserver.py 2019-07-17 18:01:33 +02:00
Thomas Woerner
a33c832bdf Merge pull request #96 from aniro/master
Fixed wrong path to CheckedIPAddress class
2019-07-17 12:40:41 +02:00
Andrey Shevchenko
fae81d62d7 Fixed wrong path to CheckedIPAddress class 2019-07-16 15:35:39 +02:00
Thomas Woerner
66449a7462 Update ipaclient/README.md: Remove "and replica" from ipaclient_on_master decription 2019-07-16 10:03:12 +02:00
Thomas Woerner
64775884b2 Update README-topology.md: Fix exmple for list of topology segments 2019-07-11 21:57:05 +02:00
Thomas Woerner
a5c43d3fed ipagroup: Fail on member addition/removal from not existing group
If members are added to or removed from a not existing group, an
error is printed.
2019-07-11 20:28:53 +02:00
Thomas Woerner
3ae4fe1cc5 plugins: flake8 fixes to calm down ansible galaxy 2019-07-11 19:56:49 +02:00
Thomas Woerner
1fa1468b85 library/ipaclient_get_otp: Enable force mode for host_add call
When OTP is used for installation of a client or the client part of
a replica and also there is no DNS record for the client, then
ipaclient_get_otp fails in the host_add call.

With the force mode the host_add call will ignore the missing DNS
record and will properly add the host. The host information and also
the DNS record will be updated while deploying the client according
to the given settings.

Fixes: #74 (ipaclient fails when ipaclient_use_otp is true and client ..)
2019-07-11 18:36:47 +02:00
Thomas Woerner
8cd34b4d53 ipaserver_setup_kra: Since 4.7.1 FIRST_MASTER needs to be used
Since 4.7.1 it is needed to use CustodiaModes.FIRST_MASTER instead of
CustodiaModes.MASTER_PEER for the get_custodia_instance.

This has been fixed already in ipaserver_setup_ca and also
ipaserver_setup_custodia, but was missed in ipaserver_setup_kra.

Fixes: #92 (KRA install fails in tasks: [ipaserver : Install - Setup KRA])
2019-07-11 18:32:31 +02:00
Thomas Woerner
e63b5759b3 ipauser exmaple playbooks: More updates 2019-07-09 11:49:50 +02:00
Thomas Woerner
00862d9709 Update README-user.md: Fixed examples, new example for unlocked 2019-07-09 11:46:51 +02:00
Thomas Woerner
50611a042f galaxy.yml: Prepare for release 0.1.5 2019-07-09 10:13:55 +02:00
Thomas Woerner
cf01262b27 ipagroup playbooks: Add names for tasks
ansible-lint does not like to have tasks without names. The comments have
been adapted and transformed into name tags.
2019-07-09 10:05:53 +02:00
Thomas Woerner
0c3d35a577 ipauser playbooks: Add names for tasks
ansible-lint does not like to have tasks without names. The comments have
been adapted and transformed into name tags.
2019-07-09 10:05:41 +02:00
Thomas Woerner
771b0ba029 Update README-user.md: Fixed givenname highlighting 2019-07-09 09:33:38 +02:00
Thomas Woerner
364267f1ab README.md: Add references to new user and group management modules 2019-07-08 23:00:32 +02:00
Thomas Woerner
2afb8c6a2f New group management module
There is a new group management module placed in the plugins folder:

  plugins/modules/ipagroup.py

The group module allows to add, remove, enable, disable, unlock und undelete
groups.

The group module is as compatible as possible to the Ansible upstream
`ipa_group` module, but addtionally offers to add users to a group and also
to remove users from a group.

Here is the documentation for the module:

  README-group.md

New example playbooks have been added:

  playbooks/user/add-groups-to-group.yml
  playbooks/user/add-user-to-group.yml
  playbooks/user/add-group.yml
  playbooks/user/delete-group.yml
2019-07-08 22:55:49 +02:00
Thomas Woerner
a36e8e0876 New user management module
There is a new user management module placed in the plugins folder:

  plugins/modules/ipauser.py

The user module allows to add, remove, enable, disable, unlock und undelete
users.

The user module is as compatible as possible to the Ansible upstream
`ipa_user` module, but addtionally offers to preserve delete, enable,
disable, unlock and undelete users.

Here is the documentation for the module:

  README-user.md

New example playbooks have been added:

  playbooks/user/add-user.yml
  playbooks/user/delete-user.yml
  playbooks/user/enable-user.yml
  playbooks/user/disable-user.yml
  playbooks/user/delete-preserve--user.yml
  playbooks/user/undelete-user.yml
2019-07-08 22:43:09 +02:00
Thomas Woerner
1cb0ac67a2 ansible_freeipa_module: New functions date_format and compare_args_ipa
date_format parses the supported date formats and creates a datetime object.

compare_args_ipa compares generated args with args returned by IPA command
find_ functions.
2019-07-08 22:27:27 +02:00
Thomas Woerner
d2968b2611 ipaserver: Support sync_time changes of 4.8.0
sync_time is not using options anymore, but has two new arguments. These
are ntp_servers and ntp_pool. The options argument is not used anymore.

This requires to use inspect on sync_time to be able to detect if the old
or the new function is available.

The call for get_time_source has been added, but is documented out as the
call is only useful in interactive mode.

ipaserver_test now returns ntp_servers and ntp_pool, which are then used
for ipaserver_setup_ntp.
2019-07-05 17:56:38 +02:00
Thomas Woerner
03d904b7ea ipaclient: Support sync_time changes of 4.8.0
sync_time is not using options anymore, but has two new arguments. These
are ntp_servers and ntp_pool. The options argument is not used anymore.

This requires to use inspect on sync_time to be able to detect if the old
or the new function is available.

The call for get_time_source has been added, but is documented out as the
call is only useful in interactive mode.

ipaclient_test now returns ntp_servers and ntp_pool, which are then used
for ipaclient_setup_ntp.
2019-07-05 17:53:32 +02:00
Thomas Woerner
7a5fadfc8d ipaclient/action_plugins/ipaclient_get_otp: Enhanced error reporting
If kinit_password call failed because of wrong password or even because
kinit was not found, there was a very unspecific error message. Now these
errors will be properly reported.

Fixes: RHBZ#1727277
2019-07-05 13:05:04 +02:00
Thomas Woerner
45b2648af2 roles/ipaclient/README.md: OTP needs kinit on controller
Add Information about needed /usr/bin/kinit on the controller when OTP is used
2019-07-05 11:59:14 +02:00
Thomas Woerner
27fb3e1bb7 README.md: OTP needs kinit on controller
Add Information about needed /usr/bin/kinit on the controller when OTP is used
2019-07-05 11:57:11 +02:00
Thomas Woerner
115f96d0be ipaserver_prepare: Properly report error, do show trace back
The raises of RuntimeError, ValueError and ScriptError are currently not
properly handled in ipaserver_prepare. This results in a trace back error
shown in Ansible instead of only showing the error message.

This happened for example if a nameserver is in /etc/resolv.conf that is
not reachable.
2019-07-02 13:43:15 +02:00
Thomas Woerner
da2631d923 ipatopology modules: Use ipaadmin_ prefix for principal and password
The use of password will conflict with the user password setting and is
not really descriptive. ipaadmin_principal and ipaadmin_password are also
used in the roles.
2019-07-01 14:48:42 +02:00
Thomas Woerner
c708ef781e New tests folder
There are currently only external signed CA tests:

external-signed-ca-with-automatic-copy
external-signed-ca-with-manual-copy
2019-06-27 13:02:11 +02:00
Thomas Woerner
e7de098790 README: Update information about external signed CA 2019-06-27 12:45:25 +02:00
Thomas Woerner
45d8008033 ipaserver: Add support for external signed CA
This adds support for the --external-ca option to ipaserver. Lots of
additional tests and checks from ServerInstallInterface.__init__ have
been added to ipaserver_test. Also duplicate tests cna checks have been
removed.

Installer settings in ansible_ipa_server module_util are now also set
to the defaults that are used in Installable, ServerInstallInterface,
ServerMasterInstall, ADTrustInstallInterface and Uninstall.

The /root/ipa.csr file generated on the node in ca.install_step_0 will
be copied to the controller as "{{ inventory_hostname }}-ipa.csr".

The new task file copy_external_cert.yml has been added to copy the
generated certificate defined in ipaserver_external_cert_files to the node
to continue with ca.install_step_1.

The tasks/install.yml file has been adapted to make sure that the steps
that will be done in step two will be skipped after step one has been
done.
2019-06-27 12:06:56 +02:00
Thomas Woerner
5f580b5152 ipa[server,replica,client]: Remove tasks folder prefix for include_tasks
This is not needed and will calm down ansible-lint, which is not able
to handle the extra tasks folder prefix.
2019-06-26 18:20:41 +02:00
Thomas Woerner
7e42102aa5 ipa[server,replica,client]: RHEL-8 specific vars files
These vars files are providing the module names used with the Ansible
package module to install the needed RPM packages.
2019-06-26 16:03:54 +02:00
Thomas Woerner
3a3b4cb397 ansible_ipa_replica: installer.add_sids should default to False
The general setting of installer.add_sids was not correct and has been
fixed.
2019-06-25 16:01:42 +02:00
Thomas Woerner
5afd889023 ipareplica_krb_enable_ssl: Initialize krb.pkcs12_info and krb.master_fqdn
These two settings are not set using the krb.init_info method, but used in
krb.enable_ssl.

The configuration of PKINIT fails in IPA 4.7.0 because of the issue
https://pagure.io/freeipa/issue/7655 where auto detection of the
master is not properly working. With the missing setting of krb.master_fqdn
the not workint auto detection has been triggered, which resulted in
failed PKINIT enablement.
2019-06-25 15:52:54 +02:00
Thomas Woerner
5d881a9bf3 ipareplica: Set all needed settings for kra
Some settings for kra have not been correct for kra with the change to
use single Custodia instance in the installer (freeipa 994f71ac8).

These modules have been adapted:

  ipareplica_custodia_import_dm_password
  ipareplica_enable_ipa
  ipareplica_setup_ca
  ipareplica_setup_custodia
  ipareplica_setup_kra
2019-06-25 10:53:07 +02:00
Thomas Woerner
2092220634 ipareplica: Make sure that certmonger picks the right master
This is related to freeipa#0f31564b35aac250456233f98730811560eda664

  During ipa-replica-install, http installation first creates a service
  principal for http/hostname (locally on the soon-to-be-replica), then
  waits for this entry to be replicated on the master picked for the
  install.
  In a later step, the installer requests a certificate for HTTPd. The local
  certmonger first tries the master defined in xmlrpc_uri (which is
  pointing to the soon-to-be-replica), but fails because the service is not
  up yet. Then certmonger tries to find a master by using the DNS and looking
  for a ldap service. This step can pick a different master, where the
  principal entry has not always be replicated yet.
  As the certificate request adds the principal if it does not exist, we can
  end by re-creating the principal and have a replication conflict.

  The replication conflict later causes kerberos issues, preventing
  from installing a new replica.

  The proposed fix forces xmlrpc_uri to point to the same master as the one
  picked for the installation, in order to make sure that the master already
  contains the principal entry.

  https://pagure.io/freeipa/issue/7041
2019-06-21 12:26:01 +02:00
Thomas Woerner
ca4518a623 ansible_ipa_client: Always set options.unattended
This has not been done so far in the ansible_ipa_client, but only in the
modules where it was really needed. But as these places are getting more
with 4.7.90, this setting makes it into the module_utils.
2019-06-21 12:07:36 +02:00
Thomas Woerner
158fdb1876 ipatopologysegment: Use commands, not command
command has been used instead of commands. command is not defined.
2019-06-17 20:33:49 +02:00
Thomas Woerner
c905cdaf02 Update README-topology.md 2019-06-17 18:52:55 +02:00
Thomas Woerner
4378d161bc Update README.md 2019-06-17 18:35:42 +02:00
Thomas Woerner
1009c889b3 Update README.md 2019-06-17 18:34:01 +02:00
Thomas Woerner
56a8acedf0 ipatopologysegment: Allow domain+ca suffix, new state: checked
It is now possible to use domain+ca as suffix, That means that the segment
will be handled for the suffixes domain and also ca.

The new state checked is returning two lists found and not-found. If a
segment exists, the ckecked suffix is added to the found list. If a segment
from suffix is not found, it is added to the not-found list.

New example playbooks have been added:
   playbooks/topology/add-topologysegments.yml
   playbooks/topology/check-topologysegments.yml
   playbooks/topology/delete-topologysegments.yml

The cluster playbook has been extended by the
2019-06-17 18:23:44 +02:00
Thomas Woerner
8ac1a6e590 ipareplica: Add default(omit) for ipaclient role varaibles
To make sure that there will be no issue with undefined output from
ipareplica_test, the default(omit) has been added.
2019-06-17 16:49:14 +02:00
Thomas Woerner
76d436ec0b ipareplica: Use ipareplica_server if set.
The variable has been ignored and was not used. The servers are now
properly set from ipareplica_servers now.
2019-06-17 16:42:37 +02:00
Thomas Woerner
438f09bad9 ipareplica: The dm password is not needed for ipareplica_master_password
The module ipareplica_master_password has been a copy from ipaserver role
and still contained code to read the cache file. This is not needed for
the replica. Therefore there is no need also to provide the dm password
to ipareplica_master_password any more.
2019-06-17 16:40:14 +02:00
Thomas Woerner
0f73362ef5 Merge pull request #60 from dawud/feature/improve_package_installation_tasks
Fixes #17 Improve how tasks manage package installation
2019-06-17 15:49:33 +02:00
Thomas Woerner
2372e5b98d ipaclient: Report error message if ipaclient_get_otp failed
Currently the error message of ipaclient_get_otp is not visble if it failed
due to the use of no_log. The no_log option is needed and useful if the
one-time password has successfully been generated, but is bad if there was
an error while generating the password, for example if a clock skew has been
detected.

There is now a new task to print the error message if ipaclient_get_otp. The
task for ipaclient_get_otp has been marked with "ignore_errors: yes" and
the new task "Install - Report error for OTP generation" will always fail
and only be used if result_ipaclient_get_otp is failed.
2019-06-17 11:14:02 +02:00
Thomas Woerner
50046a7348 ipaclient: Fix test of newly supported ipaadmin_keytab use in ipaclient_join
The check for the ipaadmin_keytab was not using "is defined". Because of this
the playbook processing failed if the variable was not defined.
2019-06-17 10:25:02 +02:00
Thomas Woerner
79d0ac9d47 Update README.md 2019-06-17 09:39:59 +02:00
Thomas Woerner
ca43b427a8 Update README.md 2019-06-17 09:38:10 +02:00
Thomas Woerner
b89112cf81 Update README.md
Fixes #87 (ipareplica README seems to have incorrect info)
2019-06-14 20:13:22 +02:00
Thomas Woerner
215359e377 Update README.md 2019-06-14 19:28:51 +02:00
Thomas Woerner
a79437d39a Update README.md 2019-06-14 19:27:52 +02:00
Thomas Woerner
4829399ef3 Update README.md 2019-06-14 18:26:50 +02:00
Thomas Woerner
e218441c39 Update README.md 2019-06-14 18:18:33 +02:00
Thomas Woerner
8ffe818b7f Update README.md 2019-06-14 18:15:07 +02:00
Thomas Woerner
100b7eabaf ipaclient: Do not fail if ipaadmin_password is not used
This is for example the case if ipaadmin_keytab is used instead without
ipaclient_use_otp.
2019-06-14 17:34:04 +02:00
Thomas Woerner
ac24f9c067 ipaclient_join: Support to use ipaadmin_keytab without ipaclient_use_otp
ipaadmin_keytab has been supported only with with ipaclient_use_otp. But
it can also be used without for ipa-join.

Important is that ipaadmin_keytab needs to be placed on the cliend node
and ipaadmin_keytab needs to be a full path. Otherwise the file will not
be found.
2019-06-14 17:30:53 +02:00
Thomas Woerner
da14fa29bb ipaclient: Use omit (None) for password, keytab, no string length checks
Password and keytab do not need to be set explicitely to an empty string
when they are not set. Also there is no need to have string length checks
in the role tasks.
2019-06-14 17:26:12 +02:00
Thomas Woerner
813d5bbf97 ipaclient_get_otp: Remove ansible_python_interpreter handling
With the deactivation of the Python2/3 test the handling of
ansible_python_interpreter needs to be removed as the setting might
not exist and is not changed in with the Python2/3 test any more.
2019-06-12 11:06:38 +02:00
Thomas Woerner
3de056bc60 ipaclient_test: Fix Python2 decode use with Python3
This is a remain of the Python2 version and has been fixed.

Fixed: #86 (AttributeError: 'str' object has no attribute 'decode')
2019-06-12 11:00:59 +02:00
David Sastre Medina
20e5338ad5 Fixes #17 Improve how tasks manage package installation
The use of squash_actions to invoke a package module, such as “yum”, to
only invoke the module once is deprecated, and will be removed in
Ansible 2.11.
Instead of relying on implicit squashing, tasks should instead supply
the list directly to the name, pkg or package parameter of the module.

See [1] for a reference to the upstream documentation.

The ipa-krb5 and ipa-sssd modules include *_packages variables in both
defaults/ and vars/, additionally, the list of packages in ipa-sssd differs
from one to the other.
Unify list of packages into vars/

[1]: https://docs.ansible.com/ansible/latest/porting_guides/porting_guide_2.7.html#using-a-loop-on-a-package-module-via-squash-actions
2019-06-04 12:42:19 +02:00
120 changed files with 8615 additions and 3594 deletions

153
README-group.md Normal file
View File

@@ -0,0 +1,153 @@
Group module
============
Description
-----------
The group module allows to add, remove, enable, disable, unlock und undelete groups.
The group module is as compatible as possible to the Ansible upstream `ipa_group` module, but addtionally offers to add users to a group and also to remove users from a group.
Features
--------
* Group management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipagroup module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to add groups:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
# Create group ops with gid 1234
- ipagroup:
ipaadmin_password: MyPassword123
name: ops
gidnumber: 1234
# Create group sysops
- ipagroup:
ipaadmin_password: MyPassword123
name: sysops
user:
- pinky
# Create group appops
- ipagroup:
ipaadmin_password: MyPassword123
name: appops
```
Example playbook to add users to a group:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
# Add user member brain to group sysops
- ipagroup:
ipaadmin_password: MyPassword123
name: sysops
action: member
user:
- brain
```
`action` controls if a the group or member will be handled. To add or remove members, set `action` to `member`.
Example playbook to add group members to a group:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
# Add group members sysops and appops to group sysops
- ipagroup:
ipaadmin_password: MyPassword123
name: ops
group:
- sysops
- appops
```
Example playbook to remove groups:
```yaml
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
# Remove goups sysops, appops and ops
- ipagroup:
ipaadmin_password: MyPassword123
name: sysops,appops,ops
state: absent
```
Variables
=========
ipagroup
-------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`name` \| `cn` | The list of group name strings. | no
`description` | The group description string. | no
`gid` \| `gidnumber` | The GID integer. | no
`nonposix` | Create as a non-POSIX group. (bool) | no
`external` | Allow adding external non-IPA members from trusted domains. (flag) | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`user` | List of user name strings assigned to this group. | no
`group` | List of group name strings assigned to this group. | no
`service` | List of service name strings assigned to this group | no
`action` | Work on group or member level. It can be on of `member` or `group` and defaults to `group`. | no
`state` | The state to ensure. It can be one of `present` or `absent`, defauilt: `present`. | yes
Authors
=======
Thomas Woerner

View File

@@ -50,7 +50,7 @@ Example playbook to add a topology segment wiht default name (cn):
tasks:
- name: Add topology segment
ipatopologysegment:
password: MyPassword123
ipaadmin_password: MyPassword123
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local
@@ -70,7 +70,7 @@ Example playbook to delete a topology segment:
tasks:
- name: Delete topology segment
ipatopologysegment:
password: MyPassword123
ipaadmin_password: MyPassword123
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local
@@ -90,7 +90,7 @@ Example playbook to reinitialize a topology segment:
tasks:
- name: Reinitialize topology segment
ipatopologysegment:
password: MyPassword123
ipaadmin_password: MyPassword123
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local
@@ -111,11 +111,43 @@ Example playbook to verify a topology suffix:
tasks:
- name: Verify topology suffix
ipatopologysuffix:
password: MyPassword123
ipaadmin_password: MyPassword123
suffix: domain
state: verified
```
Example playbook to add or remove or check or reinitialize a list of topology segments:
```yaml
---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipaadmin_password: password1
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: "{{ ipaadmin_password }}"
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
state: present
#state: absent
#state: checked
#state: reinitialized
loop: "{{ ipatopology_segments | default([]) }}"
```
Variables
=========
@@ -125,14 +157,14 @@ ipatopologysegment
Variable | Description | Required
-------- | ----------- | --------
`principal` | The admin principal is a string and defaults to `admin` | no
`password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`suffix` | The topology suffix to be used, this can either be `domain` or `ca` | yes
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`suffix` | The topology suffix to be used, this can either be `domain`, `ca` or `domain+ca` | yes
`name` \| `cn` | The topology segment name (cn) is the unique identifier for a segment. | no
`left` \| `leftnode` | The left replication node string - an IPA server | no
`right` \| `rightnode` | The right replication node string - an IPA server | no
`direction` | The direction a segment will be reinitialized. It can either be `left-to-right` or `right-to-left` and only used with `state: reinitialized` |
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled`, `disabled` or `reinitialized` | yes
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled`, `disabled`, `checked` or `reinitialized` | yes
ipatopologysuffix
@@ -142,8 +174,8 @@ Verify FreeIPA topology suffix
Variable | Description | Required
-------- | ----------- | --------
`principal` | The admin principal is a string and defaults to `admin` | no
`password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`suffix` | The topology suffix to be used, this can either be `domain` or `ca` | yes
`state` | The state to ensure. It can only be `verified` | yes

214
README-user.md Normal file
View File

@@ -0,0 +1,214 @@
User module
===========
Description
-----------
The user module allows to add, remove, enable, disable, unlock und undelete users.
The user module is as compatible as possible to the Ansible upstream `ipa_user` module, but addtionally offers to preserve delete, enable, disable, unlock and undelete users.
Features
--------
* User management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipauser module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to add users:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Create user pinky
- ipauser:
ipaadmin_password: MyPassword123
name: pinky
first: pinky
last: Acme
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
passwordexpiration: "2023-01-19 23:59:59"
password: "no-brain"
update_password: on_create
# Create user brain
- ipauser:
ipaadmin_password: MyPassword123
name: brain
first: brain
last: Acme
```
`update_password` controls if a password for a user will be set in present state only on creation or every time (always).
Example playbook to delete a user, but preserve it:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Remove but preserve user pinky
- ipauser:
ipaadmin_password: MyPassword123
name: pinky
preserve: yes
state: absent
```
Example playbook to undelete a preserved user.
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Undelete preserved user pinky
- ipauser:
ipaadmin_password: MyPassword123
name: pinky
state: undeleted
```
Example playbook to disable a user:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Disable user pinky
- ipauser:
ipaadmin_password: MyPassword123
name: pinky
state: disabled
```
Example playbook to enable users:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Enable user pinky and brain
- ipauser:
ipaadmin_password: MyPassword123
name: pinky,brain
state: enabled
```
Example playbook to unlock users:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Unlock user pinky and brain
- ipauser:
ipaadmin_password: MyPassword123
name: pinky,brain
state: unlocked
```
Example playbook to delete users:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Remove user pinky and brain
- ipauser:
ipaadmin_password: MyPassword123
name: pinky,brain
state: absent
```
Variables
=========
ipauser
-------
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`name` | The list of user name strings. | no
`first` \| `givenname` | The first name string. | no
`last` | The last name | no
`fullname` \| `cn` | The full name string. | no
`displayname` | The display name string. | no
`homedir` | The home directory string. | no
`shell` \| `loginshell` | The login shell string. | no
`email` | List of email address strings. | no
`principalname` \| `krbprincipalname` | The kerberos principal sptring. | no
`passwordexpiration` \| `krbpasswordexpiration` | The kerberos password expiration date. Possible formats: `YYYYMMddHHmmssZ`, `YYYY-MM-ddTHH:mm:ssZ`, `YYYY-MM-ddTHH:mmZ`, `YYYY-MM-ddZ`, `YYYY-MM-dd HH:mm:ssZ` or `YYYY-MM-dd HH:mmZ`. The trailing 'Z' can be skipped. | no
`password` | The user password string. | no
`uid` \| `uidnumber` | The UID integer. | no
`gid` \| `gidnumber` | The GID integer. | no
`phone` \| `telephonenumber` | List of telephone number strings, | no
`title` | The job title string. | no
~~`sshpubkey` \| `ipasshpubkey`~~ | ~~List of SSH public keys.~~ | ~~no~~
`update_password` | Set password for a user in present state only on creation or always. It can be one of `always` or `on_create` and defaults to `always`. | no
`preserve` | Delete a user, keeping the entry available for future use. (bool) | no
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled`, `disabled`, `unlocked` or `undeleted`, default: `present`. | yes
Authors
=======
Thomas Woerner

View File

@@ -1,7 +1,7 @@
FreeIPA Ansible roles
=====================
FreeIPA Ansible collection
==========================
This repository contains [Ansible](https://www.ansible.com/) roles and playbooks to install and uninstall [FreeIPA](https://www.freeipa.org/) `servers`, `replicas` and `clients`.
This repository contains [Ansible](https://www.ansible.com/) roles and playbooks to install and uninstall [FreeIPA](https://www.freeipa.org/) `servers`, `replicas` and `clients`. Also modules for group, topology and user management.
**Note**: The ansible playbooks and roles require a configured ansible environment where the ansible nodes are reachable and are properly set up to have an IP address and a working package manager.
@@ -11,7 +11,9 @@ Features
* Cluster deployments: Server, replicas and clients in one playbook
* One-time-password (OTP) support for client installation
* Repair mode for clients
* Modules for group management
* Modules for topology management
* Modules for user management
Supported FreeIPA Versions
--------------------------
@@ -32,6 +34,7 @@ Requirements
**Controller**
* Ansible version: 2.8+ (ansible-freeipa is an Ansible Collection)
* /usr/bin/kinit is required on the controller if a one time password (OTP) is used
* python3-gssapi is required on the controller if a one time password (OTP) is used with keytab to install the client.
**Node**
@@ -41,11 +44,11 @@ Requirements
Limitations
-----------
**External CA**
**External signed CA**
External CA support is not supported or working. The currently needed two step process is an issue for the processing in the role. The configuration of the server is partly done already and needs to be continued after the CSR has been handled. This is for example breaking the deployment of a server with replicas or clients in one playbook.
External signed CA is now supported. But the currently needed two step process is an issue for the processing in a simple playbook.
Work is planned to have a new method to handle CSR for external CAs in a separate step before starting the server installation.
Work is planned to have a new method to handle CSR for external signed CAs in a separate step before starting the server installation.
Usage
@@ -54,19 +57,51 @@ Usage
How to use ansible-freeipa
--------------------------
**GIT repo**
The simplest method for now is to clone this repository on the contoller from github directly and to start the deployment from the ansible-freeipa directory:
```bash
git clone https://github.com/freeipa/ansible-freeipa.git
cd ansible-freeipa
```
You can use the roles directly within the top directory of the git repo, but to be able to use the management modules in the plugins subdirectory, you have to either adapt `anisble.cfg` or create links for the modules or directories.
You can either adapt ansible.cfg:
```
library = /my/dir/ansible-freeipa/plugins/modules
module_utils = /my/dir/ansible-freeipa/plugins/module_utils
```
Or you can link the directories:
```
ansible-freeipa/plugins/modules to ~/.ansible/plugins/
ansible-freeipa/plugins/module_utils to ~/.ansible/plugins/
```
**RPM package**
There are RPM packages available for Fedora 29+. These are installing the roles and modules into the global Ansible directories for `roles`, `plugins/modules` and `plugings/module_utils` in the `/usr/share/ansible` directory. Therefore is it possible to use the roles and modules without adapting the names like it is done in the example playbooks.
**Ansible galaxy**
This command will get the whole collection from galaxy:
```bash
mazer install freeipa.ansible_freeipa
```
Ansible galaxy does not support the use of dash ('-') in a name and is automatically replacing this with an underscore ('\_'). Therefore the name is `ansible_freeipa`. The ansible_freeipa collection will be placed in the directory `~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa` where it will be automatically be found for this user.
The needed adaptions of collection prefixes for `modules` and `module_utils` will be done with ansible-freeipa release `0.1.6` for galaxy.
The roles provided by ansible-freeipa are not available in ansible galaxy so far.
Ansible inventory file
----------------------
The most important parts of the inventory file is the definition of the nodes, settings and the topology. Please remember to use [Ansible vault](https://docs.ansible.com/ansible/latest/user_guide/vault.html) for passwords. The examples here are not using vault for better readability.
The most important parts of the inventory file is the definition of the nodes, settings and the management modules. Please remember to use [Ansible vault](https://docs.ansible.com/ansible/latest/user_guide/vault.html) for passwords. The examples here are not using vault for better readability.
**Master server**
@@ -101,7 +136,7 @@ ipaserver_setup_firewalld=no
```
The installation of packages and also the configuration of the firewall are by default enabled.
For more server settings, please have a look at the [server role documentation](SERVER.md).
For more server settings, please have a look at the [server role documentation](roles/ipaserver/README.md).
**Replica**
@@ -176,7 +211,7 @@ ipareplica_setup_firewalld=no
The installation of packages and also the configuration of the firewall are by default enabled.
For more replica settings, please have a look at the [replica role documentation](REPLICA.md).
For more replica settings, please have a look at the [replica role documentation](roles/ipareplica/README.md).
**Client**
@@ -215,7 +250,7 @@ To enable the generation of the one-time-password:
ipaclient_use_otp=yes
```
For more client settings, please have a look at the [client role documentation](CLIENT.md).
For more client settings, please have a look at the [client role documentation](roles/ipaclient/README.md).
**Cluster**
@@ -234,6 +269,42 @@ ipaserver_realm=TEST.LOCAL
```
All these settings will be available in the ```[ipaserver]```, ```[ipareplicas]``` and ```[ipaclient]``` groups.
**Topology**
With this playbook it is possible to add a list of topology segments using the `ipatopologysegment` module.
```yaml
---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipaadmin_password: password1
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
password: "{{ ipaadmin_password }}"
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
#state: present
#state: absent
#state: checked
state: reinitialized
loop: "{{ ipatopology_segments | default([]) }}"
```
Playbooks
=========
@@ -309,8 +380,10 @@ Roles
* [Replica](roles/ipareplica/README.md)
* [Client](roles/ipaclient/README.md)
Plugins in plugin/modules
Modules in plugin/modules
=========================
* [ipagroup](README-group.md)
* [ipatopologysegment](README-topology.md)
* [ipatopologysuffix](README-topology.md)
* [ipauser](README-user.md)

View File

@@ -1,6 +1,6 @@
namespace: "freeipa"
name: "ansible_freeipa"
version: "0.1.1"
version: "A.B.C"
description: ""
authors:

View File

@@ -6,7 +6,7 @@
tasks:
- name: Add topology segment
ipatopologysegment:
password: MyPassword123
ipaadmin_password: MyPassword123
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local

View File

@@ -0,0 +1,23 @@
---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: "{{ ipaadmin_password }}"
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
state: present
loop: "{{ ipatopology_segments | default([]) }}"

View File

@@ -0,0 +1,23 @@
---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: "{{ ipaadmin_password }}"
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
state: checked
loop: "{{ ipatopology_segments | default([]) }}"

View File

@@ -6,7 +6,7 @@
tasks:
- name: Delete topology segment
ipatopologysegment:
password: MyPassword123
ipaadmin_password: MyPassword123
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local

View File

@@ -0,0 +1,23 @@
---
- name: Add topology segments
hosts: ipaserver
become: true
gather_facts: false
vars:
ipatopology_segments:
- {suffix: domain, left: replica1.test.local, right: replica2.test.local}
- {suffix: domain, left: replica2.test.local, right: replica3.test.local}
- {suffix: domain, left: replica3.test.local, right: replica4.test.local}
- {suffix: domain+ca, left: replica4.test.local, right: replica1.test.local}
tasks:
- name: Add topology segment
ipatopologysegment:
ipaadmin_password: "{{ ipaadmin_password }}"
suffix: "{{ item.suffix }}"
name: "{{ item.name | default(omit) }}"
left: "{{ item.left }}"
right: "{{ item.right }}"
state: absent
loop: "{{ ipatopology_segments | default([]) }}"

View File

@@ -6,7 +6,7 @@
tasks:
- name: Reinitialize topology segment
ipatopologysegment:
password: MyPassword123
ipaadmin_password: MyPassword123
suffix: domain
left: ipareplica1.test.local
right: ipareplica2.test.local

View File

@@ -6,6 +6,6 @@
tasks:
- name: Verify topology suffix
ipatopologysuffix:
password: MyPassword123
ipaadmin_password: MyPassword123
suffix: domain
state: verified

View File

@@ -0,0 +1,24 @@
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
- name: Create group ops with gid 1234
ipagroup:
ipaadmin_password: MyPassword123
name: ops
gidnumber: 1234
- name: Create group sysops
ipagroup:
ipaadmin_password: MyPassword123
name: sysops
user:
- pinky
- name: Create group appops
ipagroup:
ipaadmin_password: MyPassword123
name: appops

View File

@@ -0,0 +1,13 @@
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
- name: Add group members sysops and appops to group sysops
ipagroup:
ipaadmin_password: MyPassword123
name: ops
group:
- sysops
- appops

View File

@@ -0,0 +1,13 @@
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
- name: Add user member brain to group sysops
ipagroup:
ipaadmin_password: MyPassword123
name: sysops
action: member
user:
- brain

View File

@@ -0,0 +1,20 @@
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Create user pinky
ipauser:
ipaadmin_password: MyPassword123
name: pinky
first: pinky
last: Acme
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
passwordexpiration: "2023-01-19 23:59:59"
password: "no-brain"
update_password: on_create

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to handle groups
hosts: ipaserver
become: true
tasks:
- name: Remove goups sysops, appops and ops
ipagroup:
ipaadmin_password: MyPassword123
name: sysops,appops,ops
state: absent

View File

@@ -0,0 +1,12 @@
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Delete and preserve user pinky
ipauser:
ipaadmin_password: MyPassword123
name: pinky
preserve: yes
state: absent

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Remove user pinky and brain
ipauser:
ipaadmin_password: MyPassword123
name: pinky
state: absent

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Disable user pinky
ipauser:
ipaadmin_password: MyPassword123
name: pinky
state: disabled

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Enable user pinky
ipauser:
ipaadmin_password: MyPassword123
name: pinky
state: enabled

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Undelete preserved user pinky
ipauser:
ipaadmin_password: MyPassword123
name: pinky
state: undeleted

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
- name: Unlock users pinky and brain
ipauser:
ipaadmin_password: MyPassword123
name: pinky,brain
state: unlocked

View File

@@ -22,12 +22,12 @@
import os
import sys
import tempfile
import shutil
from ipalib import api, errors
from datetime import datetime
from ipalib import api
from ipalib.config import Env
from ipalib.constants import DEFAULT_CONFIG
from ipalib.constants import DEFAULT_CONFIG, LDAP_GENERALIZED_TIME_FORMAT
try:
from ipalib.install.kinit import kinit_password
except ImportError:
@@ -120,3 +120,40 @@ def execute_api_command(module, principal, password, command, name, args):
finally:
temp_kdestroy(ccache_dir, ccache_name)
def date_format(value):
accepted_date_formats = [
LDAP_GENERALIZED_TIME_FORMAT, # generalized time
'%Y-%m-%dT%H:%M:%SZ', # ISO 8601, second precision
'%Y-%m-%dT%H:%MZ', # ISO 8601, minute precision
'%Y-%m-%dZ', # ISO 8601, date only
'%Y-%m-%d %H:%M:%SZ', # non-ISO 8601, second precision
'%Y-%m-%d %H:%MZ', # non-ISO 8601, minute precision
]
for date_format in accepted_date_formats:
try:
return datetime.strptime(value, date_format)
except ValueError:
pass
raise ValueError("Invalid date '%s'" % value)
def compare_args_ipa(module, args, ipa):
for key in args.keys():
if key not in ipa:
return False
else:
arg = args[key]
ipa_arg = ipa[key]
# If ipa_arg is a list and arg is not, replace arg
# with list containing arg. Most args in a find result
# are lists, but not all.
if isinstance(ipa_arg, list) and not isinstance(arg, list):
arg = [arg]
# module.warn("%s <=> %s" % (arg, ipa_arg))
if arg != ipa_arg:
return False
return True

425
plugins/modules/ipagroup.py Normal file
View File

@@ -0,0 +1,425 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2019 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipagroup
short description: Manage FreeIPA groups
description: Manage FreeIPA groups
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: false
name:
description: The group name
required: false
aliases: ["cn"]
description:
description: The group description
required: false
gid:
description: The GID
required: false
aliases: ["gidnumber"]
nonposix:
description: Create as a non-POSIX group
required: false
type: bool
external:
description: Allow adding external non-IPA members from trusted domains
required: false
type: bool
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
user:
description: List of user names assigned to this group.
required: false
type: list
group:
description: List of group names assigned to this group.
required: false
type: list
service:
description: List of service names assigned to this group.
required: false
type: list
action:
description: Work on group or member level
default: group
choices: ["member", "group"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Thomas Woerner
"""
EXAMPLES = """
# Create group ops with gid 1234
- ipagroup:
ipaadmin_password: MyPassword123
name: ops
gidnumber: 1234
# Create group sysops
- ipagroup:
ipaadmin_password: MyPassword123
name: sysops
# Create group appops
- ipagroup:
ipaadmin_password: MyPassword123
name: appops
# Add user member pinky to group sysops
- ipagroup:
ipaadmin_password: MyPassword123
name: sysops
action: member
user:
- pinky
# Add user member brain to group sysops
- ipagroup:
ipaadmin_password: MyPassword123
name: sysops
action: member
user:
- brain
# Add group members sysops and appops to group sysops
- ipagroup:
ipaadmin_password: MyPassword123
name: ops
group:
- sysops
- appops
# Remove goups sysops, appops and ops
- ipagroup:
ipaadmin_password: MyPassword123
name: sysops,appops,ops
state: absent
"""
RETURN = """
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
temp_kdestroy, valid_creds, api_connect, api_command, compare_args_ipa
def find_group(module, name):
_args = {
"all": True,
"cn": to_text(name),
}
_result = api_command(module, "group_find", to_text(name), _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one group '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(description, gid, nonposix, external, nomembers):
_args = {}
if description is not None:
_args["description"] = description
if gid is not None:
_args["gidnumber"] = str(gid)
if nonposix is not None:
_args["nonposix"] = nonposix
if external is not None:
_args["external"] = external
if nomembers is not None:
_args["nomembers"] = nomembers
return _args
def gen_member_args(user, group, service):
_args = {}
if user is not None:
_args["member_user"] = user
if group is not None:
_args["member_group"] = group
if service is not None:
_args["member_service"] = service
return _args
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# general
ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=False, no_log=True),
name=dict(type="list", aliases=["cn"], default=None,
required=True),
# present
description=dict(type="str", default=None),
gid=dict(type="int", aliases=["gidnumber"], default=None),
nonposix=dict(required=False, type='bool', default=None),
external=dict(required=False, type='bool', default=None),
nomembers=dict(required=False, type='bool', default=None),
user=dict(required=False, type='list', default=None),
group=dict(required=False, type='list', default=None),
service=dict(required=False, type='list', default=None),
action=dict(type="str", default="group",
choices=["member", "group"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent",
"member_present", "member_absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
ipaadmin_principal = ansible_module.params.get("ipaadmin_principal")
ipaadmin_password = ansible_module.params.get("ipaadmin_password")
names = ansible_module.params.get("name")
# present
description = ansible_module.params.get("description")
gid = ansible_module.params.get("gid")
nonposix = ansible_module.params.get("nonposix")
external = ansible_module.params.get("external")
nomembers = ansible_module.params.get("nomembers")
user = ansible_module.params.get("user")
group = ansible_module.params.get("group")
service = ansible_module.params.get("service")
action = ansible_module.params.get("action")
# state
state = ansible_module.params.get("state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Onle one group can be added at a time.")
if action == "member":
invalid = ["description", "gid", "nonposix", "external",
"nomembers"]
for x in invalid:
if vars()[x] is not None:
ansible_module.fail_json(
msg="Argument '%s' can not be used with action "
"'%s'" % (x, action))
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(
msg="No name given.")
invalid = ["description", "gid", "nonposix", "external", "nomembers"]
if action == "group":
invalid.extend(["user", "group", "service"])
for x in invalid:
if vars()[x] is not None:
ansible_module.fail_json(
msg="Argument '%s' can not be used with state '%s'" %
(x, state))
# Init
changed = False
exit_args = {}
ccache_dir = None
ccache_name = None
try:
if not valid_creds(ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Make sure group exists
res_find = find_group(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description, gid, nonposix, external,
nomembers)
if action == "group":
# Found the group
if res_find is not None:
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args,
res_find):
commands.append([name, "group_mod", args])
else:
commands.append([name, "group_add", args])
# Set res_find to empty dict for next step
res_find = {}
member_args = gen_member_args(user, group, service)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
user_add = list(
set(user or []) -
set(res_find.get("member_user", [])))
user_del = list(
set(res_find.get("member_user", [])) -
set(user or []))
group_add = list(
set(group or []) -
set(res_find.get("member_group", [])))
group_del = list(
set(res_find.get("member_group", [])) -
set(group or []))
service_add = list(
set(service or []) -
set(res_find.get("member_service", [])))
service_del = list(
set(res_find.get("member_service", [])) -
set(service or []))
# Add members
if len(user_add) > 0 or len(group_add) > 0 or \
len(service_add) > 0:
commands.append([name, "group_add_member",
{
"user": user_add,
"group": group_add,
"service": service_add,
}])
# Remove members
if len(user_del) > 0 or len(group_del) > 0 or \
len(service_del) > 0:
commands.append([name, "group_remove_member",
{
"user": user_del,
"group": group_del,
"service": service_del,
}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No group '%s'" % name)
user_add = list(
set(user or []) -
set(res_find.get("member_user", [])))
group_add = list(
set(group or []) -
set(res_find.get("member_group", [])))
service_add = list(
set(service or []) -
set(res_find.get("member_service", [])))
# Add members
if len(user_add) > 0 or len(group_add) > 0 or \
len(service_add) > 0:
commands.append([name, "group_add_member",
{
"user": user,
"group": group,
"service": service,
}])
elif state == "absent":
if action == "group":
if res_find is not None:
commands.append([name, "group_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No group '%s'" % name)
# Remove intersection member
user_del = list(
set(user or []) &
set(res_find.get("member_user", [])))
group_del = list(
set(group or []) &
set(res_find.get("member_group", [])))
service_del = list(
set(service or []) &
set(res_find.get("member_service", [])))
# Remove members
if len(user_del) > 0 or len(group_del) > 0 or \
len(service_del) > 0:
commands.append([name, "group_remove_member",
{
"user": user,
"group": group,
"service": service,
}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
for name, command, args in commands:
try:
api_command(ansible_module, command, to_text(name), args)
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
except Exception as e:
ansible_module.fail_json(msg=str(e))
finally:
temp_kdestroy(ccache_dir, ccache_name)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()

View File

@@ -32,16 +32,16 @@ module: ipatopologysegment
short description: Manage FreeIPA topology segments
description: Manage FreeIPA topology segments
options:
principal:
ipaadmin_principal:
description: The admin principal
default: admin
password:
ipaadmin_password:
description: The admin password
required: false
suffix:
description: Topology suffix
required: true
choices: ["domain", "ca"]
choices: ["domain", "ca", "domain+ca"]
name:
description: Topology segment name, unique identifier.
required: false
@@ -59,7 +59,8 @@ options:
state:
description: State to ensure
default: present
choices: ["present", "absent", "enabled", "disabled", "reinitialized"]
choices: ["present", "absent", "enabled", "disabled", "reinitialized"
"checked" ]
author:
- Thomas Woerner
"""
@@ -87,16 +88,37 @@ EXAMPLES = """
name: ipaserver.test.local-to-replica1.test.local
direction: left-to-right
state: reinitialized
- ipatopologysegment:
suffix: domain+ca
left: ipaserver.test.local
right: ipareplica1.test.local
state: absent
- ipatopologysegment:
suffix: domain+ca
left: ipaserver.test.local
right: ipareplica1.test.local
state: checked
"""
RETURN = """
found:
description: List of found segments
returned: if state is checked
type: list
not-found:
description: List of not found segments
returned: if state is checked
type: list
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_bytes, to_native, to_text
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
temp_kdestroy, valid_creds, api_connect, api_command
def find_left_right(module, suffix, left, right):
_args = {
"iparepltoposegmentleftnode": to_text(left),
@@ -129,12 +151,34 @@ def find_cn(module, suffix, name):
return None
def find_left_right_cn(module, suffix, left, right, name):
if left is not None and right is not None:
left_right = find_left_right(module, suffix, left, right)
if left_right is not None:
if name is not None and \
left_right["cn"][0] != to_text(name):
module.fail_json(
msg="Left and right nodes do not match "
"given name name (cn) '%s'" % name)
return left_right
# else: Nothing to change
elif name is not None:
cn = find_cn(module, suffix, name)
if cn is not None:
return cn
# else: Nothing to change
else:
module.fail_json(
msg="Either left and right or name need to be set.")
return None
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
principal=dict(type="str", default="admin"),
password=dict(type="str", required=False, no_log=True),
suffix=dict(choices=["domain", "ca"], required=True),
ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=False, no_log=True),
suffix=dict(choices=["domain", "ca", "domain+ca"], required=True),
name=dict(type="str", aliases=["cn"], default=None),
left=dict(type="str", aliases=["leftnode"], default=None),
right=dict(type="str", aliases=["rightnode"], default=None),
@@ -142,7 +186,7 @@ def main():
choices=["left-to-right", "right-to-left"]),
state=dict(type="str", default="present",
choices=["present", "absent", "enabled", "disabled",
"reinitialized"]),
"reinitialized", "checked"]),
),
supports_check_mode=True,
)
@@ -151,9 +195,9 @@ def main():
# Get parameters
principal = ansible_module.params.get("principal")
password = ansible_module.params.get("password")
suffix = ansible_module.params.get("suffix")
ipaadmin_principal = ansible_module.params.get("ipaadmin_principal")
ipaadmin_password = ansible_module.params.get("ipaadmin_password")
suffixes = ansible_module.params.get("suffix")
name = ansible_module.params.get("name")
left = ansible_module.params.get("left")
right = ansible_module.params.get("right")
@@ -169,109 +213,110 @@ def main():
# Init
changed = False
exit_args = {}
ccache_dir = None
ccache_name = None
try:
if not valid_creds(principal):
ccache_dir, ccache_name = temp_kinit(principal, password)
if not valid_creds(ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
command = None
commands = []
# Get name (cn) from left and right node if set for absent, disabled
# or reinitialized.
if state in ["absent", "disabled", "reinitialized"]:
if left is not None and right is not None:
left_right = find_left_right(ansible_module, suffix,
left, right)
if left_right is not None:
if name is not None and \
left_right["cn"][0] != to_text(name):
ansible_module.fail_json(
msg="Left and right nodes do not match "
"given name name (cn) '%s'" % name)
args = {
"cn": left_right["cn"][0]
}
# else: Nothing to change
elif name is not None:
result = find_cn(ansible_module, suffix, name)
if result is not None:
args = {
"cn": result["cn"][0]
}
# else: Nothing to change
else:
ansible_module.fail_json(
msg="Either left and right or name need to be set.")
for suffix in suffixes.split("+"):
# Create command
if state in ["present", "enabled"]:
# Make sure topology segment exists
# Create command
if state in ["present", "enabled"]:
# Make sure topology segment exists
if left is None or right is None:
ansible_module.fail_json(
msg="Left and right need to be set.")
args = {
"iparepltoposegmentleftnode": to_text(left),
"iparepltoposegmentrightnode": to_text(right),
}
if name is not None:
args["cn"] = to_text(name)
res_left_right = find_left_right(ansible_module, suffix,
left, right)
if res_left_right is not None:
if name is not None and \
res_left_right["cn"][0] != to_text(name):
if left is None or right is None:
ansible_module.fail_json(
msg="Left and right nodes already used with "
"different name (cn) '%s'" % res_left_right["cn"])
msg="Left and right need to be set.")
args = {
"iparepltoposegmentleftnode": to_text(left),
"iparepltoposegmentrightnode": to_text(right),
}
if name is not None:
args["cn"] = to_text(name)
# Left and right nodes and also the name can not be
# changed
for key in [ "iparepltoposegmentleftnode",
"iparepltoposegmentrightnode" ]:
if key in args:
del args[key]
if len(args) > 1:
# cn needs to be in args always
command = "topologysegment_mod"
# else: Nothing to change
else:
if name is None:
args["cn"] = to_text("%s-to-%s" % (left, right))
command = "topologysegment_add"
res_left_right = find_left_right(ansible_module, suffix,
left, right)
if res_left_right is not None:
if name is not None and \
res_left_right["cn"][0] != to_text(name):
ansible_module.fail_json(
msg="Left and right nodes already used with "
"different name (cn) '%s'" % res_left_right["cn"])
elif state in ["absent", "disabled"]:
# Make sure topology segment does not exist
if len(args) > 0:
# Either name defined or found name from left and right node
command = "topologysegment_del"
elif state == "reinitialized":
# Reinitialize segment
if len(args) > 0:
# Either name defined or found name from left and right node
command = "topologysegment_reinitialize"
if direction == "left-to-right":
args["left"] = True
elif direction == "right-to-left":
args["right"] = True
# Left and right nodes and also the name can not be
# changed
for key in ["iparepltoposegmentleftnode",
"iparepltoposegmentrightnode"]:
if key in args:
del args[key]
if len(args) > 1:
# cn needs to be in args always
commands.append(["topologysegment_mod", args])
# else: Nothing to change
else:
if name is None:
args["cn"] = to_text("%s-to-%s" % (left, right))
commands.append(["topologysegment_add", args])
elif state in ["absent", "disabled"]:
# Make sure topology segment does not exist
res_find = find_left_right_cn(ansible_module, suffix,
left, right, name)
if res_find is not None:
# Found either given name or found name from left and right
# node
args = {
"cn": res_find["cn"][0]
}
commands.append(["topologysegment_del", args])
elif state == "checked":
# Check if topology segment does exists
res_find = find_left_right_cn(ansible_module, suffix,
left, right, name)
if res_find is not None:
# Found either given name or found name from left and right
# node
exit_args.setdefault("found", []).append(suffix)
else:
# Not found
exit_args.setdefault("not-found", []).append(suffix)
elif state == "reinitialized":
# Reinitialize segment
if direction not in ["left-to-right", "right-to-left"]:
ansible_module.fail_json(msg="Unknown direction '%s'" %
direction)
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
res_find = find_left_right_cn(ansible_module, suffix,
left, right, name)
if res_find is not None:
# Found either given name or found name from left and right
# node
args = {
"cn": res_find["cn"][0]
}
if direction == "left-to-right":
args["left"] = True
elif direction == "right-to-left":
args["right"] = True
commands.append(["topologysegment_reinitialize", args])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute command
if command is not None:
result = api_command(ansible_module, command,
to_text(suffix), args)
for command, args in commands:
api_command(ansible_module, command, to_text(suffix), args)
changed = True
except Exception as e:
@@ -282,7 +327,8 @@ def main():
# Done
ansible_module.exit_json(changed=changed)
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()

View File

@@ -32,10 +32,10 @@ module: ipatopologysuffix
short description: Verify FreeIPA topology suffix
description: Verify FreeIPA topology suffix
options:
principal:
ipaadmin_principal:
description: The admin principal
default: admin
password:
ipaadmin_password:
description: The admin password
required: false
suffix:
@@ -60,14 +60,15 @@ RETURN = """
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_bytes, to_native, to_text
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import execute_api_command
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
principal=dict(type="str", default="admin"),
password=dict(type="str", required=False, no_log=True),
ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=False, no_log=True),
suffix=dict(choices=["domain", "ca"], required=True),
state=dict(type="str", default="verified",
choices=["verified"]),
@@ -79,8 +80,8 @@ def main():
# Get parameters
principal = ansible_module.params.get("principal")
password = ansible_module.params.get("password")
ipaadmin_principal = ansible_module.params.get("ipaadmin_principal")
ipaadmin_password = ansible_module.params.get("ipaadmin_password")
suffix = ansible_module.params.get("suffix")
state = ansible_module.params.get("state")
@@ -98,12 +99,13 @@ def main():
# Execute command
execute_api_command(ansible_module, principal, password,
execute_api_command(ansible_module, ipaadmin_principal, ipaadmin_password,
command, to_text(suffix), args)
# Done
ansible_module.exit_json(changed=True)
if __name__ == "__main__":
main()

457
plugins/modules/ipauser.py Normal file
View File

@@ -0,0 +1,457 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2019 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipauser
short description: Manage FreeIPA users
description: Manage FreeIPA users
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: false
name:
description: The list of users (internally uid).
required: false
first:
description: The first name
required: false
aliases: ["givenname"]
last:
description: The last name
required: false
fullname:
description: The full name
required: false
aliases: ["cn"]
displayname:
description: The display name
required: false
homedir:
description: The home directory
required: false
shell:
description: The login shell
required: false
aliases: ["loginshell"]
email:
description: List of email addresses
required: false
principalname:
description: The kerberos principal
required: false
aliases: ["krbprincipalname"]
passwordexpiration:
description:
- The kerberos password expiration date
- (possible formats: YYYYMMddHHmmssZ, YYYY-MM-ddTHH:mm:ssZ,
- YYYY-MM-ddTHH:mmZ, YYYY-MM-ddZ, YYYY-MM-dd HH:mm:ssZ,
- YYYY-MM-dd HH:mmZ) The trailing 'Z' can be skipped.
required: false
aliases: ["krbpasswordexpiration"]
password:
description: The user password
required: false
uid:
description: The UID
required: false
aliases: ["uidnumber"]
gid:
description: The GID
required: false
aliases: ["gidnumber"]
phone:
description: List of telephone numbers
required: false
aliases: ["telephonenumber"]
title:
description: The job title
required: false
#sshpubkey:
# description: List of SSH public keys
# required: false
# aliases: ["ipasshpubkey"]
# ..
update_password:
description:
Set password for a user in present state only on creation or always
default: 'always'
choices: ["always", "on_create"]
preserve:
description: Delete a user, keeping the entry available for future use
required: false
state:
description: State to ensure
default: present
choices: ["present", "absent",
"enabled", "disabled",
"unlocked", "undeleted"]
author:
- Thomas Woerner
"""
EXAMPLES = """
# Create user pinky
- ipauser:
ipaadmin_password: MyPassword123
name: pinky
first: pinky
last: Acme
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
passwordexpiration: "2023-01-19 23:59:59"
password: "no-brain"
update_password: on_create
# Create user brain
- ipauser:
ipaadmin_password: MyPassword123
name: brain
first: brain
last: Acme
# Delete user pinky, but preserved
- ipauser:
ipaadmin_password: MyPassword123
name: pinky
preserve: yes
state: absent
# Undelete user pinky
- ipauser:
ipaadmin_password: MyPassword123
name: pinky
state: undeleted
# Disable user pinky
- ipauser:
ipaadmin_password: MyPassword123
name: pinky,brain
state: disabled
# Enable user pinky and brain
- ipauser:
ipaadmin_password: MyPassword123
name: pinky,brain
state: enabled
# Remove user pinky and brain
- ipauser:
ipaadmin_password: MyPassword123
name: pinky,brain
state: disabled
"""
RETURN = """
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
temp_kdestroy, valid_creds, api_connect, api_command, date_format, \
compare_args_ipa
def find_user(module, name, preserved=False):
_args = {
"all": True,
"uid": to_text(name),
}
if preserved:
_args["preserved"] = preserved
_result = api_command(module, "user_find", to_text(name), _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one user '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(first, last, fullname, displayname, homedir, shell, emails,
principalname, passwordexpiration, password, uid, gid,
phones, title, sshpubkey):
_args = {}
if first is not None:
_args["givenname"] = first
if last is not None:
_args["sn"] = last
if fullname is not None:
_args["cn"] = fullname
if displayname is not None:
_args["displayname"] = displayname
if homedir is not None:
_args["homedirectory"] = homedir
if shell is not None:
_args["loginshell"] = shell
if emails is not None and len(emails) > 0:
_args["mail"] = emails
if principalname is not None:
_args["krbprincipalname"] = principalname
if passwordexpiration is not None:
_args["krbpasswordexpiration"] = passwordexpiration
if password is not None:
_args["userpassword"] = password
if uid is not None:
_args["uidnumber"] = str(uid)
if gid is not None:
_args["gidnumber"] = str(gid)
if phones is not None and len(phones) > 0:
_args["telephonenumber"] = phones
if title is not None:
_args["title"] = title
if sshpubkey is not None:
_args["ipasshpubkey"] = sshpubkey
return _args
def main():
ansible_module = AnsibleModule(
argument_spec=dict(
# general
ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=False, no_log=True),
name=dict(type="list", aliases=["login"], default=None,
required=True),
# present
first=dict(type="str", aliases=["givenname"], default=None),
last=dict(type="str", default=None),
fullname=dict(type="str", aliases=["cn"], default=None),
displayname=dict(type="str", default=None),
homedir=dict(type="str", default=None),
shell=dict(type="str", aliases=["loginshell"], default=None),
email=dict(type="list", default=None),
principalname=dict(type="str", aliases=["krbprincipalname"],
default=None),
passwordexpiration=dict(type="str",
aliases=["krbpasswordexpiration"],
default=None),
password=dict(type="str", default=None, no_log=True),
uid=dict(type="int", aliases=["uidnumber"], default=None),
gid=dict(type="int", aliases=["gidnumber"], default=None),
phone=dict(type="list", aliases=["telephonenumber"], default=None),
title=dict(type="str", default=None),
# sshpubkey=dict(type="list", aliases=["ipasshpubkey"],
# default=None),
update_password=dict(type='str', default=None,
choices=['always', 'on_create']),
# deleted
preserve=dict(required=False, type='bool', default=None),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "enabled", "disabled",
"unlocked", "undeleted"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
ipaadmin_principal = ansible_module.params.get("ipaadmin_principal")
ipaadmin_password = ansible_module.params.get("ipaadmin_password")
names = ansible_module.params.get("name")
# present
first = ansible_module.params.get("first")
last = ansible_module.params.get("last")
fullname = ansible_module.params.get("fullname")
displayname = ansible_module.params.get("displayname")
homedir = ansible_module.params.get("homedir")
shell = ansible_module.params.get("shell")
emails = ansible_module.params.get("email")
principalname = ansible_module.params.get("principalname")
passwordexpiration = ansible_module.params.get("passwordexpiration")
if passwordexpiration is not None:
if passwordexpiration[:-1] != "Z":
passwordexpiration = "%sZ" % passwordexpiration
passwordexpiration = date_format(passwordexpiration)
password = ansible_module.params.get("password")
uid = ansible_module.params.get("uid")
gid = ansible_module.params.get("gid")
phones = ansible_module.params.get("phone")
title = ansible_module.params.get("title")
sshpubkey = ansible_module.params.get("sshpubkey")
update_password = ansible_module.params.get("update_password")
# deleted
preserve = ansible_module.params.get("preserve")
# state
state = ansible_module.params.get("state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Onle one user can be added at a time.")
if first is None:
ansible_module.fail_json(msg="First name is needed")
if last is None:
ansible_module.fail_json(msg="Last name is needed")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(
msg="No name given.")
for x in ["first", "last", "fullname", "displayname", "homedir",
"shell", "emails", "principalname", "passwordexpiration",
"password", "uid", "gid", "phones", "title", "sshpubkey",
"update_password"]:
if vars()[x] is not None:
ansible_module.fail_json(
msg="Argument '%s' can not be used with state '%s'" %
(x, state))
else:
if preserve is not None:
ansible_module.fail_json(
msg="Preserve is only possible for state=absent")
if update_password is None:
update_password = "always"
# Init
changed = False
exit_args = {}
ccache_dir = None
ccache_name = None
try:
if not valid_creds(ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Make sure user exists
res_find = find_user(ansible_module, name)
# Also search for preserved user
res_find_preserved = find_user(ansible_module, name,
preserved=True)
# Create command
if state == "present":
# Generate args
args = gen_args(
first, last, fullname, displayname, homedir, shell, emails,
principalname, passwordexpiration, password, uid, gid,
phones, title, sshpubkey)
# Also check preserved users
if res_find is None and res_find_preserved is not None:
res_find = res_find_preserved
# Found the user
if res_find is not None:
# Ignore password with update_password == on_create
if update_password == "on_create" and \
"userpassword" in args:
del args["userpassword"]
# For all settings is args, check if there are
# different settings in the find result.
# If yes: modify
if not compare_args_ipa(ansible_module, args, res_find):
commands.append([name, "user_mod", args])
else:
commands.append([name, "user_add", args])
elif state == "absent":
# Also check preserved users
if res_find is None and res_find_preserved is not None:
res_find = res_find_preserved
if res_find is not None:
args = {}
if preserve is not None:
args["preserve"] = preserve
commands.append([name, "user_del", args])
elif state == "undeleted":
if res_find_preserved is not None:
commands.append([name, "user_undel", {}])
else:
raise ValueError("No preserved user '%s'" % name)
elif state == "enabled":
if res_find is not None:
if res_find["nsaccountlock"]:
commands.append([name, "user_enable", {}])
else:
raise ValueError("No disabled user '%s'" % name)
elif state == "disabled":
if res_find is not None:
if not res_find["nsaccountlock"]:
commands.append([name, "user_disable", {}])
else:
raise ValueError("No user '%s'" % name)
elif state == "unlocked":
if res_find is not None:
commands.append([name, "user_unlock", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
for name, command, args in commands:
try:
api_command(ansible_module, command, to_text(name), args)
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
except Exception as e:
ansible_module.fail_json(msg=str(e))
finally:
temp_kdestroy(ccache_dir, ccache_name)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()

View File

@@ -1,13 +1,47 @@
ipaclient role
==============
Description
-----------
This [Ansible](https://www.ansible.com/) role allows to join hosts as clients to an IPA domain. This can be done in differnt ways using auto-discovery of the servers, domain and other settings or by specifying them.
**Note**: The ansible playbooks and role require a configured ansible environment where the ansible nodes are reachable and are properly set up to have an IP address and a working package manager.
Features
--------
* Client deployment
* One-time-password (OTP) support
* Repair mode
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.5 and up are supported by the client role. There is also limited support for verison 4.4.
Supported Distributions
-----------------------
* RHEL/CentOS 7.4+
* Fedora 26+
* Ubuntu
Requirements
------------
**Controller**
* Ansible version: 2.8+
* /usr/bin/kinit is required on the controller if a one time password (OTP) is used
* python3-gssapi is required on the controller if a one time password (OTP) is used to install the client.
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
This role allows to join hosts as clients to an IPA domain. This can be done in differnt ways using auto-discovery of the servers, domain and other settings or by specifying them.
Usage
-----
=====
Example inventory file with fixed principal using auto-discovery with DNS records:
@@ -74,78 +108,74 @@ Example playbook to setup the IPA client(s) using principal and password from in
state: present
```
Playbooks
=========
The playbooks needed to deploy or undeploy a client are part of the repository in the playbooks folder. There are also playbooks to deploy and undeploy clusters.
```
install-client.yml
uninstall-client.yml
```
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
How to setup a client
---------------------
```bash
ansible-playbook -v -i inventory/hosts install-client.yml
```
This will deploy the clients defined in the inventory file.
Variables
---------
=========
### `ipaclients`
Base Variables
--------------
The mandatory `ipaclients` group is a list of the names of the IPA clients in FQDN form. All these clients will be installed or configured using the playbook.
Variable | Description | Required
-------- | ----------- | --------
`ipaclients` | This group is a list of the names of the IPA clients in FQDN form. All these clients will be installed or configured using the playbook. | yes
`ipaclient_domain` | This string value sets the DNS domain that will be used for client installation. Usually the DNS domain is a lower-cased name of the Kerberos realm. If the role is for example used in a cluster inventory and `ipaserver_domain` is set, then it will be used. | no
`ipaclient_realm` | This string value sets the Kerberos realm that will be used for client installation. Usually the Kerberos realm is an upper-cased name of the DNS domain. If the role is for example used in a cluster inventory and `ipaserver_realm` is set, then it will be used. If `ipaclient_realm` is not set, then it will be generated from `ipaclient_domain` if this is set. | no
`ipaclient_mkhomedir` | This bool value defines if PAM will be configured to create a users home directory if it does not exist. `ipaclient_mkhomedir` defaults to `no`. | no
`ipaclient_force_join` | This bool value defines if an already enrolled host can join again. `ipaclient_force_join` defaults to `no`. | no
`ipaclient_kinit_attempts` | The int value defines the number of tries to repeat the request for a failed host Kerberos ticket. `ipaclient_kinit_attempts` defaults to 5.| no
`ipaclient_ntp_servers` | The list defines the NTP servers to be used. | no
`ipaclient_ntp_pool` | The string value defines the ntp server pool to be used. | no
`ipaclient_no_ntp` | The bool value defines if NTP will not be configured and enabled. `ipaclient_no_ntp` defaults to `no`. | no
`ipaclient_ssh_trust_dns` | The bool value defines if OpenSSH client will be configured to trust DNS SSHFP records. `ipaclient_ssh_trust_dns` defaults to `no`. | no
`ipaclient_no_ssh` | The bool value defines if OpenSSH client will be configured. `ipaclient_no_ssh` defaults to `no`. | no
`ipaclient_no_sshd` | The bool value defines if OpenSSH server will be configured. `ipaclient_no_sshd` defaults to `no`. | no
`ipaclient_no_sudo` | The bool value defines if SSSD will be configured as a data source for sudo. `ipaclient_no_sudo` defaults to `no`. | no
`ipaclient_no_dns_sshfp` | The bool value defines if DNS SSHFP records will not be created automatically. `ipaclient_no_dns_sshfp` defaults to `no`. | no
`ipaclient_force` | The bool value defines if settings will be forced even in the error case. `ipaclient_force` defaults to `no`. | no
`ipaclient_force_ntpd` | The bool value defines if ntpd usage will be forced. This is not supported anymore and leads to a warning. `ipaclient_force_ntpd` defaults to `no`. | no
`ipaclient_nisdomain` | This string value defines the NIS domain name. | no
`ipaclient_no_nisdomain` | The bool value defines if the NIS domain name will not be configured. `ipaclient_no_nisdomain` defaults to `no`. | no
`ipaclient_configure_firefox` | The bool value defines if Firefox will be configured to use IPA domain credentials. `ipaclient_configure_firefox` defaults to `no`. | no
`ipaclient_firefox_dir` | The string value defines the Firefox installation directory. For example: '/usr/lib/firefox'. | no
`ipaclient_all_ip_addresses` | The bool value defines if DNS A/AAAA records for each IP address on the client will be created. `ipaclient_all_ip_addresses` defaults to `no`. | no
`ipasssd_fixed_primary` | The bool value defines if SSSD will be configured to use a fixed server as the primary IPA server. `ipasssd_fixed_primary` defaults to `no`. | no
`ipasssd_permit` | The bool value defines if SSSD will be configured to permit all access. Otherwise the machine will be controlled by the Host-based Access Controls (HBAC) on the IPA server. `ipasssd_permit` defaults to `no`. | no
`ipasssd_enable_dns_updates` | The bool value tells SSSD to automatically update DNS with the IP address of this client. `ipasssd_enable_dns_updates` defaults to `no`. | no
`ipasssd_no_krb5_offline_passwords` | The bool value defines if SSSD will be configured not to store user password when the server is offline . `ipasssd_no_krb5_offline_passwords` defaults to `no`. | no
`ipasssd_preserve_sssd` | The bool value defines if the old SSSD configuration will be preserved if it is not possible to merge it with a new one. `ipasssd_preserve_sssd` defaults to `no`. | no
`ipaclient_request_cert` | The bool value defines if the certificate for the machine wil be requested. The certificate will be stored in /etc/ipa/nssdb under the nickname "Local IPA host". . `ipaclient_request_cert` defaults to `no`. The option is deprecated and will be removed in a future release. | no
`ipaclient_keytab` | The string value contains the path on the node of a backup host keytab from a previous enrollment. | no
### `ipaclient_domain`
The optional `ipaclient_domain` variable sets the DNS domain that will be used for client installation. Usually the DNS domain is a lower-cased name of the Kerberos realm.
If `ipaclient_domain` is not set, then it will be generated from the domain part of the first entry from the `ipaservers` FQDN group if the group is defined and contains at least one entry. If `ipaservers` is not defined, then the domain will be tried to gather using DNS autodiscovery. `ipaclient_domain` needs to be set if the primary DNS domain is different from domain part of the server FQDN.
### `ipaclient_realm`
The optional `ipaclient_realm` sets the Kerberos realm that will be used for client installation. Usually the Kerberos realm is an upper-cased name of the DNS domain.
If `ipaclient_realm` is not set, then it will be generated from `ipaclient_domain` if this is set. If both are not set, then this
### `ipaclient_keytab`
The optional `ipaclient_keytab` contains the path of a backup host keytab from a previous enrollment.
### `ipaclient_force_join`
The `ipaclient_force_join` bool value defines if an already enrolled host can join again. `ipaclient_force_join` defaults to `no`.
### `ipaclient_use_otp`
The `ipaclient_use_otp` bool value defines if a one-time password will be generated to join a new or existing host. `ipaclient_use_otp` defaults to `no`.
The enforcement on an existing host is not done if there is a working krb5.keytab on the host. If the generation of an otp is enforced for an existing host entry, then the host gets diabled and the containing keytab gets removed.
### `ipaclient_allow_repair`
The `ipaclient_allow_repair` bool value defines if an already joined or partly set-up client can be repaired. `ipaclient_allow_repair` defaults to `no`.
Contrary to `ipaclient_force_join=yes` the host entry will not be changed on the server.
### `ipaclient_kinit_attempts`
The optional `ipaclient_kinit_attempts` defines the number of tries to repeat the request for a failed host Kerberos ticket. `ipaclient_kinit_attempts` defaults to 3.
### `ipaclient_no_ntp`
The `ipaclient_no_ntp` bool value defines if NTP will not be configured and enabled. `ipaclient_no_ntp` defaults to `no`.
### `ipaclient_mkhomedir`
The `ipaclient_mkhomedir` bool value defines if PAM will be configured to create a users home directory if it does not exist. `ipaclient_mkhomedir` defaults to `no`.
Server Variables
----------------
### `ipaservers`
The optional `ipaservers` group is a list of the IPA server full qualified host names. In a topology with a chain of servers and replicas, it is important to use the right server or replica as the server for the client. If there is a need to overwrite the setting for a client in the `ipaclients` group, please use the list `ipaclient_servers` explained below.
If no `ipaservers` group is defined than the installation preparation step will try to use DNS autodiscovery to identify the the IPA server using DNS txt records.
### `ipaadmin_keytab`
The `ipaadmin_keytab` variable enables the use of an admin keytab as an alternativce authentication method. The variable needs to contain the local path to the keytab file. If `ipaadmin_keytab` is used, then `ipaadmin_password` does not need to be set.
### `ipaadmin_principal`
The optional `ipaadmin_principal` variable only needs to be set if the name of the Kerberos admin principal is not "admin". If `ipaadmin_principal` is not set it will be set internally to "admin".
### `ipaadmin_password`
The `ipaadmin_password` variable contains the Kerberos password of the Kerberos admin principal. If `ipaadmin_keytab` is used, then `ipaadmin_password` does not need to be set.
Variable | Description | Required
-------- | ----------- | --------
`ipaservers` | This group is a list of the IPA server full qualified host names. In a topology with a chain of servers and replicas, it is important to use the right server or replica as the server for the client. If there is a need to overwrite the setting for a client in the `ipaclients` group, please use the list `ipaclient_servers` explained below. If no `ipaservers` group is defined than the installation preparation step will try to use DNS autodiscovery to identify the the IPA server using DNS txt records. | mostly
`ipaadmin_keytab` | The string variable enables the use of an admin keytab as an alternativce authentication method. The variable needs to contain the local path to the keytab file. If `ipaadmin_keytab` is used, then `ipaadmin_password` does not need to be set. If `ipaadmin_keytab` is used with `ipaclient_use_otp: yes` then the keytab needs to be available on the contoller, else on the client node. The use of full path names is recommended. | no
`ipaadmin_principal` | The string variable only needs to be set if the name of the Kerberos admin principal is not "admin". If `ipaadmin_principal` is not set it will be set internally to "admin". | no
`ipaadmin_password` | The string variable contains the Kerberos password of the Kerberos admin principal. If `ipaadmin_keytab` is used, then `ipaadmin_password` does not need to be set. | mostly
Topology Variables
@@ -153,21 +183,25 @@ Topology Variables
These variables can be used to define or change how clients are arranged within a cluster for example.
### `ipaclient_no_dns_lookup`
Variable | Description | Required
-------- | ----------- | --------
`ipaclient_no_dns_lookup` | The bool value defines if the `ipaservers` group will be used as servers for the clients automatically. If enabled this deactivates DNS lookup in Kerberos in client installations. `ipaclient_no_dns_lookup` defauults to `no`. | no
`ipaclient_servers` | The optional list can be used to manually override list of servers on a per client basis. The list of servers is normally taken from from `ipaservers` group. | no
The `ipaclient_no_dns_lookup` bool value defines if the `ipaservers` group will be used as servers for the clients automatically. If enabled this deactivates DNS lookup in Kerberos in client installations. `ipaclient_no_dns_lookup` defauults to `no`.
### `ipaclient_servers`
Special Variables
-----------------
The optional `ipaclient_servers` varaible can be used to manually override list of servers on a per client basis. The list of servers is normally taken from from `ipaservers` group.
Variable | Description | Required
-------- | ----------- | --------
`ipaclient_use_otp` | The bool value defines if a one-time password will be generated to join a new or existing host. `ipaclient_use_otp` defaults to `no`. The enforcement on an existing host is not done if there is a working krb5.keytab on the host. If the generation of an otp is enforced for an existing host entry, then the host gets diabled and the containing keytab gets removed. | no
`ipaclient_allow_repair` | The bool value defines if an already joined or partly set-up client can be repaired. `ipaclient_allow_repair` defaults to `no`. Contrary to `ipaclient_force_join=yes` the host entry will not be changed on the server. | no
`ipaclient_install_packages` | The bool value defines if the needed packages are installed on the node. `ipaclient_install_packages` defaults to `yes`. | no
`ipaclient_on_master` | The bool value is only used in the server and replica installation process to install the client part. It should not be set otherwise. `ipaclient_on_master` defaults to `no`. | no
Requirements
------------
freeipa-client v4.4 or later
Authors
-------
=======
Florence Blanc-Renaud

View File

@@ -31,11 +31,6 @@ from ansible.errors import AnsibleError
from ansible.module_utils._text import to_native
from ansible.plugins.action import ActionBase
try:
from __main__ import display
except ImportError:
from ansible.utils.display import Display
display = Display()
def run_cmd(args, stdin=None):
"""
@@ -50,9 +45,10 @@ def run_cmd(args, stdin=None):
p = subprocess.Popen(args, stdin=p_in, stdout=p_out, stderr=p_err,
close_fds=True)
stdout, stderr = p.communicate(stdin)
__temp, stderr = p.communicate(stdin)
return p.returncode
if p.returncode != 0:
raise RuntimeError(stderr)
def kinit_password(principal, password, ccache_name, config):
@@ -60,13 +56,12 @@ def kinit_password(principal, password, ccache_name, config):
Perform kinit using principal/password, with the specified config file
and store the TGT in ccache_name.
"""
args = [ "/usr/bin/kinit", principal, '-c', ccache_name]
args = ["/usr/bin/kinit", principal, '-c', ccache_name]
old_config = os.environ.get('KRB5_CONFIG')
os.environ['KRB5_CONFIG'] = config
try:
result = run_cmd(args, stdin=password.encode())
return result
return run_cmd(args, stdin=password.encode())
finally:
if old_config is not None:
os.environ['KRB5_CONFIG'] = old_config
@@ -126,6 +121,7 @@ KRB5CONF_TEMPLATE = """
{{ ipa_domain }} = {{ ipa_realm }}
"""
class ActionModule(ActionBase):
def run(self, tmp=None, task_vars=None):
@@ -155,8 +151,6 @@ class ActionModule(ActionBase):
keytab = self._task.args.get('keytab', None)
password = self._task.args.get('password', None)
lifetime = self._task.args.get('lifetime', '1h')
ansible_python_interpreter = self._task.args.get('ansible_python_interpreter', None)
task_vars["ansible_python_interpreter"] = ansible_python_interpreter
if (not keytab and not password):
result['failed'] = True
@@ -168,8 +162,8 @@ class ActionModule(ActionBase):
result['msg'] = "principal is required"
return result
data = self._execute_module(module_name='ipaclient_get_facts', module_args=dict(),
task_vars={ "ansible_python_interpreter": ansible_python_interpreter })
data = self._execute_module(module_name='ipaclient_get_facts',
module_args=dict(), task_vars=None)
try:
domain = data['ansible_facts']['ipa']['domain']
realm = data['ansible_facts']['ipa']['realm']
@@ -199,12 +193,14 @@ class ActionModule(ActionBase):
f.write(content)
if password:
# perform kinit -c ccache_name -l 1h principal
res = kinit_password(principal, password, ccache_name,
krb5conf_name)
if res:
try:
# perform kinit -c ccache_name -l 1h principal
kinit_password(principal, password, ccache_name,
krb5conf_name)
except Exception as e:
result['failed'] = True
result['msg'] = 'kinit %s with password failed' % principal
result['msg'] = 'kinit %s with password failed: %s' % \
(principal, to_native(e))
return result
else:
@@ -221,7 +217,8 @@ class ActionModule(ActionBase):
kinit_keytab(principal, keytab, ccache_name, krb5conf_name)
except Exception as e:
result['failed'] = True
result['msg'] = 'kinit %s with keytab %s failed' % (principal, keytab)
result['msg'] = 'kinit %s with keytab %s failed: %s' % \
(principal, keytab, str(e))
return result
try:

View File

@@ -29,21 +29,23 @@ ANSIBLE_METADATA = {'metadata_version': '1.0',
DOCUMENTATION = '''
---
module: ipaclient_api
short description: Create temporary NSS database, call IPA API for remaining enrollment parts
short description:
Create temporary NSS database, call IPA API for remaining enrollment parts
description:
Create temporary NSS database, call IPA API for remaining enrollment parts
Create temporary NSS database, call IPA API for remaining enrollment parts
options:
servers:
description: Fully qualified name of IPA servers to enroll to
required: no
realm:
description: The Kerberos realm of an existing IPA deployment.
required: true
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: The hostname of the machine to join (FQDN).
required: true
description: Fully qualified name of this host
required: no
debug:
description: Turn on extra debugging
required: false
type: bool
default: no
required: yes
author:
- Thomas Woerner
'''
@@ -70,23 +72,26 @@ subject_base:
'''
import os
import sys
import time
import tempfile
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
paths, x509, NUM_VERSION, serialization, certdb, api,
delete_persistent_client_session_data, write_tmp_file,
ipa_generate_password, CalledProcessError, errors, disable_ra, DN,
CLIENT_INSTALL_ERROR, logger
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
servers=dict(required=True, type='list'),
realm=dict(required=True),
hostname=dict(required=True),
debug=dict(required=False, type='bool', default="false")
debug=dict(required=False, type='bool', default="false"),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -97,13 +102,13 @@ def main():
host_principal = 'host/%s@%s' % (hostname, realm)
os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
ca_certs = x509.load_certificate_list_from_file(paths.IPA_CA_CRT)
if NUM_VERSION >= 40500 and NUM_VERSION < 40590:
ca_certs = [ cert.public_bytes(serialization.Encoding.DER)
for cert in ca_certs ]
if 40500 <= NUM_VERSION < 40590:
ca_certs = [cert.public_bytes(serialization.Encoding.DER)
for cert in ca_certs]
elif NUM_VERSION < 40500:
ca_certs = [ cert.der_data for cert in ca_certs ]
ca_certs = [cert.der_data for cert in ca_certs]
with certdb.NSSDatabase() as tmp_db:
api.bootstrap(context='cli_installer',
@@ -137,7 +142,7 @@ def main():
else:
tmp_db.add_cert(cert, 'CA certificate %d' % (i + 1),
'C,,')
except CalledProcessError as e:
except CalledProcessError:
module.fail_json(msg="Failed to add CA to temporary NSS database.")
api.finalize()
@@ -173,10 +178,12 @@ def main():
"may not be available")
except errors.PublicError as e2:
module.fail_json(
msg="Cannot connect to the IPA server RPC interface: %s" % e2)
msg="Cannot connect to the IPA server RPC interface: "
"%s" % e2)
except errors.PublicError as e:
module.fail_json(
msg="Cannot connect to the server due to generic error: %s" % e)
msg="Cannot connect to the server due to generic error: "
"%s" % e)
# Use the RPC directly so older servers are supported
try:
result = api.Backend.rpcclient.forward(
@@ -198,7 +205,7 @@ def main():
try:
config = api.Command['config_show']()['result']
subject_base = str(DN(config['ipacertificatesubjectbase'][0]))
except errors.PublicError as e:
except errors.PublicError:
try:
config = api.Backend.rpcclient.forward(
'config_show',
@@ -217,5 +224,6 @@ def main():
ca_enabled=ca_enabled,
subject_base=subject_base)
if __name__ == '__main__':
main()

View File

@@ -34,20 +34,19 @@ description:
Repair Fix IPA ca certificate
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: true
type: list
description: Fully qualified name of IPA servers to enroll to
required: no
realm:
description: The Kerberos realm of an existing IPA deployment.
required: true
description: Kerberos realm name of the IPA deployment
required: no
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com).
required: true
description: The basedn of the IPA server (of the form dc=example,dc=com)
required: no
allow_repair:
description: Allow repair of already joined hosts. Contrary to ipaclient_force_join the host entry will not be changed on the server.
required: true
type: bool
default: no
description:
Allow repair of already joined hosts. Contrary to ipaclient_force_join
the host entry will not be changed on the server
required: no
author:
- Thomas Woerner
'''
@@ -67,11 +66,15 @@ RETURN = '''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
SECURE_PATH, paths, sysrestore, options, NUM_VERSION, get_ca_cert,
get_ca_certs, errors
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
servers=dict(required=True, type='list'),
realm=dict(required=True),
basedn=dict(required=True),
@@ -90,7 +93,6 @@ def main():
os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
options.ca_cert_file = None
options.unattended = True
options.principal = None
options.force = False
options.password = None
@@ -99,7 +101,7 @@ def main():
if not os.path.exists(paths.IPA_CA_CRT):
if not allow_repair:
module.fail_json(
msg="%s missing, enable allow_repair to fix it." % \
msg="%s missing, enable allow_repair to fix it." %
paths.IPA_CA_CRT)
# Repair missing ca.crt file
@@ -119,5 +121,6 @@ def main():
module.exit_json(changed=changed)
if __name__ == '__main__':
main()

View File

@@ -37,7 +37,7 @@ Backup files using IPA client sysrestore
options:
backup:
description: File to backup
required: true
required: no
author:
- Thomas Woerner
'''
@@ -52,11 +52,14 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
paths, sysrestore
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
backup=dict(required=True),
),
)
@@ -71,5 +74,6 @@ def main():
module.exit_json(changed=False)
if __name__ == '__main__':
main()

View File

@@ -4,10 +4,14 @@
import os
import re
import six
from six.moves.configparser import RawConfigParser
try:
from six.moves.configparser import RawConfigParser
except ImportError:
from ConfigParser import RawConfigParser
from ansible.module_utils.basic import AnsibleModule
# pylint: disable=unused-import
try:
from ipalib import api
except ImportError:
@@ -48,6 +52,7 @@ def is_ntpd_configured():
except IOError:
return False
def is_dns_configured():
# dns is configured when /etc/named.conf contains the line
# dyndb "ipa" "/usr/lib64/bind/ldap.so" {
@@ -62,20 +67,24 @@ def is_dns_configured():
except IOError:
return False
def is_dogtag_configured(subsystem):
# ca / kra is configured when the directory /var/lib/pki/pki-tomcat/[ca|kra]
# exists
available_subsystems = { 'ca', 'kra' }
# ca / kra is configured when the directory
# /var/lib/pki/pki-tomcat/[ca|kra] # exists
available_subsystems = {'ca', 'kra'}
assert subsystem in available_subsystems
return os.path.isdir(os.path.join(VAR_LIB_PKI_TOMCAT, subsystem))
def is_ca_configured():
return is_dogtag_configured('ca')
def is_kra_configured():
return is_dogtag_configured('kra')
def is_client_configured():
# IPA Client is configured when /etc/ipa/default.conf exists
# and /var/lib/ipa-client/sysrestore/sysrestore.state exists
@@ -83,12 +92,14 @@ def is_client_configured():
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
return (os.path.isfile(paths.IPA_DEFAULT_CONF) and fstore.has_files())
def is_server_configured():
# IPA server is configured when /etc/ipa/default.conf exists
# and /var/lib/ipa/sysrestore/sysrestore.state exists
return (os.path.isfile(paths.IPA_DEFAULT_CONF) and
os.path.isfile(SERVER_SYSRESTORE_STATE))
def get_ipa_conf():
# Extract basedn, realm and domain from /etc/ipa/default.conf
parser = RawConfigParser()
@@ -102,6 +113,7 @@ def get_ipa_conf():
domain=domain
)
def get_ipa_version():
try:
from ipapython import version
@@ -114,7 +126,8 @@ def get_ipa_version():
# 4.4.90.201610191151GITd852c00
# 4.4.90.dev201701071308+git2e43db1
# 4.6.90.pre2
if part.startswith('dev') or part.startswith('pre') or 'GIT' in part:
if part.startswith('dev') or part.startswith('pre') or \
'GIT' in part:
version_info.append(part)
else:
version_info.append(int(part))
@@ -126,10 +139,11 @@ def get_ipa_version():
version=version.VERSION,
version_info=version_info
)
def main():
module = AnsibleModule(
argument_spec = dict(),
argument_spec=dict(),
supports_check_mode=True
)
@@ -137,7 +151,7 @@ def main():
# check mode is supported
facts = dict(
packages= dict(
packages=dict(
ipalib=HAS_IPALIB,
ipaserver=HAS_IPASERVER,
),
@@ -156,7 +170,7 @@ def main():
facts['configured']['client'] = True
facts['version'] = get_ipa_version()
for key,value in six.iteritems(get_ipa_conf()):
for key, value in six.iteritems(get_ipa_conf()):
facts[key] = value
if HAS_IPASERVER:
@@ -172,5 +186,6 @@ def main():
ansible_facts=dict(ipa=facts)
)
if __name__ == '__main__':
main()

View File

@@ -35,48 +35,31 @@ description:
host operations.
options:
principal:
description: Kerberos principal used to manage the host
required: true
default: admin
password:
description: Password for the kerberos principal
required: false
keytab:
description: Keytab file containing the Kerberos principal and encrypted key
required: false
lifetime:
description: Sets the default lifetime for initial ticket requests
required: false
default: 1h
description:
User Principal allowed to promote replicas and join IPA realm
required: yes
ccache:
description: The local ccache
required: yes
fqdn:
description: the fully-qualified hostname of the host to add/modify/remove
required: true
random:
description: generate a random password to be used in bulk enrollment
required: false
type: bool
default: no
state:
description: the host state
required: false
default: present
choices: [ "present", "absent" ]
description:
The fully-qualified hostname of the host to add/modify/remove
required: no
certificates:
description: a list of host certificates
required: false
type: list
description: A list of host certificates
required: yes
sshpubkey:
description: the SSH public key for the host
required: false
description: The SSH public key for the host
required: yes
ipaddress:
description: the IP address for the host
required: false
ansible_python_interpreter:
desciption: The ansible python interpreter used in the action plugin part, ignored here
required: false
requirements:
- gssapi on the Ansible controller
description: The IP address for the host
required: yes
random:
description: Generate a random password to be used in bulk enrollment
required: yes
state:
description: The desired host state
required: yes
author:
- "Florence Blanc-Renaud"
'''
@@ -91,26 +74,6 @@ EXAMPLES = '''
ipaddress: 192.168.100.23
random: True
register: result_ipaclient_get_otp
# Add a new host, authenticate with a keytab stored on the controller node
- ipaclient_get_otp:
keytab: admin.keytab
fqdn: ipaclient.ipa.domain.com
# Remove a host, authenticate using principal/password
- ipaclient_get_otp:
principal: admin
password: MySecretPassword
fqdn: ipaclient.ipa.domain.com
state: absent
# Modify a host, add ssh public key:
- ipaclient_get_otp:
principal: admin
password: MySecretPassword
fqdn: ipaclient.ipa.domain.com
sshpubkey: ssh-rsa AAAA...
'''
RETURN = '''
@@ -169,6 +132,7 @@ from ipapython.ipautil import run
if six.PY3:
unicode = str
def get_host_diff(ipa_host, module_host):
"""
Compares two dictionaries containing host attributes and builds a dict
@@ -194,7 +158,7 @@ def get_host_diff(ipa_host, module_host):
ipa_value = sorted(ipa_value)
module_value = sorted(module_value)
if ipa_value != module_value:
data[key]=unicode(module_value)
data[key] = unicode(module_value)
return data
@@ -249,7 +213,7 @@ def ensure_host_present(module, api, ipahost):
# If we want to create a random password, and the host
# already has Keytab: true, then we need first to run
# ipa host-disable in order to remove OTP and keytab
if module.params.get('random') and ipahost['has_keytab'] == True:
if module.params.get('random') and ipahost['has_keytab'] is True:
api.Command.host_disable(fqdn)
result = api.Command.host_mod(fqdn, **diffs)
@@ -268,6 +232,8 @@ def ensure_host_present(module, api, ipahost):
# Must add the user
module_host = get_module_host(module)
# force creation of host even if there is no DNS record
module_host["force"] = True
result = api.Command.host_add(fqdn, **module_host)
# Save random password as it is not displayed by host-show
if module.params.get('random'):
@@ -310,15 +276,14 @@ def main():
"""
module = AnsibleModule(
argument_spec=dict(
principal = dict(default='admin'),
ccache = dict(required=False, type='path'),
fqdn = dict(required=True),
certificates = dict(required=False, type='list'),
sshpubkey= dict(required=False),
ipaddress = dict(required=False),
random = dict(default=False, type='bool'),
state = dict(default='present', choices=[ 'present', 'absent' ]),
ansible_python_interpreter = dict(required=False),
principal=dict(default='admin'),
ccache=dict(required=False, type='path'),
fqdn=dict(required=True),
certificates=dict(required=False, type='list'),
sshpubkey=dict(required=False),
ipaddress=dict(required=False),
random=dict(default=False, type='bool'),
state=dict(default='present', choices=['present', 'absent']),
),
supports_check_mode=True,
)
@@ -329,7 +294,7 @@ def main():
state = module.params.get('state')
try:
os.environ['KRB5CCNAME']=ccache
os.environ['KRB5CCNAME'] = ccache
cfg = dict(
context='ansible_module',
@@ -342,24 +307,24 @@ def main():
api.finalize()
api.Backend.rpcclient.connect()
changed = False
try:
result = api.Command.host_show(fqdn, all=True)
host = result['result']
except errors.NotFound:
host = None
if state == 'present' or state == 'disabled':
changed = ensure_host_present(module, api, host)
if state in ['present', 'disabled']:
ensure_host_present(module, api, host)
elif state == 'absent':
changed = ensure_host_absent(module, api, host)
ensure_host_absent(module, api, host)
except Exception as e:
module.fail_json(msg="ipaclient_get_otp module failed : %s" % str(e))
finally:
run([paths.KDESTROY], raiseonerr=False, env=os.environ)
module.exit_json(changed=changed, host=host)
module.exit_json(changed=False, host=host)
if __name__ == '__main__':
main()

View File

@@ -35,24 +35,21 @@ short description: Configure ipa.conf
description:
Configure ipa.conf
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: true
type: list
domain:
description: The primary DNS domain of an existing IPA deployment.
required: false
description: Primary DNS domain of the IPA deployment
required: no
servers:
description: Fully qualified name of IPA servers to enroll to
required: no
realm:
description: The Kerberos realm of an existing IPA deployment.
required: false
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: The hostname of the machine to join (FQDN).
required: true
description: Fully qualified name of this host
required: no
basedn:
description: The basedn of the detected IPA server.
returned: always
type: string
sample: dc=example,dc=com
description: The basedn of the IPA server (of the form dc=example,dc=com)
required: no
author:
- Thomas Woerner
'''
@@ -71,22 +68,22 @@ EXAMPLES = '''
RETURN = '''
'''
import os
import tempfile
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
paths, sysrestore, configure_ipa_conf
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
domain=dict(required=True, default=None),
servers=dict(required=True, type='list', default=None),
realm=dict(required=True, default=None),
hostname=dict(required=True, default=None),
basedn=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -102,5 +99,6 @@ def main():
module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -31,56 +31,58 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: ipaclient_join
short description: Join a machine to an IPA realm and get a keytab for the host service principal
short description:
Join a machine to an IPA realm and get a keytab for the host service
principal
description:
Join a machine to an IPA realm and get a keytab for the host service principal
Join a machine to an IPA realm and get a keytab for the host service
principal
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: true
type: list
description: Fully qualified name of IPA servers to enroll to
required: no
domain:
description: The primary DNS domain of an existing IPA deployment.
required: true
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: The Kerberos realm of an existing IPA deployment.
required: true
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: The hostname of the machine to join (FQDN).
required: true
description: Fully qualified name of this host
required: no
kdc:
description: The name or address of the host running the KDC.
required: true
description: The name or address of the host running the KDC
required: no
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com).
required: true
description: The basedn of the IPA server (of the form dc=example,dc=com)
required: no
principal:
description: The authorized kerberos principal used to join the IPA realm.
required: false
description:
User Principal allowed to promote replicas and join IPA realm
required: yes
password:
description: The password to use if not using Kerberos to authenticate.
required: false
description: Admin user kerberos password
required: yes
keytab:
description: The path to a backed-up host keytab from previous enrollment.
required: false
description: Path to backed up keytab from previous enrollment
required: yes
admin_keytab:
description: The path to a local admin keytab
required: yes
ca_cert_file:
description: A CA certificate to use. Do not acquire the IPA CA certificate via automated means.
required: false
description:
A CA certificate to use. Do not acquire the IPA CA certificate via
automated means
required: yes
force_join:
description: Force enrolling the host even if host entry exists.
required: false
type: bool
default: no
description: Force client enrollment even if already enrolled
required: yes
kinit_attempts:
description: Repeat the request for host Kerberos ticket X times.
required: false
type: int
default: 5
description: Repeat the request for host Kerberos ticket X times
required: yes
debug:
description: Enable debug mode.
required: false
type: bool
default: no
description: Turn on extra debugging
required: yes
author:
- Thomas Woerner
'''
@@ -124,26 +126,32 @@ import os
import tempfile
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
SECURE_PATH, sysrestore, paths, options, configure_krb5_conf,
realm_to_suffix, kinit_keytab, GSSError, kinit_password, NUM_VERSION,
get_ca_cert, get_ca_certs, errors, run
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
servers=dict(required=True, type='list'),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=True),
kdc=dict(required=True),
basedn=dict(required=True),
basedn=dict(required=True),
principal=dict(required=False),
password=dict(required=False, no_log=True),
keytab=dict(required=False),
admin_keytab=dict(required=False),
ca_cert_file=dict(required=False),
force_join=dict(required=False, type='bool'),
kinit_attempts=dict(required=False, type='int', default=5),
debug=dict(required=False, type='bool'),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -157,14 +165,17 @@ def main():
principal = module.params.get('principal')
password = module.params.get('password')
keytab = module.params.get('keytab')
admin_keytab = module.params.get('admin_keytab')
ca_cert_file = module.params.get('ca_cert_file')
kinit_attempts = module.params.get('kinit_attempts')
debug = module.params.get('debug')
if password is not None and password != "" and \
keytab is not None and keytab != "":
if password is not None and keytab is not None:
module.fail_json(msg="Password and keytab cannot be used together")
if password is None and admin_keytab is None:
module.fail_json(msg="Password or admin_keytab is needed")
client_domain = hostname[hostname.find(".")+1:]
nolog = tuple()
env = {'PATH': SECURE_PATH}
@@ -173,8 +184,7 @@ def main():
sssd = True
options.ca_cert_file = ca_cert_file
options.unattended = True
options.principal = principal if principal != "" else None
options.principal = principal
options.force = False
options.password = password
@@ -207,15 +217,32 @@ def main():
env['XMLRPC_TRACE_CURL'] = 'yes'
if force_join:
join_args.append("-f")
if principal:
if principal is not None:
if principal.find('@') == -1:
principal = '%s@%s' % (principal, realm)
try:
kinit_password(principal, password, ccache_name,
config=krb_name)
except RuntimeError as e:
module.fail_json(
msg="Kerberos authentication failed: {}".format(e))
if admin_keytab:
join_args.append("-f")
if not os.path.exists(admin_keytab):
module.fail_json(
msg="Keytab file could not be found: %s" %
admin_keytab)
try:
kinit_keytab(principal,
admin_keytab,
ccache_name,
config=krb_name,
attempts=kinit_attempts)
except GSSError as e:
module.fail_json(
msg="Kerberos authentication failed: %s" % str(e))
else:
try:
kinit_password(principal, password, ccache_name,
config=krb_name)
except RuntimeError as e:
module.fail_json(
msg="Kerberos authentication failed: {}".format(e))
elif keytab:
join_args.append("-f")
if os.path.exists(keytab):
@@ -271,7 +298,8 @@ def main():
# Fail for missing krb5.keytab on already joined host
if already_joined and not os.path.exists(paths.KRB5_KEYTAB):
module.fail_json(msg="krb5.keytab missing! Retry with ipaclient_force_join=yes to generate a new one.")
module.fail_json(msg="krb5.keytab missing! Retry with "
"ipaclient_force_join=yes to generate a new one.")
if principal:
run([paths.KDESTROY], raiseonerr=False, env=env)
@@ -310,5 +338,6 @@ def main():
module.exit_json(changed=changed,
already_joined=already_joined)
if __name__ == '__main__':
main()

View File

@@ -36,8 +36,8 @@ description:
Backup and set hostname
options:
hostname:
description: The hostname of the machine to join (FQDN).
required: true
description: Fully qualified name of this host
required: no
author:
- Thomas Woerner
'''
@@ -52,18 +52,18 @@ EXAMPLES = '''
RETURN = '''
'''
import os
import tempfile
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
sysrestore, paths, tasks
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
hostname=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -77,5 +77,6 @@ def main():
module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -36,12 +36,14 @@ description:
Setup automount for IPA client
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: true
type: list
description: Fully qualified name of IPA servers to enroll to
required: no
sssd:
description: The installer sssd setting
required: yes
automount_location:
description: Automount location
required: false
description: The automount location
required: yes
author:
- Thomas Woerner
'''
@@ -55,22 +57,24 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
options, configure_automount
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
servers=dict(required=True, type='list'),
sssd=dict(required=False, type='bool', default='yes'),
automount_location=dict(required=False, default=None),
),
supports_check_mode = True,
supports_check_mode=True,
)
#os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
# os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
module._ansible_debug = True
options.servers = module.params.get('servers')
@@ -84,5 +88,6 @@ def main():
module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -36,11 +36,13 @@ description:
Setup firefox for IPA client
options:
domain:
description: The primary DNS domain of an existing IPA deployment.
required: true
description: Primary DNS domain of the IPA deployment
required: no
firefox_dir:
description: Specify directory where Firefox is installed (for example: '/usr/lib/firefox')
required: false
description:
Specify directory where Firefox is installed (for example
'/usr/lib/firefox')
required: yes
author:
- Thomas Woerner
'''
@@ -57,15 +59,18 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
sysrestore, paths, options, configure_firefox
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
domain=dict(required=True),
firefox_dir=dict(required=False),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -78,5 +83,6 @@ def main():
module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -35,12 +35,33 @@ short description: Setup krb5 for IPA client
description:
Setup krb5 for IPA client
options:
server:
domain:
description: Primary DNS domain of the IPA deployment
required: yes
servers:
description: Fully qualified name of IPA servers to enroll to
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: The hostname of the machine to join (FQDN).
required: true
description: Fully qualified name of this host
required: yes
kdc:
description: The name or address of the host running the KDC
required: yes
dnsok:
description: The installer dnsok setting
required: yes
client_domain:
description: Primary DNS domain of the IPA deployment
required: yes
sssd:
description: The installer sssd setting
required: yes
force:
description: Installer force parameter
required: yes
author:
- Thomas Woerner
'''
@@ -58,14 +79,15 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
sysrestore, paths, configure_krb5_conf, logger
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
domain=dict(required=False, default=None),
servers=dict(required=False, type='list', default=None),
realm=dict(required=False, default=None),
@@ -75,9 +97,9 @@ def main():
client_domain=dict(required=False, default=None),
sssd=dict(required=False, type='bool', default=False),
force=dict(required=False, type='bool', default=False),
#on_master=dict(required=False, type='bool', default=False),
# on_master=dict(required=False, type='bool', default=False),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -90,21 +112,21 @@ def main():
client_domain = module.params.get('client_domain')
sssd = module.params.get('sssd')
force = module.params.get('force')
#on_master = module.params.get('on_master')
# on_master = module.params.get('on_master')
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
#if options.on_master:
# # If on master assume kerberos is already configured properly.
# # Get the host TGT.
# try:
# kinit_keytab(host_principal, paths.KRB5_KEYTAB, CCACHE_FILE,
# attempts=options.kinit_attempts)
# os.environ['KRB5CCNAME'] = CCACHE_FILE
# except gssapi.exceptions.GSSError as e:
# logger.error("Failed to obtain host TGT: %s", e)
# raise ScriptError(rval=CLIENT_INSTALL_ERROR)
#else:
# if options.on_master:
# # If on master assume kerberos is already configured properly.
# # Get the host TGT.
# try:
# kinit_keytab(host_principal, paths.KRB5_KEYTAB, CCACHE_FILE,
# attempts=options.kinit_attempts)
# os.environ['KRB5CCNAME'] = CCACHE_FILE
# except gssapi.exceptions.GSSError as e:
# logger.error("Failed to obtain host TGT: %s", e)
# raise ScriptError(rval=CLIENT_INSTALL_ERROR)
# else:
# Configure krb5.conf
fstore.backup_file(paths.KRB5_CONF)
@@ -125,5 +147,6 @@ def main():
module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -36,11 +36,11 @@ description:
Setup NIS for IPA client
options:
domain:
description: The primary DNS domain of an existing IPA deployment.
required: true
description: Primary DNS domain of the IPA deployment
required: no
nisdomain:
description: NIS domain name
required: false
description: The NIS domain name
required: yes
author:
- Thomas Woerner
'''
@@ -54,18 +54,21 @@ EXAMPLES = '''
RETURN = '''
'''
import os
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
options, sysrestore, paths, configure_nisdomain
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
domain=dict(required=True),
nisdomain=dict(required=False),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -75,7 +78,7 @@ def main():
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
argspec = inspect.getargspec(configure_nisdomain)
if not "statestore" in argspec.args:
if "statestore" not in argspec.args:
# NUM_VERSION < 40500:
configure_nisdomain(options=options, domain=domain)
else:
@@ -84,5 +87,6 @@ def main():
module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -36,103 +36,82 @@ description:
Create IPA NSS database
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: true
type: list
description: Fully qualified name of IPA servers to enroll to
required: no
domain:
description: The primary DNS domain of an existing IPA deployment.
required: true
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: The Kerberos realm of an existing IPA deployment.
required: true
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: The hostname of the machine to join (FQDN).
required: true
description: Fully qualified name of this host
required: no
basedn:
description: The basedn of the IPA server (of the form dc=example,dc=com).
required: true
description: The basedn of the IPA server (of the form dc=example,dc=com)
required: no
principal:
description: The authorized kerberos principal used to join the IPA realm.
required: false
description:
User Principal allowed to promote replicas and join IPA realm
required: yes
subject_base:
description: The subject base, needed for certmonger
required: true
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
ca_enabled:
description: Whether the Certificate Authority is enabled or not.
required: true
type: bool
default: no
description: Whether the Certificate Authority is enabled or not
required: no
mkhomedir:
description: Whether to create home directories for users on their first login.
required: false
type: bool
default: no
description: Create home directories for users on their first login
required: yes
on_master:
description: Whether the configuration is done on the master or not.
required: false
type: bool
default: no
description: Whether the configuration is done on the master or not
required: yes
dnsok:
description: The installer dnsok setting
required: yes
enable_dns_updates:
description: Configures the machine to attempt dns updates when the ip address changes.
required: false
type: bool
default: no
description:
Configures the machine to attempt dns updates when the ip address
changes
required: yes
all_ip_addresses:
description: All routable IP addresses configured on any interface will be added to DNS
required: false
type: bool
default: no
description:
All routable IP addresses configured on any interface will be added
to DNS
required: yes
ip_addresses:
description: Specify IP addresses that should be added to DNS.
required: false
type: list
default: None
description: List of Master Server IP Addresses
required: yes
request_cert:
description: request certificate for the machine
required: false
type: bool
default: no
description: Request certificate for the machine
required: yes
preserve_sssd:
description: Preserve old SSSD configuration if possible
required: false
type: bool
default: no
required: yes
no_ssh:
description: Do not configure OpenSSH client
required: false
type: bool
default: no
required: yes
no_sshd:
description: Do not configure OpenSSH server
required: false
type: bool
default: no
required: yes
no_sudo:
description: Do not configure SSSD as data source for sudo
required: false
type: bool
default: no
required: yes
fixed_primary:
description: Configure sssd to use fixed server as primary IPA server
required: false
type: bool
default: no
required: yes
permit:
description: Disable access rules by default, permit all access.
required: false
type: bool
default: no
description: Disable access rules by default, permit all access
required: yes
no_krb5_offline_passwords:
description: Configure SSSD not to store user password when the server is offline
required: false
type: bool
default: no
description:
Configure SSSD not to store user password when the server is offline
required: yes
no_dns_sshfp:
description: Do not automatically create DNS SSHFP records
required: false
type: bool
default: no
required: yes
author:
- Thomas Woerner
'''
@@ -155,13 +134,22 @@ RETURN = '''
import os
import time
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
options, sysrestore, paths, ansible_module_get_parsed_ip_addresses,
api, errors, create_ipa_nssdb, ipautil, ScriptError, CLIENT_INSTALL_ERROR,
get_certs_from_ldap, DN, certstore, x509, logger, certdb,
CalledProcessError, tasks, client_dns, configure_certmonger, services,
update_ssh_keys, save_state, configure_ldap_conf, configure_nslcd_conf,
nosssd_files, configure_openldap_conf, hardcode_ldap_server
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
servers=dict(required=True, type='list'),
domain=dict(required=True),
realm=dict(required=True),
@@ -172,6 +160,7 @@ def main():
ca_enabled=dict(required=True, type='bool'),
mkhomedir=dict(required=False, type='bool'),
on_master=dict(required=False, type='bool'),
dnsok=dict(required=False, type='bool', default=False),
enable_dns_updates=dict(required=False, type='bool'),
all_ip_addresses=dict(required=False, type='bool', default=False),
@@ -186,7 +175,7 @@ def main():
no_krb5_offline_passwords=dict(required=False, type='bool'),
no_dns_sshfp=dict(required=False, type='bool', default=False),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -200,6 +189,7 @@ def main():
ca_enabled = module.params.get('ca_enabled')
options.mkhomedir = module.params.get('mkhomedir')
options.on_master = module.params.get('on_master')
dnsok = module.params.get('dnsok')
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
@@ -241,7 +231,7 @@ def main():
api.Backend.rpcclient.connect()
try:
api.Backend.rpcclient.forward('ping')
except errors.KerberosError as e:
except errors.KerberosError:
# Cannot connect to the server due to Kerberos error, trying with
# delegate=True
api.Backend.rpcclient.disconnect()
@@ -262,8 +252,8 @@ def main():
# Get CA certificates from the certificate store
try:
ca_certs = get_certs_from_ldap(cli_server[0], cli_basedn, cli_realm,
ca_enabled)
ca_certs = get_certs_from_ldap(cli_server[0], cli_basedn,
cli_realm, ca_enabled)
except errors.NoCertificateError:
if ca_enabled:
ca_subject = DN(('CN', 'Certificate Authority'), subject_base)
@@ -271,7 +261,8 @@ def main():
ca_subject = None
ca_certs = certstore.make_compat_ca_certs(ca_certs, cli_realm,
ca_subject)
ca_certs_trust = [(c, n, certstore.key_policy_to_trust_flags(t, True, u))
ca_certs_trust = [(c, n,
certstore.key_policy_to_trust_flags(t, True, u))
for (c, n, t, u) in ca_certs]
if hasattr(paths, "KDC_CA_BUNDLE_PEM"):
@@ -293,12 +284,13 @@ def main():
for cert, nickname, trust_flags in ca_certs_trust:
try:
ipa_db.add_cert(cert, nickname, trust_flags)
except CalledProcessError as e:
except CalledProcessError:
raise ScriptError(
"Failed to add %s to the IPA NSS database." % nickname,
rval=CLIENT_INSTALL_ERROR)
# Add the CA certificates to the platform-dependant systemwide CA store
# Add the CA certificates to the platform-dependant systemwide CA
# store
tasks.insert_ca_certs_into_systemwide_ca_store(ca_certs)
if not options.on_master:
@@ -351,7 +343,8 @@ def main():
except Exception:
if not options.sssd:
logger.warning(
"Failed to configure automatic startup of the %s daemon",
"Failed to configure automatic startup of the %s "
"daemon",
nscd.service_name)
logger.info(
"Caching of users/groups will not be "
@@ -424,15 +417,15 @@ def main():
sssd.enable()
except CalledProcessError as e:
logger.warning(
"Failed to enable automatic startup of the SSSD daemon: "
"%s", e)
"Failed to enable automatic startup of the SSSD "
"daemon: %s", e)
if not options.sssd:
tasks.modify_pam_to_use_krb5(statestore)
logger.info("Kerberos 5 enabled")
# Update non-SSSD LDAP configuration after authconfig calls as it would
# change its configuration otherways
# Update non-SSSD LDAP configuration after authconfig calls as it
# would change its configuration otherways
if not options.sssd:
for configurer in [configure_ldap_conf, configure_nslcd_conf]:
(retcode, conf, filenames) = configurer(
@@ -467,11 +460,15 @@ def main():
# It can sometimes take a few seconds to connect to the remote
# provider.
# Particulary, SSSD might take longer than 6-8 seconds.
if hasattr(paths, "GETENT"):
getent_cmd = paths.GETENT
else:
getent_cmd = '/usr/bin/getent'
while n < 10 and not found:
try:
ipautil.run([paths.GETENT, "passwd", user])
ipautil.run([getent_cmd, "passwd", user])
found = True
except Exception as e:
except Exception:
time.sleep(1)
n = n + 1
@@ -500,5 +497,6 @@ def main():
module.exit_json(changed=True,
ca_enabled_ra=ca_enabled)
if __name__ == '__main__':
main()

View File

@@ -35,44 +35,24 @@ short description: Setup NTP for IPA client
description:
Setup NTP for IPA client
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: false
type: list
default: []
domain:
description: The primary DNS domain of an existing IPA deployment.
required: false
realm:
description: The Kerberos realm of an existing IPA deployment.
required: false
hostname:
description: The hostname of the machine to join (FQDN).
required: false
ca_cert_file:
description: A CA certificate to use.
required: false
on_master:
description: IPA client installation on IPA server
required: false
default: false
type: bool
default: no
ntp_servers:
description: List of NTP servers to use
required: false
type: list
default: []
description: ntp servers to use
required: yes
ntp_pool:
description: ntp server pool to use
required: false
required: yes
no_ntp:
description: Do not sync time and do not detect time servers
required: false
default: false
type: bool
default: no
description: Do not configure ntp
required: yes
on_master:
description: Whether the configuration is done on the master or not
required: yes
servers:
description: Fully qualified name of IPA servers to enroll to
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
author:
- Thomas Woerner
'''
@@ -83,33 +63,36 @@ EXAMPLES = '''
RETURN = '''
'''
import os
import socket
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
options, sysrestore, paths, sync_time, logger, ipadiscovery,
timeconf
)
def main():
module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
ntp_servers=dict(required=False, type='list', default=None),
ntp_pool=dict(required=False, default=None),
no_ntp=dict(required=False, type='bool', default=False),
#force_ntpd=dict(required=False, type='bool', default=False),
# force_ntpd=dict(required=False, type='bool', default=False),
on_master=dict(required=False, type='bool', default=False),
### additional ###
# additional
servers=dict(required=False, type='list', default=None),
domain=dict(required=False, default=None),
),
supports_check_mode = True,
supports_check_mode=True,
)
#module._ansible_debug = True
# module._ansible_debug = True
options.ntp_servers = module.params.get('ntp_servers')
options.ntp_pool = module.params.get('ntp_pool')
options.no_ntp = module.params.get('no_ntp')
#options.force_ntpd = module.params.get('force_ntpd')
# options.force_ntpd = module.params.get('force_ntpd')
options.on_master = module.params.get('on_master')
cli_server = module.params.get('servers')
cli_domain = module.params.get('domain')
@@ -124,20 +107,27 @@ def main():
if sync_time is not None:
if options.conf_ntp:
# Attempt to configure and sync time with NTP server (chrony).
synced_ntp = sync_time(options, fstore, statestore)
argspec = inspect.getargspec(sync_time)
if "options" not in argspec.args:
synced_ntp = sync_time(options.ntp_servers, options.ntp_pool,
fstore, statestore)
else:
synced_ntp = sync_time(options, fstore, statestore)
elif options.on_master:
# If we're on master skipping the time sync here because it was done
# in ipa-server-install
logger.info("Skipping attempt to configure and synchronize time with"
" chrony server as it has been already done on master.")
# If we're on master skipping the time sync here because it was
# done in ipa-server-install
logger.info(
"Skipping attempt to configure and synchronize time with"
" chrony server as it has been already done on master.")
else:
logger.info("Skipping chrony configuration")
else:
ntp_srv_servers = [ ]
ntp_srv_servers = []
if not options.on_master and options.conf_ntp:
# Attempt to sync time with IPA server.
# If we're skipping NTP configuration, we also skip the time sync here.
# If we're skipping NTP configuration, we also skip the time sync
# here.
# We assume that NTP servers are discoverable through SRV records
# in the DNS.
# If that fails, we try to sync directly with IPA server,
@@ -159,7 +149,8 @@ def main():
break
if not synced_ntp and not options.ntp_servers:
synced_ntp = timeconf.synconce_ntp(cli_server[0], options.debug)
synced_ntp = timeconf.synconce_ntp(cli_server[0],
options.debug)
if not synced_ntp:
module.warn(
"Unable to sync time with NTP "
@@ -171,5 +162,6 @@ def main():
# Done
module.exit_json(changed=synced_ntp)
if __name__ == '__main__':
main()

View File

@@ -36,29 +36,20 @@ description:
Configure ssh and sshd for IPA client
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: true
type: list
ssh:
description: Configure OpenSSH client
required: false
type: bool
default: no
trust_sshfp:
description: Fully qualified name of IPA servers to enroll to
required: no
no_ssh:
description: Do not configure OpenSSH client
required: yes
ssh_trust_dns:
description: Configure OpenSSH client to trust DNS SSHFP records
required: false
type: bool
default: no
sshd:
description: Configure OpenSSH server
required: false
type: bool
default: no
required: yes
no_sshd:
description: Do not configure OpenSSH server
required: yes
sssd:
description: Configure SSSD server
required: false
type: bool
default: no
description: The installer sssd setting
required: yes
author:
- Thomas Woerner
'''
@@ -75,21 +66,22 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
options, sysrestore, paths, configure_ssh_config, configure_sshd_config
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
servers=dict(required=True, type='list'),
no_ssh=dict(required=False, type='bool', default='no'),
ssh_trust_dns=dict(required=False, type='bool', default='no'),
no_sshd=dict(required=False, type='bool', default='no'),
sssd=dict(required=False, type='bool', default='no'),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -104,7 +96,7 @@ def main():
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
#os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
# os.environ['KRB5CCNAME'] = paths.IPA_DNS_CCACHE
changed = False
if options.conf_ssh:
@@ -117,5 +109,6 @@ def main():
module.exit_json(changed=changed)
if __name__ == '__main__':
main()

View File

@@ -36,68 +36,52 @@ description:
Setup sssd for IPA client
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: true
type: list
description: Fully qualified name of IPA servers to enroll to
required: no
domain:
description: The primary DNS domain of an existing IPA deployment.
required: true
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: The Kerberos realm of an existing IPA deployment.
required: true
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: The hostname of the machine to join (FQDN).
required: true
description: Fully qualified name of this host
required: no
on_master:
description: Whether the configuration is done on the master or not.
required: false
type: bool
default: no
description: Whether the configuration is done on the master or not
required: yes
no_ssh:
description: Do not configure OpenSSH client
required: false
type: bool
default: no
required: yes
no_sshd:
description: Do not configure OpenSSH server
required: false
type: bool
default: no
required: yes
no_sudo:
description: Do not configure SSSD as data source for sudo
required: false
type: bool
default: no
required: yes
all_ip_addresses:
description: All routable IP addresses configured on any interface will be added to DNS.
required: false
type: bool
default: no
description:
All routable IP addresses configured on any interface will be added
to DNS
required: yes
fixed_primary:
description: Whether to use fixed server as primary IPA server.
required: false
type: bool
default: no
description: Configure sssd to use fixed server as primary IPA server
required: yes
permit:
description: Disable access rules by default, permit all access.
required: false
type: bool
default: no
description: Disable access rules by default, permit all access
required: yes
enable_dns_updates:
description: Configures the machine to attempt dns updates when the ip address changes.
required: false
type: bool
default: no
description:
Configures the machine to attempt dns updates when the ip address
changes
required: yes
preserve_sssd:
description: Preserve old SSSD configuration if possible.
required: false
type: bool
default: no
description: Preserve old SSSD configuration if possible
required: yes
no_krb5_offline_passwords:
description: Whether user passwords are stored when the server is offline.
required: false
type: bool
default: no
description:
Configure SSSD not to store user password when the server is offline
required: yes
author:
- Thomas Woerner
'''
@@ -116,11 +100,14 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
options, sysrestore, paths, configure_sssd_conf, logger
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
servers=dict(required=True, type='list'),
domain=dict(required=True),
realm=dict(required=True),
@@ -137,10 +124,10 @@ def main():
preserve_sssd=dict(required=False, type='bool'),
no_krb5_offline_passwords=dict(required=False, type='bool'),
),
supports_check_mode = True,
supports_check_mode=True,
)
#ansible_log = AnsibleModuleLog(module, logger)
#options.set_logger(ansible_log)
# ansible_log = AnsibleModuleLog(module, logger)
# options.set_logger(ansible_log)
module._ansible_debug = True
cli_server = module.params.get('servers')
@@ -176,5 +163,6 @@ def main():
module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -35,84 +35,70 @@ short description: Tries to discover IPA server
description:
Tries to discover IPA server using DNS or host name
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: false
type: list
default: []
domain:
description: The primary DNS domain of an existing IPA deployment.
required: false
description: Primary DNS domain of the IPA deployment
required: yes
servers:
description: Fully qualified name of IPA servers to enroll to
required: yes
realm:
description: The Kerberos realm of an existing IPA deployment.
required: false
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: The hostname of the machine to join (FQDN).
required: false
description: Fully qualified name of this host
required: yes
ntp_servers:
description: List of NTP servers to use
required: false
type: list
default: []
description: ntp servers to use
required: yes
ntp_pool:
description: ntp server pool to use
required: false
required: yes
no_ntp:
description: Do not sync time and do not detect time servers
required: false
default: false
type: bool
default: no
description: Do not configure ntp
required: yes
force_ntpd:
description: Stop and disable any time&date synchronization services besides ntpd. Deprecated since 4.7.
requried: false
type: bool
default: no
description:
Stop and disable any time&date synchronization services besides ntpd
Deprecated since 4.7
required: yes
nisdomain:
description: NIS domain name
required: false
description: The NIS domain name
required: yes
no_nisdomain:
description: Do not configure NIS domain name
required: false
type: bool
default: no
required: yes
kinit_attempts:
description: Repeat the request for host Kerberos ticket X times.
required: false
type: int
default: 5
description: Repeat the request for host Kerberos ticket X times
required: yes
ca_cert_files:
description: CA certificates to use.
required: false
description:
List of files containing CA certificates for the service certificate
files
required: yes
configure_firefox:
description: Configure Firefox to use IPA domain credentials
required: false
type: bool
default: no
required: yes
firefox_dir:
description: Specify directory where Firefox is installed (for example: '/usr/lib/firefox')
required: false
description:
Specify directory where Firefox is installed (for example
'/usr/lib/firefox')
required: yes
ip_addresses:
description: All routable IP addresses configured on any interface will be added to DNS.
required: false
type: bool
default: no
description: List of Master Server IP Addresses
required: yes
all_ip_addresses:
description: All routable IP addresses configured on any interface will be added to DNS.
required: false
type: bool
default: no
description:
All routable IP addresses configured on any interface will be added
to DNS
required: yes
on_master:
description: IPA client installation on IPA server
required: false
default: false
type: bool
default: no
description: Whether the configuration is done on the master or not
required: yes
enable_dns_updates:
description: Configures the machine to attempt dns updates when the ip address changes.
required: false
type: bool
default: no
description:
Configures the machine to attempt dns updates when the ip address
changes
required: yes
author:
- Thomas Woerner
'''
@@ -194,7 +180,9 @@ ntp_servers:
type: list
sample: ["ntp.example.com"]
ipa_python_version:
description: The IPA python version as a number: <major version>*10000+<minor version>*100+<release>
description:
- The IPA python version as a number:
- <major version>*10000+<minor version>*100+<release>
returned: always
type: int
sample: 040400
@@ -202,10 +190,23 @@ ipa_python_version:
import os
import socket
import inspect
try:
from six.moves.configparser import RawConfigParser
except ImportError:
from ConfigParser import RawConfigParser
from six.moves.configparser import RawConfigParser
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
paths, sysrestore, options, CheckedIPAddress, validate_domain_name,
logger, x509, normalize_hostname, installer, version, ScriptError,
CLIENT_INSTALL_ERROR, tasks, check_ldap_conf, timeconf, constants,
validate_hostname, nssldap_exists, gssapi, remove_file,
check_ip_addresses, ipadiscovery, print_port_conf_info,
IPA_PYTHON_VERSION
)
def get_cert_path(cert_path):
"""
@@ -223,6 +224,7 @@ def get_cert_path(cert_path):
return None
def is_client_configured():
"""
Check if ipa client is configured.
@@ -237,6 +239,7 @@ def is_client_configured():
os.path.isfile(os.path.join(paths.IPA_CLIENT_SYSRESTORE,
sysrestore.SYSRESTORE_STATEFILE)))
def get_ipa_conf():
"""
Return IPA configuration read from /etc/ipa/default.conf
@@ -257,10 +260,11 @@ def get_ipa_conf():
return result
def main():
module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
domain=dict(required=False, default=None),
servers=dict(required=False, type='list', default=None),
realm=dict(required=False, default=None),
@@ -278,13 +282,14 @@ def main():
ip_addresses=dict(required=False, type='list', default=None),
all_ip_addresses=dict(required=False, type='bool', default=False),
on_master=dict(required=False, type='bool', default=False),
### sssd ###
enable_dns_updates=dict(required=False, type='bool', default=False),
# sssd
enable_dns_updates=dict(required=False, type='bool',
default=False),
),
supports_check_mode = True,
supports_check_mode=True,
)
#module._ansible_debug = True
# module._ansible_debug = True
options.domain_name = module.params.get('domain')
options.servers = module.params.get('servers')
options.realm_name = module.params.get('realm')
@@ -308,12 +313,13 @@ def main():
# servers
if options.domain_name is None and options.servers is not None:
if len(options.servers) > 0:
options.domain_name = options.servers[0][options.servers[0].find(".")+1:]
options.domain_name = options.servers[0][
options.servers[0].find(".")+1:]
try:
self = options
### HostNameInstallInterface ###
# HostNameInstallInterface
if options.ip_addresses is not None:
for value in options.ip_addresses:
@@ -323,7 +329,7 @@ def main():
raise ValueError("invalid IP address {0}: {1}".format(
value, e))
### ServiceInstallInterface ###
# ServiceInstallInterface
if options.domain_name:
validate_domain_name(options.domain_name)
@@ -334,12 +340,12 @@ def main():
# NUM_VERSION >= 40690:
validate_domain_name(options.realm_name, entity="realm")
### ClientInstallInterface ###
# ClientInstallInterface
if options.kinit_attempts < 1:
raise ValueError("expects an integer greater than 0.")
### ClientInstallInterface.__init__ ###
# ClientInstallInterface.__init__
if self.servers and not self.domain_name:
raise RuntimeError(
@@ -364,18 +370,18 @@ def main():
if self.enable_dns_updates:
raise RuntimeError(
"--ip-address cannot be used together with"
" --enable-dns-updates")
" --enable-dns-updates")
if self.all_ip_addresses:
raise RuntimeError(
"--ip-address cannot be used together with"
"--all-ip-addresses")
### SSSDInstallInterface ###
# SSSDInstallInterface
self.no_sssd = False
### ClientInstall ###
# ClientInstall
if options.ca_cert_files is not None:
for value in options.ca_cert_files:
@@ -388,18 +394,20 @@ def main():
if not os.path.isfile(value):
raise ValueError("'%s' is not a file" % value)
if not os.path.isabs(value):
raise ValueError("'%s' is not an absolute file path" % value)
raise ValueError("'%s' is not an absolute file path" %
value)
try:
x509.load_certificate_from_file(value)
except Exception:
raise ValueError("'%s' is not a valid certificate file" % value)
raise ValueError("'%s' is not a valid certificate file" %
value)
#self.prompt_password = self.interactive
# self.prompt_password = self.interactive
self.no_ac = False
### ClientInstall.__init__ ###
# ClientInstall.__init__
if self.firefox_dir and not self.configure_firefox:
raise RuntimeError(
@@ -409,41 +417,41 @@ def main():
except (RuntimeError, ValueError) as e:
module.fail_json(msg=str(e))
### ipaclient.install.client.init ###
# ipaclient.install.client.init
# root_logger
options.debug = False
options.unattended = not installer.interactive
if options.domain_name:
options.domain = normalize_hostname(installer.domain_name)
else:
options.domain = None
options.server = options.servers
options.realm = options.realm_name
#installer.primary = installer.fixed_primary
#if installer.principal:
# installer.password = installer.admin_password
#else:
# installer.password = installer.host_password
# installer.primary = installer.fixed_primary
# if installer.principal:
# installer.password = installer.admin_password
# else:
# installer.password = installer.host_password
installer.hostname = installer.host_name
options.conf_ntp = not options.no_ntp
#installer.trust_sshfp = installer.ssh_trust_dns
#installer.conf_ssh = not installer.no_ssh
#installer.conf_sshd = not installer.no_sshd
#installer.conf_sudo = not installer.no_sudo
#installer.create_sshfp = not installer.no_dns_sshfp
# installer.trust_sshfp = installer.ssh_trust_dns
# installer.conf_ssh = not installer.no_ssh
# installer.conf_sshd = not installer.no_sshd
# installer.conf_sudo = not installer.no_sudo
# installer.create_sshfp = not installer.no_dns_sshfp
if installer.ca_cert_files:
installer.ca_cert_file = installer.ca_cert_files[-1]
else:
installer.ca_cert_file = None
#installer.location = installer.automount_location
# installer.location = installer.automount_location
installer.dns_updates = installer.enable_dns_updates
#installer.krb5_offline_passwords = not installer.no_krb5_offline_passwords
# installer.krb5_offline_passwords = \
# not installer.no_krb5_offline_passwords
installer.sssd = not installer.no_sssd
try:
### client ###
# client
# global variables
hostname = None
@@ -452,23 +460,23 @@ def main():
dnsok = False
cli_domain = None
cli_server = None
subject_base = None
# subject_base = None
cli_realm = None
cli_kdc = None
client_domain = None
cli_basedn = None
# end of global variables
### client.install_check ###
# client.install_check
logger.info("This program will set up FreeIPA client.")
logger.info("Version {}".format(version.VERSION))
logger.info("Version %s", version.VERSION)
logger.info("")
cli_domain_source = 'Unknown source'
cli_server_source = 'Unknown source'
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
# fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
if not os.getegid() == 0:
raise ScriptError(
@@ -477,14 +485,14 @@ def main():
tasks.check_selinux_status()
#if is_ipa_client_installed(fstore, on_master=options.on_master):
# logger.error("IPA client is already configured on this system.")
# logger.info(
# "If you want to reinstall the IPA client, uninstall it first "
# "using 'ipa-client-install --uninstall'.")
# raise ScriptError(
# "IPA client is already configured on this system.",
# rval=CLIENT_ALREADY_CONFIGURED)
# if is_ipa_client_installed(fstore, on_master=options.on_master):
# logger.error("IPA client is already configured on this system.")
# logger.info(
# "If you want to reinstall the IPA client, uninstall it first "
# "using 'ipa-client-install --uninstall'.")
# raise ScriptError(
# "IPA client is already configured on this system.",
# rval=CLIENT_ALREADY_CONFIGURED)
if check_ldap_conf is not None:
check_ldap_conf()
@@ -493,24 +501,25 @@ def main():
try:
timeconf.check_timedate_services()
except timeconf.NTPConflictingService as e:
logger.info("WARNING: conflicting time&date synchronization service '{}'"
" will be disabled".format(e.conflicting_service))
logger.info("in favor of chronyd")
logger.info(
"WARNING: conflicting time&date synchronization service "
"'%s' will be disabled in favor of chronyd",
e.conflicting_service)
logger.info("")
except timeconf.NTPConfigurationError:
pass
# password, principal and keytab are checked in tasks/install.yml
#if options.unattended and (
# options.password is None and
# options.principal is None and
# options.keytab is None and
# options.prompt_password is False and
# not options.on_master
#):
# raise ScriptError(
# "One of password / principal / keytab is required.",
# rval=CLIENT_INSTALL_ERROR)
# if options.unattended and (
# options.password is None and
# options.principal is None and
# options.keytab is None and
# options.prompt_password is False and
# not options.on_master
# ):
# raise ScriptError(
# "One of password / principal / keytab is required.",
# rval=CLIENT_INSTALL_ERROR)
if options.hostname:
hostname = options.hostname
@@ -541,17 +550,17 @@ def main():
# --no-sssd is not supported any more for rhel-based distros
if not tasks.is_nosssd_supported() and not options.sssd:
raise ScriptError(
"Option '--no-sssd' is incompatible with the 'authselect' tool "
"provided by this distribution for configuring system "
"authentication resources",
"Option '--no-sssd' is incompatible with the 'authselect' "
"tool provided by this distribution for configuring "
"system authentication resources",
rval=CLIENT_INSTALL_ERROR)
# --noac is not supported any more for rhel-based distros
if not tasks.is_nosssd_supported() and options.no_ac:
raise ScriptError(
"Option '--noac' is incompatible with the 'authselect' tool "
"provided by this distribution for configuring system "
"authentication resources",
"Option '--noac' is incompatible with the 'authselect' "
"tool provided by this distribution for configuring "
"system authentication resources",
rval=CLIENT_INSTALL_ERROR)
# when installing with '--no-sssd' option, check whether nss-ldap is
@@ -563,6 +572,7 @@ def main():
rval=CLIENT_INSTALL_ERROR)
(nssldap_installed, nosssd_files) = nssldap_exists()
(nssldap_installed, __temp) = nssldap_exists()
if not nssldap_installed:
raise ScriptError(
"One of these packages must be installed: nss_ldap or "
@@ -570,15 +580,15 @@ def main():
rval=CLIENT_INSTALL_ERROR)
# principal and keytab are checked in tasks/install.yml
#if options.keytab and options.principal:
# raise ScriptError(
# "Options 'principal' and 'keytab' cannot be used together.",
# rval=CLIENT_INSTALL_ERROR)
# if options.keytab and options.principal:
# raise ScriptError(
# "Options 'principal' and 'keytab' cannot be used together.",
# rval=CLIENT_INSTALL_ERROR)
# keytab and force_join are checked in tasks/install.yml
#if options.keytab and options.force_join:
# logger.warning("Option 'force-join' has no additional effect "
# "when used with together with option 'keytab'.")
# if options.keytab and options.force_join:
# logger.warning("Option 'force-join' has no additional effect "
# "when used with together with option 'keytab'.")
# Added with freeipa-4.7.1 >>>
# Remove invalid keytab file
@@ -597,7 +607,8 @@ def main():
not options.ca_cert_file and
get_cert_path(options.ca_cert_file) == paths.IPA_CA_CRT
):
logger.warning("Using existing certificate '%s'.", paths.IPA_CA_CRT)
logger.warning("Using existing certificate '%s'.",
paths.IPA_CA_CRT)
if not check_ip_addresses(options):
raise ScriptError(
@@ -616,9 +627,9 @@ def main():
)
if options.server and ret != 0:
# There is no point to continue with installation as server list was
# passed as a fixed list of server and thus we cannot discover any
# better result
# There is no point to continue with installation as server list
# was passed as a fixed list of server and thus we cannot discover
# any better result
logger.error(
"Failed to verify that %s is an IPA Server.",
', '.join(options.server))
@@ -666,7 +677,8 @@ def main():
# logger.info(
# "DNS discovery failed to determine your DNS domain")
# cli_domain = user_input(
# "Provide the domain name of your IPA server (ex: example.com)",
# "Provide the domain name of your IPA server "
# "(ex: example.com)",
# allow_empty=False)
# cli_domain_source = 'Provided interactively'
# logger.debug(
@@ -705,7 +717,7 @@ def main():
# ]
# cli_server_source = 'Provided interactively'
# logger.debug(
# "will use interactively provided server: %s", cli_server[0])
# "will use interactively provided server: %s", cli_server[0])
ret = ds.search(
domain=cli_domain,
servers=cli_server,
@@ -713,8 +725,8 @@ def main():
ca_cert_path=get_cert_path(options.ca_cert_file))
else:
# Only set dnsok to True if we were not passed in one or more servers
# and if DNS discovery actually worked.
# Only set dnsok to True if we were not passed in one or more
# servers and if DNS discovery actually worked.
if not options.server:
(server, domain) = ds.check_domain(
ds.domain, set(), "Validating DNS Discovery")
@@ -784,22 +796,29 @@ def main():
logger.info("Discovery was successful!")
elif not options.unattended:
raise ScriptError("No interactive installation")
# if not options.server:
# logger.warning(
# "The failure to use DNS to find your IPA "
# "server indicates that your resolv.conf file is not properly "
# "configured.")
# logger.info(
# "Autodiscovery of servers for failover cannot work "
# "with this configuration.")
# logger.info(
# "If you proceed with the installation, services "
# "will be configured to always access the discovered server for "
# "all operations and will not fail over to other servers in case "
# "of failure.")
# if not user_input(
# "Proceed with fixed values and no DNS discovery?", False):
# raise ScriptError(rval=CLIENT_INSTALL_ERROR)
# if not options.server:
# logger.warning(
# "The failure to use DNS to find your IPA "
# "server indicates that your resolv.conf file is not properly "
# "configured.")
# logger.info(
# "Autodiscovery of servers for failover cannot work "
# "with this configuration.")
# logger.info(
# "If you proceed with the installation, services "
# "will be configured to always access the discovered server for "
# "all operations and will not fail over to other servers in case "
# "of failure.")
# if not user_input(
# "Proceed with fixed values and no DNS discovery?", False):
# raise ScriptError(rval=CLIENT_INSTALL_ERROR)
# Do not ask for time source
# if options.conf_ntp:
# if not options.on_master and not options.unattended and not (
# options.ntp_servers or options.ntp_pool):
# options.ntp_servers, options.ntp_pool = \
# timeconf.get_time_source()
cli_realm = ds.realm
cli_realm_source = ds.realm_source
@@ -807,17 +826,19 @@ def main():
if options.realm_name and options.realm_name != cli_realm:
logger.error(
"The provided realm name [%s] does not match discovered one [%s]",
"The provided realm name [%s] does not match discovered "
"one [%s]",
options.realm_name, cli_realm)
logger.debug("(%s: %s)", cli_realm, cli_realm_source)
raise ScriptError(
"The provided realm name [%s] does not match discovered one [%s]" % (options.realm_name, cli_realm),
"The provided realm name [%s] does not match discovered "
"one [%s]" % (options.realm_name, cli_realm),
rval=CLIENT_INSTALL_ERROR)
cli_basedn = ds.basedn
cli_basedn_source = ds.basedn_source
logger.debug("will use discovered basedn: %s", cli_basedn)
subject_base = DN(('O', cli_realm))
# subject_base = DN(('O', cli_realm))
logger.info("Client hostname: %s", hostname)
logger.debug("Hostname source: %s", hostname_source)
@@ -830,6 +851,14 @@ def main():
logger.info("BaseDN: %s", cli_basedn)
logger.debug("BaseDN source: %s", cli_basedn_source)
if not options.on_master:
if options.ntp_servers:
for server in options.ntp_servers:
logger.info("NTP server: %s", server)
if options.ntp_pool:
logger.info("NTP pool: %s", options.ntp_pool)
# ipa-join would fail with IP address instead of a FQDN
for srv in cli_server:
try:
@@ -850,24 +879,22 @@ def main():
"installation may fail.")
break
#logger.info()
#if not options.unattended and not user_input(
# "Continue to configure the system with these values?", False):
# raise ScriptError(rval=CLIENT_INSTALL_ERROR)
# logger.info()
# if not options.unattended and not user_input(
# "Continue to configure the system with these values?", False):
# raise ScriptError(rval=CLIENT_INSTALL_ERROR)
except ScriptError as e:
module.fail_json(msg=str(e))
#########################################################################
### client._install ###
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
# client._install
# May not happen in here at this time
#if not options.on_master:
# # Try removing old principals from the keytab
# purge_host_keytab(cli_realm)
# if not options.on_master:
# # Try removing old principals from the keytab
# purge_host_keytab(cli_realm)
# Check if ipa client is already configured
if is_client_configured():
@@ -895,8 +922,11 @@ def main():
client_domain=client_domain,
dnsok=dnsok,
sssd=options.sssd,
ntp_servers=options.ntp_servers,
ntp_pool=options.ntp_pool,
client_already_configured=client_already_configured,
ipa_python_version=IPA_PYTHON_VERSION)
if __name__ == '__main__':
main()

View File

@@ -31,32 +31,30 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: ipaclient_test_keytab
short description: Test if the krb5.keytab on the machine is valid and can be used.
short description:
Test if the krb5.keytab on the machine is valid and can be used.
description:
Test if the krb5.keytab on the machine is valid and can be used.
A temporary krb5.conf file will be generated to not fail on an invalid one.
options:
servers:
description: The FQDN of the IPA servers to connect to.
required: true
type: list
description: Fully qualified name of IPA servers to enroll to
required: no
domain:
description: The primary DNS domain of an existing IPA deployment.
required: true
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: The Kerberos realm of an existing IPA deployment.
required: true
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: The hostname of the machine to join (FQDN).
required: true
description: Fully qualified name of this host
required: no
kdc:
description: The name or address of the host running the KDC.
required: true
description: The name or address of the host running the KDC
required: no
kinit_attempts:
description: Repeat the request for host Kerberos ticket X times.
required: false
type: int
default: 5
description: Repeat the request for host Kerberos ticket X times
required: yes
author:
- Thomas Woerner
'''
@@ -100,19 +98,18 @@ ping_test_ok:
type: bool
'''
class Object(object):
pass
options = Object()
import os
import tempfile
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_client import *
from ansible.module_utils.ansible_ipa_client import (
SECURE_PATH, paths, kinit_keytab, run, GSSError, configure_krb5_conf
)
def main():
module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
servers=dict(required=True, type='list'),
domain=dict(required=True),
realm=dict(required=True),
@@ -120,7 +117,7 @@ def main():
kdc=dict(required=True),
kinit_attempts=dict(required=False, type='int', default=5),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -163,52 +160,52 @@ def main():
ping_test_ok = True
except OSError:
pass
except GSSError as e:
except GSSError:
pass
# Second try: Validate krb5 keytab with temporary krb5
# configuration
if not krb5_conf_ok:
try:
(krb_fd, krb_name) = tempfile.mkstemp()
os.close(krb_fd)
configure_krb5_conf(
cli_realm=realm,
cli_domain=domain,
cli_server=servers,
cli_kdc=kdc,
dnsok=False,
filename=krb_name,
client_domain=client_domain,
client_hostname=hostname,
configure_sssd=sssd,
force=False)
try:
(krb_fd, krb_name) = tempfile.mkstemp()
os.close(krb_fd)
configure_krb5_conf(
cli_realm=realm,
cli_domain=domain,
cli_server=servers,
cli_kdc=kdc,
dnsok=False,
filename=krb_name,
client_domain=client_domain,
client_hostname=hostname,
configure_sssd=sssd,
force=False)
try:
kinit_keytab(host_principal, paths.KRB5_KEYTAB,
paths.IPA_DNS_CCACHE,
config=krb_name,
attempts=kinit_attempts)
krb5_keytab_ok = True
try:
kinit_keytab(host_principal, paths.KRB5_KEYTAB,
paths.IPA_DNS_CCACHE,
config=krb_name,
attempts=kinit_attempts)
krb5_keytab_ok = True
# Test IPA
env['KRB5_CONFIG'] = krb_name
try:
result = run(["/usr/bin/ipa", "ping"], raiseonerr=False,
env=env)
if result.returncode == 0:
ping_test_ok = True
except OSError:
pass
# Test IPA
env['KRB5_CONFIG'] = krb_name
try:
result = run(["/usr/bin/ipa", "ping"], raiseonerr=False,
env=env)
if result.returncode == 0:
ping_test_ok = True
except OSError:
pass
except GSSError as e:
pass
except GSSError:
pass
finally:
try:
os.remove(krb_name)
except OSError:
module.fail_json(msg="Could not remove %s" % krb_name)
finally:
try:
os.remove(krb_name)
except OSError:
module.fail_json(msg="Could not remove %s" % krb_name)
module.exit_json(changed=False,
krb5_keytab_ok=krb5_keytab_ok,
@@ -216,5 +213,6 @@ def main():
ca_crt_exists=ca_crt_exists,
ping_test_ok=ping_test_ok)
if __name__ == '__main__':
main()

View File

@@ -22,15 +22,39 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
__all__ = ["gssapi", "version", "ipadiscovery", "api", "errors", "x509",
"constants", "sysrestore", "certmonger", "certstore",
"delete_persistent_client_session_data", "ScriptError",
"CheckedIPAddress", "validate_domain_name", "normalize_hostname",
"validate_hostname", "services", "tasks", "CalledProcessError",
"write_tmp_file", "ipa_generate_password", "DN", "kinit_keytab",
"kinit_password", "GSSError", "CLIENT_INSTALL_ERROR",
"is_ipa_client_installed", "CLIENT_ALREADY_CONFIGURED",
"nssldap_exists", "remove_file", "check_ip_addresses",
"print_port_conf_info", "configure_ipa_conf", "purge_host_keytab",
"configure_sssd_conf", "realm_to_suffix", "run", "timeconf",
"serialization", "configure_krb5_conf", "get_ca_certs",
"SECURE_PATH", "get_server_connection_interface",
"configure_nsswitch_database", "disable_ra", "client_dns",
"configure_certmonger", "update_ssh_keys",
"configure_openldap_conf", "hardcode_ldap_server",
"get_certs_from_ldap", "save_state", "create_ipa_nssdb",
"configure_nisdomain", "configure_ldap_conf",
"configure_nslcd_conf", "nosssd_files", "configure_ssh_config",
"configure_sshd_config", "configure_automount",
"configure_firefox", "sync_time", "check_ldap_conf",
"sssd_enable_ifp"]
from ipapython.version import NUM_VERSION, VERSION
if NUM_VERSION < 30201:
# See ipapython/version.py
IPA_MAJOR,IPA_MINOR,IPA_RELEASE = [ int(x) for x in VERSION.split(".", 2) ]
IPA_MAJOR, IPA_MINOR, IPA_RELEASE = [int(x) for x in VERSION.split(".", 2)]
IPA_PYTHON_VERSION = IPA_MAJOR*10000 + IPA_MINOR*100 + IPA_RELEASE
else:
IPA_PYTHON_VERSION = NUM_VERSION
class installer_obj(object):
def __init__(self):
pass
@@ -38,20 +62,20 @@ class installer_obj(object):
def set_logger(self, logger):
self.logger = logger
#def __getattribute__(self, attr):
# def __getattribute__(self, attr):
# value = super(installer_obj, self).__getattribute__(attr)
# if not attr.startswith("--") and not attr.endswith("--"):
# logger.debug(
# " <-- Accessing installer.%s (%s)" % (attr, repr(value)))
# return value
#def __getattr__(self, attr):
# #logger.info(" --> ADDING missing installer.%s" % attr)
# def __getattr__(self, attr):
# # logger.info(" --> ADDING missing installer.%s" % attr)
# self.logger.warn(" --> ADDING missing installer.%s" % attr)
# setattr(self, attr, None)
# return getattr(self, attr)
#def __setattr__(self, attr, value):
# def __setattr__(self, attr, value):
# logger.debug(" --> Setting installer.%s to %s" % (attr, repr(value)))
# return super(installer_obj, self).__setattr__(attr, value)
@@ -59,11 +83,13 @@ class installer_obj(object):
for name in self.__dict__:
yield self, name
# Initialize installer settings
installer = installer_obj()
# Create options
options = installer
options.interactive = False
options.unattended = not options.interactive
if NUM_VERSION >= 40400:
# IPA version >= 4.4
@@ -73,8 +99,6 @@ if NUM_VERSION >= 40400:
import gssapi
import logging
import six
from ipapython import version
try:
from ipaclient.install import ipadiscovery
@@ -103,8 +127,10 @@ if NUM_VERSION >= 40400:
from ipaplatform import services
from ipaplatform.paths import paths
from ipaplatform.tasks import tasks
if NUM_VERSION >= 40500 and NUM_VERSION < 40590:
try:
from cryptography.hazmat.primitives import serialization
except ImportError:
serialization = None
from ipapython.ipautil import CalledProcessError, write_tmp_file, \
ipa_generate_password
from ipapython.dn import DN
@@ -125,7 +151,9 @@ if NUM_VERSION >= 40400:
CLIENT_INSTALL_ERROR, is_ipa_client_installed, \
CLIENT_ALREADY_CONFIGURED, nssldap_exists, remove_file, \
check_ip_addresses, print_port_conf_info, configure_ipa_conf, \
purge_host_keytab, configure_sssd_conf
purge_host_keytab, configure_sssd_conf, configure_ldap_conf, \
configure_nslcd_conf, nosssd_files
get_ca_cert = None
except ImportError:
# Create temporary copy of ipa-client-install script (as
# ipa_client_install.py) to be able to import the script easily
@@ -134,7 +162,8 @@ if NUM_VERSION >= 40400:
# needed in the next step.
# This is done in a temporary directory that gets removed right
# after ipa_client_install has been imported.
import shutil, tempfile
import shutil
import tempfile
temp_dir = tempfile.mkdtemp(dir="/tmp")
sys.path.append(temp_dir)
temp_file = "%s/ipa_client_install.py" % temp_dir
@@ -168,11 +197,15 @@ if NUM_VERSION >= 40400:
get_ca_cert = ipa_client_install.get_ca_cert
get_ca_certs = None
else:
get_ca_cert = None
get_ca_certs = ipa_client_install.get_ca_certs
SECURE_PATH = ("/bin:/sbin:/usr/kerberos/bin:/usr/kerberos/sbin:/usr/bin:/usr/sbin")
SECURE_PATH = ("/bin:/sbin:/usr/kerberos/bin:/usr/kerberos/sbin:"
"/usr/bin:/usr/sbin")
get_server_connection_interface = ipa_client_install.get_server_connection_interface
configure_nsswitch_database = ipa_client_install.configure_nsswitch_database
get_server_connection_interface = \
ipa_client_install.get_server_connection_interface
configure_nsswitch_database = \
ipa_client_install.configure_nsswitch_database
disable_ra = ipa_client_install.disable_ra
client_dns = ipa_client_install.client_dns
configure_certmonger = ipa_client_install.configure_certmonger
@@ -191,6 +224,10 @@ if NUM_VERSION >= 40400:
def configure_nisdomain(options, domain, statestore=None):
return ipa_client_install.configure_nisdomain(options, domain)
configure_ldap_conf = ipa_client_install.configure_ldap_conf
configure_nslcd_conf = ipa_client_install.configure_nslcd_conf
nosssd_files = ipa_client_install.nosssd_files
configure_ssh_config = ipa_client_install.configure_ssh_config
configure_sshd_config = ipa_client_install.configure_sshd_config
configure_automount = ipa_client_install.configure_automount
@@ -198,9 +235,6 @@ if NUM_VERSION >= 40400:
from ipapython.ipautil import realm_to_suffix, run
if six.PY3:
unicode = str
try:
from ipaclient.install import timeconf
time_service = "chronyd"
@@ -244,7 +278,7 @@ def ansible_module_get_parsed_ip_addresses(ansible_module,
if ip_addresses is None:
return None
ip_addrs = [ ]
ip_addrs = []
for ip in ip_addresses:
try:
ip_parsed = ipautil.CheckedIPAddress(ip)
@@ -252,4 +286,3 @@ def ansible_module_get_parsed_ip_addresses(ansible_module,
ansible_module.fail_json(msg="Invalid IP Address %s: %s" % (ip, e))
ip_addrs.append(ip_parsed)
return ip_addrs

View File

@@ -3,9 +3,8 @@
- name: Install - Ensure that IPA client packages are installed
package:
name: "{{ item }}"
name: "{{ ipaclient_packages }}"
state: present
with_items: "{{ ipaclient_packages }}"
when: ipaclient_install_packages | bool
#- name: Install - Include Python2/3 import test
@@ -64,8 +63,8 @@
- name: Install - Configure NTP
ipaclient_setup_ntp:
### basic ###
ntp_servers: "{{ ipaclient_ntp_servers | default(omit) }}"
ntp_pool: "{{ ipaclient_ntp_pool | default(omit) }}"
ntp_servers: "{{ result_ipaclient_test.ntp_servers | default(omit) }}"
ntp_pool: "{{ result_ipaclient_test.ntp_pool | default(omit) }}"
no_ntp: "{{ ipaclient_no_ntp }}"
# force_ntpd: "{{ ipaclient_force_ntpd }}"
on_master: "{{ ipaclient_on_master }}"
@@ -107,10 +106,6 @@
fail: msg="Keytab or password is required for otp"
when: ipaadmin_keytab is undefined and ipaadmin_password is undefined
- name: Install - Save client ansible_python_interpreter setting
set_fact:
ipaclient_ansible_python_interpreter: "{{ ansible_python_interpreter }}"
#- name: Install - Include Python2/3 import test
# import_tasks: "{{ role_path }}/tasks/python_2_3_test.yml"
# delegate_to: "{{ result_ipaclient_test.servers[0] }}"
@@ -119,13 +114,12 @@
no_log: yes
ipaclient_get_otp:
state: present
principal: "{{ ipaadmin_principal | default('admin') }}"
principal: "{{ ipaadmin_principal | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
keytab: "{{ ipaadmin_keytab | default(omit) }}"
fqdn: "{{ result_ipaclient_test.hostname }}"
lifetime: "{{ ipaclient_lifetime | default(omit) }}"
random: True
ansible_python_interpreter: "{{ ansible_python_interpreter }}"
register: result_ipaclient_get_otp
# If the host is already enrolled, this command will exit on error
# The error can be ignored
@@ -134,18 +128,21 @@
in result_ipaclient_get_otp.msg
delegate_to: "{{ result_ipaclient_test.servers[0] }}"
delegate_facts: yes
ignore_errors: yes
- name: Install - Report error for OTP generation
debug:
msg: "{{ result_ipaclient_get_otp.msg }}"
when: result_ipaclient_get_otp is failed
failed_when: yes
- name: Install - Store the previously obtained OTP
no_log: yes
set_fact:
ipaadmin_orig_password: "{{ ipaadmin_password }}"
ipaadmin_orig_password: "{{ ipaadmin_password | default(omit) }}"
ipaadmin_password: "{{ result_ipaclient_get_otp.host.randompassword
if result_ipaclient_get_otp.host is defined }}"
- name: Install - Restore client ansible_python_interpreter setting
set_fact:
ansible_python_interpreter: "{{ ipaclient_ansible_python_interpreter }}"
when: ipaclient_use_otp | bool
- block:
@@ -159,14 +156,14 @@
- name: Install - Check if principal and keytab are set
fail: msg="Principal and keytab cannot be used together"
when: ipaadmin_principal is defined and ipaadmin_principal|length > 0
and ipaclient_keytab is defined and ipaclient_keytab|length > 0
when: ipaadmin_principal is defined and ipaclient_keytab is defined
- name: Install - Check if one of password and keytab are set
fail: msg="At least one of password or keytab must be specified"
when: not result_ipaclient_test_keytab.krb5_keytab_ok and
(ipaadmin_password is undefined or ipaadmin_password|length == 0)
and (ipaclient_keytab is undefined or ipaclient_keytab|length == 0)
- name: Install - Check if one of password or keytabs are set
fail: msg="At least one of password or keytabs must be specified"
when: not result_ipaclient_test_keytab.krb5_keytab_ok
and ipaadmin_password is undefined
and ipaadmin_keytab is undefined
and ipaclient_keytab is undefined
when: not ipaclient_on_master | bool
- name: Install - Purge {{ result_ipaclient_test.realm }} from host keytab
@@ -197,9 +194,10 @@
hostname: "{{ result_ipaclient_test.hostname }}"
force_join: "{{ ipaclient_force_join | default(omit) }}"
principal: "{{ ipaadmin_principal if not ipaclient_use_otp | bool and
ipaclient_keytab is not defined else '' }}"
ipaclient_keytab is not defined else omit }}"
password: "{{ ipaadmin_password | default(omit) }}"
keytab: "{{ ipaclient_keytab | default(omit) }}"
admin_keytab: "{{ ipaadmin_keytab if ipaadmin_keytab is defined and not ipaclient_use_otp | bool else omit }}"
# ca_cert_file: "{{ ipaclient_ca_cert_file | default(omit) }}"
kinit_attempts: "{{ ipaclient_kinit_attempts | default(omit) }}"
register: result_ipaclient_join
@@ -298,6 +296,7 @@
mkhomedir: "{{ ipaclient_mkhomedir }}"
ca_enabled: "{{ result_ipaclient_api.ca_enabled }}"
on_master: "{{ ipaclient_on_master }}"
dnsok: "{{ result_ipaclient_test.dnsok }}"
enable_dns_updates: "{{ ipassd_enable_dns_updates }}"
all_ip_addresses: "{{ ipaclient_all_ip_addresses }}"
ip_addresses: "{{ ipaclient_ip_addresses | default(omit) }}"

View File

@@ -10,9 +10,9 @@
- "{{ role_path }}/vars/default.yml"
- name: Install IPA client
include_tasks: tasks/install.yml
include_tasks: install.yml
when: state|default('present') == 'present'
- name: Uninstall IPA client
include_tasks: tasks/uninstall.yml
include_tasks: uninstall.yml
when: state|default('present') == 'absent'

View File

@@ -14,8 +14,7 @@
failed_when: uninstall.rc != 0 and uninstall.rc != 2
changed_when: uninstall.rc == 0
# - name: Remove IPA client package
# package:
# name: "{{ item }}"
# state: absent
# with_items: "{{ ipaclient_packages }}"
#- name: Remove IPA client package
# package:
# name: "{{ ipaclient_packages }}"
# state: absent

View File

@@ -0,0 +1,3 @@
# defaults file for ipaclient
# vars/RedHat-8.yml
ipaclient_packages: [ "@idm:DL1/client" ]

View File

@@ -9,8 +9,41 @@ Changes made to any master are automatically replicated to other masters.
This can be done in differnt ways using auto-discovery of the servers, domain and other settings or by specifying them.
**Note**: The ansible playbooks and role require a configured ansible environment where the ansible nodes are reachable and are properly set up to have an IP address and a working package manager.
Features
--------
* Replica deployment
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.6 and up are supported by the replica role.
Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* Fedora 26+
* Ubuntu
Requirements
------------
**Controller**
* Ansible version: 2.8+
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
Usage
-----
=====
Example inventory file with fixed principal using auto-discovery with DNS records:
@@ -68,68 +101,146 @@ Example playbook to setup the IPA client(s) using principal and password from in
- role: ipareplica
state: present
Playbooks
=========
The playbooks needed to deploy or undeploy a replica are part of the repository in the playbooks folder. There are also playbooks to deploy and undeploy clusters.
```
install-replica.yml
uninstall-replica.yml
```
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
How to setup replicas
---------------------
```bash
ansible-playbook -v -i inventory/hosts install-replica.yml
```
This will deploy the replicas defined in the inventory file.
Variables
---------
=========
**ipaserver** - Group with IPA server hostname.
(list of strings, optional)
Base Variables
--------------
**ipaclients** - Group of IPA client hostnames.
(list of strings)
Variable | Description | Required
-------- | ----------- | --------
`ipaservers` | This group with the IPA master full qualified hostnames. (list of strings) | mostly
`ipareplicas` | Group of IPA replica hostnames. (list of strings) | yes
`ipaadmin_password` | The password for the IPA admin user (string) | mostly
`ipareplica_ip_addresses` | The list of master server IP addresses. (list of strings) | no
`ipareplica_domain` | The primary DNS domain of an existing IPA deployment. (string) | no
`ipaserver_realm` | The Kerberos realm of an existing IPA deployment. (string) | no
`ipaserver_hostname` | Fully qualified name of the server. (string) | no
`ipaadmin_principal` | The authorized kerberos principal used to join the IPA realm. (string) | no
`ipareplica_no_host_dns` | Do not use DNS for hostname lookup during installation. (bool, default: false) | no
`ipareplica_skip_conncheck` | Skip connection check to remote master. (bool, default: false) | no
`ipareplica_pki_config_override` | Path to ini file with config overrides. This is only usable with recent FreeIPA versions. (string) | no
**ipaadmin_keytab** - The path to the admin keytab used for alternative authentication.
(string, optional)
Server Vaiables
---------------
**ipaadmin_principal** - The authorized kerberos principal used to join the IPA realm.
(string, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipadm_password` | The password for the Directory Manager. (string) | mostly
`ipareplica_setup_adtrust` | Configure AD trust capability. (bool, default: false) | no
`ipareplica_setup_ca` | Configure a dogtag CA. (bool, default: false) | no
`ipareplica_setup_kra` | Configure a dogtag KRA. (bool, default: false) | no
`ipareplica_setup_dns` | Configure bind with our zone. (bool, default: false) | no
`ipareplica_no_pkinit` | Disables pkinit setup steps. (bool, default: false) | no
`ipareplica_no_ui_redirect` | Do not automatically redirect to the Web UI. (bool, default: false) | no
`ipareplica_dirsrv_config_file` | The path to LDIF file that will be used to modify configuration of dse.ldif during installation of the directory server instance. (string)| no
**ipaadmin_password** - The password for the kerberos principal.
(string, optional)
**ipaclient_domain** - The primary DNS domain of an existing IPA deployment.
(string, optional)
SSL certificate Variables
-------------------------
**ipaclient_realm** - The Kerberos realm of an existing IPA deployment.
(string, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipareplica_dirsrv_cert_files` | Files containing the Directory Server SSL certificate and private keys. (list of strings) | no
`ipareplica_http_cert_file` | File containing the Apache Server SSL certificate and private key. (string) | no
`ipareplica_pkinit_cert_file` | File containing the Kerberos KDC SSL certificate and private key. (string) | no
`ipareplica_dirsrv_pin` | The password to unlock the Directory Server private key. (string) | no
`ipareplica_http_pin` | The password to unlock the Apache Server private key. (string) | no
`ipareplica_pkinit_pin` | The password to unlock the Kerberos KDC private key. (string) | no
`ipareplica_dirsrv_cert_name` | Name of the Directory Server SSL certificate to install. (string) | no
`ipareplica_http_cert_name` | Name of the Apache Server SSL certificate to install. (string) | no
`ipareplica_pkinit_cert_name` | Name of the Kerberos KDC SSL certificate to install. (string) | no
**ipaclient_keytab** - The path to a backed-up host keytab from previous enrollment.
(string, optional)
Client Variables
----------------
**ipaclient_force_join** - Set force_join to yes to join the host even if it is already enrolled.
(bool, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipaclient_keytab` | Path to backed up keytab from previous enrollment. (string) | no
`ipaclient_mkhomedir` | Set to yes to configure PAM to create a users home directory if it does not exist. (string) | no
`ipaclient_force_join` | Force client enrollment even if already enrolled. (bool, default: false) | no
`ipaclient_ntp_servers` | The list defines the NTP servers to be used. (list of strings) | no
`ipaclient_ntp_pool` | The string value defines the ntp server pool to be used. (string) | no
`ipaclient_no_ntp` | The bool value defines if NTP will not be configured and enabled. (bool, default: false) | no
`ipaclient_ssh_trust_dns` | The bool value defines if OpenSSH client will be configured to trust DNS SSHFP records. (bool, default: false) | no
`ipaclient_no_ssh` | The bool value defines if OpenSSH client will be configured. (bool, default: false) | no
`ipaclient_no_sshd` | The bool value defines if OpenSSH server will be configured. (bool, default: false) | no
`ipaclient_no_sudo` | The bool value defines if SSSD will be configured as a data source for sudo. (bool, default: false) | no
`ipaclient_no_dns_sshfp` | The bool value defines if DNS SSHFP records will not be created automatically. (bool, default: false) | no
**ipaclient_use_otp** - Enforce the generation of a one time password to configure new and existing hosts. The enforcement on an existing host is not done if there is a working krb5.keytab on the host. If the generation of an otp is enforced for an existing host entry, then the host gets diabled and the containing keytab gets removed.
(bool, optional)
Certificate system Variables
----------------------------
**ipaclient_allow_repair** - Allow repair of already joined hosts. Contrary to ipaclient_force_join the host entry will not be changed on the server.
(bool, optional)
Variable | Description | Required
-------- | ----------- | --------
~~`ipareplica_skip_schema_check`~~ | ~~Skip check for updated CA DS schema on the remote master. (bool, default: false)~~ | ~~no~~
**ipaclient_kinit_attempts** - Repeat the request for host Kerberos ticket X times if it fails.
(int, optional)
DNS Variables
-------------
**ipaclient_no_ntp** - Set to yes to not configure and enable NTP
(bool, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipareplica_allow_zone_overlap` | Allow creation of (reverse) zone even if the zone is already resolvable. (bool, default: false) | no
`ipareplica_reverse_zones` | The reverse DNS zones to use. (list of strings) | no
`ipareplica_no_reverse` | Do not create reverse DNS zone. (bool, default: false) | no
`ipareplica_auto_reverse` | Try to resolve reverse records and reverse zones for server IP addresses. (bool, default: false) | no
`ipareplica_zonemgr` | The e-mail address of the DNS zone manager. (string, default: hostmaster@DOMAIN.) | no
`ipareplica_forwarders` | Add DNS forwarders to the DNS configuration. (list of strings) | no
`ipareplica_no_forwarders` | Do not add any DNS forwarders. Root DNS servers will be used instead. (bool, default: false) | no
`ipareplica_auto_forwarders` | Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS. (bool, default: false) | no
`ipareplica_forward_policy` | DNS forwarding policy for global forwarders specified using other options. (choice: first,only) | no
`ipareplica_no_dnssec_validation` | Disable DNSSEC validation on this server. (bool, default: false) | no
**ipaclient_mkhomedir** - Set to yes to configure PAM to create a users home directory if it does not exist.
(string, optional)
AD trust Variables
------------------
Variable | Description | Required
-------- | ----------- | --------
~~`ipareplica_add_sids`~~ | ~~Add SIDs for existing users and groups as the final step. (bool, default: false)~~ | ~~no~~
~~`ipareplica_add_agents`~~ | ~~Add IPA masters to a list of hosts allowed to serve information about users from trusted forests. (bool, default: false)~~ | ~~no~~
`ipareplica_enable_compat`| Enables support for trusted domains users for old clients through Schema Compatibility plugin. (bool, default: false) | no
`ipareplica_netbios_name` | The NetBIOS name for the IPA domain. (string) | no
`ipareplica_rid_base` | First RID value of the local domain. (integer) | no
`ipareplica_secondary_rid_base` | Start value of the secondary RID range. (integer) | no
Cluster Specific Variables
--------------------------
**ipaclient_no_dns_lookup** - Set to 'yes' to use groups.ipaserver in cluster environments as servers for the clients. This deactivates DNS lookup in krb5.
(bool, optional, default: 'no')
Variable | Description | Required
-------- | ----------- | --------
`ipareplica_servers` | Manually override list of servers for example in a cluster environment on a per replica basis. The list of servers is normally taken from from groups.ipaserver in cluster environments. (list of strings) | no
`ipaserver_domain` | Used if set in a cliuster environment to overload `ipareplica_domain` | no
**ipareplica_servers** - Manually override list of servers for example in a cluster environment on a per client basis. The list of servers is normally taken from from groups.ipaserver in cluster environments.
(list of strings, optional)
Special Variables
-----------------
Requirements
------------
Variable | Description | Required
-------- | ----------- | --------
`ipareplica_install_packages` | The bool value defines if the needed packages are installed on the node. (bool, default: true) | no
`ipareplica_setup_firewalld` | The value defines if the needed services will automatically be openen in the firewall managed by firewalld. (bool, default: true) | no
freeipa-server v4.6 or later
Authors
-------
Florence Blanc-Renaud
=======
Thomas Woerner

View File

@@ -38,20 +38,20 @@ description:
Add to ipaservers
options:
setup_kra:
description:
required: yes
description: Configure a dogtag KRA
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
installer_ccache:
description:
required: yes
description: The installer ccache setting
required: no
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
author:
- Thomas Woerner
'''
@@ -62,21 +62,32 @@ EXAMPLES = '''
RETURN = '''
'''
import os
import six
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_remote_api, api
)
if six.PY3:
unicode = str
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### server ###
argument_spec=dict(
# server
setup_kra=dict(required=True, type='bool'),
### additional ###
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
installer_ccache=dict(required=True),
_top_dir = dict(required=True),
_top_dir=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -85,33 +96,30 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_kra = ansible_module.params.get('setup_kra')
### additional ###
config_master_host_name = ansible_module.params.get('config_master_host_name')
# additional
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._ccache = ansible_module.params.get('installer_ccache')
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
options._top_dir = ansible_module.params.get('_top_dir')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALLER ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
#config = gen_ReplicaConfig()
# config = gen_ReplicaConfig()
remote_api = gen_remote_api(config_master_host_name, paths.ETC_IPA)
#installer._remote_api = remote_api
# installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
@@ -134,5 +142,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -45,7 +45,7 @@ options:
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: no
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
@@ -56,83 +56,73 @@ options:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description: List of iles containing CA certificates for the service certificate files
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
setup_adtrust:
description:
description: Configure AD trust capability
required: yes
setup_ca:
description:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
setup_dns:
description:
description: Configure bind with our zone
required: yes
dirserv_cert_files:
description:
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
force_join:
description:
description: Force client enrollment even if already enrolled
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
server:
description:
required: yes
description: Fully qualified name of IPA server to enroll to
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
installer_ccache:
description:
required: yes
description: The installer ccache setting
required: no
_ca_enabled:
description:
required: yes
_kra_enabled:
description:
required: yes
_dirsrv_pkcs12_info:
description:
required: yes
_http_pkcs12_info:
description:
required: yes
_pkinit_pkcs12_info:
description:
description: The installer _ca_enabled setting
required: yes
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
_add_to_ipaservers:
description:
required: yes
description: The installer _add_to_ipaservers setting
required: no
_ca_subject:
description:
required: yes
description: The installer _ca_subject setting
required: no
_subject_base:
description:
description: The installer _subject_base setting
required: no
master:
description: Master host name
required: yes
dirman_password:
description:
required: yes
config_setup_ca:
description:
required: yes
config_master_host_name:
description:
required: yes
config_ca_host_name:
description:
required: yes
config_ips:
description:
required: yes
description: Directory Manager (master) password
required: no
author:
- Thomas Woerner
'''
@@ -143,13 +133,21 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
ansible_module_get_parsed_ip_addresses, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, create_ipa_conf
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
dm_password=dict(required=False, no_log=True),
password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
@@ -158,35 +156,33 @@ def main():
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
### server ###
# server
setup_adtrust=dict(required=False, type='bool'),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
### ssl certificate ###
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
### client ###
# client
force_join=dict(required=False, type='bool'),
### certificate system ###
# certificate system
subject_base=dict(required=True),
### additional ###
# additional
server=dict(required=True),
config_master_host_name=dict(required=True),
config_ca_host_name=dict(required=True),
ccache=dict(required=True),
installer_ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_kra_enabled=dict(required=False, type='bool'),
_dirsrv_pkcs12_info = dict(required=False),
_http_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_add_to_ipaservers = dict(required=True, type='bool'),
_top_dir=dict(required=True),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
master=dict(required=False, default=None),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -205,16 +201,16 @@ def main():
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
### server ###
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
### ssl certificate ###
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
### client ###
# client
options.force_join = ansible_module.params.get('force_join')
### certificate system ###
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
@@ -222,37 +218,34 @@ def main():
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options.ca_subject = ansible_module.params.get('ca_subject')
### additional ###
#options._host_name_overridden = ansible_module.params.get(
# '_hostname_overridden')
# additional
# options._host_name_overridden = ansible_module.params.get(
# '_hostname_overridden')
options.server = ansible_module.params.get('server')
master_host_name = ansible_module.params.get('config_master_host_name')
ca_host_name = ansible_module.params.get('config_ca_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
kra_enabled = ansible_module.params.get('_kra_enabled')
dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
http_pkcs12_info = ansible_module.params.get('_http_pkcs12_info')
pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options._top_dir = ansible_module.params.get('_top_dir')
options._add_to_ipaservers = ansible_module.params.get('_add_to_ipaservers')
options._add_to_ipaservers = ansible_module.params.get(
'_add_to_ipaservers')
options._ca_subject = ansible_module.params.get('_ca_subject')
options._subject_base = ansible_module.params.get('_subject_base')
master = ansible_module.params.get('master')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
# prepare (install prepare, install checks) #
@@ -267,15 +260,13 @@ def main():
config = gen_ReplicaConfig()
config.subject_base = options.subject_base
config.dirman_password = dirman_password
config.ca_host_name = ca_host_name
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
cafile = paths.IPA_CA_CRT
if promote:
ansible_log.debug("-- CREATE_IPA_CONF --")
# Create the management framework config file. Do this irregardless
@@ -284,11 +275,12 @@ def main():
# successful uninstallation
# The configuration creation has to be here otherwise previous call
# To config certmonger would try to connect to local server
create_ipa_conf(fstore, config, ca_enabled)
create_ipa_conf(fstore, config, ca_enabled, master)
# done #
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -38,44 +38,52 @@ description:
Import dm password into custodia
options:
setup_ca:
description:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
required: yes
config_master_host_name:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_ca_enabled:
description:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description:
description: The installer _ca_file setting
required: yes
_dirsrv_pkcs12_info:
description:
_kra_enabled:
description: The installer _kra_enabled setting
required: yes
_pkinit_pkcs12_info:
description:
_kra_host_name:
description: The installer _kra_host_name setting
required: yes
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
dirman_password:
description:
required: yes
description: Directory Manager (master) password
required: no
config_setup_ca:
description: The config setup_ca setting
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
author:
- Thomas Woerner
'''
@@ -86,32 +94,40 @@ EXAMPLES = '''
RETURN = '''
'''
import os
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, redirect_stdout, custodiainstance
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
#### additional ###
# additional
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_dirsrv_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
config_ca_host_name=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -120,23 +136,23 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
#installer._ccache = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
kra_enabled = ansible_module.params.get('_kra_enabled')
kra_host_name = ansible_module.params.get('_kra_host_name')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
config_setup_ca = ansible_module.params.get('config_setup_ca')
@@ -144,9 +160,6 @@ def main():
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
@@ -161,11 +174,12 @@ def main():
config.ca_host_name = config_ca_host_name
config.subject_base = options.subject_base
config.promote = installer.promote
config.kra_enabled = kra_enabled
config.kra_host_name = kra_host_name
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# do the work #
@@ -193,5 +207,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -37,6 +37,55 @@ short description: DS apply updates
description:
DS apply updates
options:
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description: The installer _ca_file setting
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
ds_ca_subject:
description: The ds.ca_subject setting
required: no
author:
- Thomas Woerner
'''
@@ -47,32 +96,40 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout,
replica_ds_init_info, dsinstance, upgradeinstance, installutils
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
dirsrv_config_file=dict(required=False),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
#### additional ###
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_dirsrv_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_dirsrv_pkcs12_info=dict(required=False),
_pkinit_pkcs12_info=dict(required=False),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
ds_ca_subject=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -81,38 +138,37 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get('dirsrv_config_file')
### certificate system ###
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
#installer._ccache = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
installer._dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
installer._pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
installer._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
installer._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
ds_ca_subject = ansible_module.params.get('ds_ca_subject')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
pkinit_pkcs12_info = installer._pkinit_pkcs12_info
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
@@ -122,17 +178,15 @@ def main():
config.subject_base = options.subject_base
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
#installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
# ntpinstance
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
cafile = paths.IPA_CA_CRT
with redirect_stdout(ansible_log):
ds = replica_ds_init_info(ansible_log,
config, options, ca_enabled,
@@ -145,8 +199,8 @@ def main():
# Apply any LDAP updates. Needs to be done after the replica is
# synced-up
#service.print_msg("Applying LDAP updates")
#ds.apply_updates()
# service.print_msg("Applying LDAP updates")
# ds.apply_updates()
schema_files = dsinstance.get_all_external_schema_files(
paths.EXTERNAL_SCHEMA_DIR)
data_upgrade = upgradeinstance.IPAUpgrade(ds.realm,
@@ -163,5 +217,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -38,44 +38,51 @@ description:
DS enable SSL
options:
setup_ca:
description:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description:
description: Disable pkinit setup steps
required: yes
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_ca_enabled:
description:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description:
description: The installer _ca_file setting
required: yes
_dirsrv_pkcs12_info:
description:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_pkinit_pkcs12_info:
description:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
dirman_password:
description:
required: yes
description: Directory Manager (master) password
required: no
ds_ca_subject:
description:
required: yes
description: The ds.ca_subject setting
required: no
author:
- Thomas Woerner
'''
@@ -86,31 +93,39 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout,
replica_ds_init_info
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
dirsrv_config_file=dict(required=False),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
#### additional ###
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_dirsrv_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_dirsrv_pkcs12_info=dict(required=False),
_pkinit_pkcs12_info=dict(required=False),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
ds_ca_subject=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -119,38 +134,37 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get('dirsrv_config_file')
### certificate system ###
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
#installer._ccache = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
options._dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
options._pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
options._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
ds_ca_subject = ansible_module.params.get('ds_ca_subject')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
pkinit_pkcs12_info = installer._pkinit_pkcs12_info
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
@@ -160,7 +174,7 @@ def main():
config.subject_base = options.subject_base
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
#installer._remote_api = remote_api
# installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
@@ -187,5 +201,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -33,25 +33,36 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: ipareplica_enable_ipa
short description:
short description: Enable IPA
description: Enable IPA
Enable IPA
options:
hostname:
description: Fully qualified name of this host
required: yes
hidden_replica:
description: Install a hidden replica
required: yes
subject_base:
description: The certificate subject base (default O=<realm-name>).
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description: The installation specific ccache file.
required: yes
description: The local ccache
required: no
_top_dir:
description: The temporary top directory used for the installation.
required: yes
description: The installer _top_dir setting
required: no
setup_ca:
description: Configure a dogtag CA
required: yes
required: no
setup_kra:
description: Configure a dogtag KRA
required: no
config_master_host_name:
description: The master host name
required: yes
description: The config master_host_name setting
required: no
author:
- Thomas Woerner
'''
@@ -62,24 +73,33 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, service,
find_providing_servers, services
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
hostname=dict(required=False),
hidden_replica=dict(required=False, type='bool', default=False),
### server ###
### certificate system ###
# server
# certificate system
subject_base=dict(required=True),
### additional ###
# additional
ccache=dict(required=True),
_top_dir = dict(required=True),
_top_dir=dict(required=True),
setup_ca=dict(required=True, type='bool'),
setup_kra=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -90,27 +110,24 @@ def main():
options = installer
options.host_name = ansible_module.params.get('hostname')
options.hidden_replica = ansible_module.params.get('hidden_replica')
### server ###
### certificate system ###
# server
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
options.setup_ca = ansible_module.params.get('setup_ca')
config_master_host_name = ansible_module.params.get('config_master_host_name')
options.setup_kra = ansible_module.params.get('setup_kra')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
@@ -119,7 +136,6 @@ def main():
remote_api = gen_remote_api(config_master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
api.Backend.ldap2.connect()
@@ -153,5 +169,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -45,7 +45,7 @@ options:
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: no
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
@@ -56,37 +56,72 @@ options:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description: List of iles containing CA certificates for the service certificate files
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
setup_adtrust:
description:
required: yes
setup_kra:
description:
required: yes
setup_dns:
description:
required: yes
external_ca:
description:
required: yes
external_cert_files:
description:
required: yes
subject_base:
description:
required: yes
ca_subject:
description:
description: Configure AD trust capability
required: yes
setup_ca:
description:
description: Configure a dogtag CA
required: yes
_hostname_overridden:
description:
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
force_join:
description: Force client enrollment even if already enrolled
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
server:
description: Fully qualified name of IPA server to enroll to
required: no
ccache:
description: The local ccache
required: no
installer_ccache:
description: The installer ccache setting
required: no
_top_dir:
description: The installer _top_dir setting
required: no
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
required: no
_ca_subject:
description: The installer _ca_subject setting
required: no
_subject_base:
description: The installer _subject_base setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
config_setup_ca:
description: The config setup_ca setting
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
config_ips:
description: The config ips setting
required: yes
author:
- Thomas Woerner
@@ -98,13 +133,22 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
ansible_module_get_parsed_ip_addresses,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, ipaldap,
install_ca_cert
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
dm_password=dict(required=False, no_log=True),
password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
@@ -113,28 +157,23 @@ def main():
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
### server ###
# server
setup_adtrust=dict(required=False, type='bool'),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
### ssl certificate ###
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
### client ###
# client
force_join=dict(required=False, type='bool'),
### certificate system ###
# certificate system
subject_base=dict(required=True),
### additional ###
# additional
server=dict(required=True),
ccache=dict(required=True),
installer_ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_kra_enabled=dict(required=False, type='bool'),
_dirsrv_pkcs12_info = dict(required=False),
_http_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_add_to_ipaservers = dict(required=True, type='bool'),
_top_dir=dict(required=True),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
dirman_password=dict(required=True, no_log=True),
@@ -143,7 +182,7 @@ def main():
config_ca_host_name=dict(required=True),
config_ips=dict(required=False, type='list', default=[]),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -152,7 +191,7 @@ def main():
# get parameters #
options = installer
### basic ###
# basic
options.dm_password = ansible_module.params.get('dm_password')
options.password = options.dm_password
options.admin_password = ansible_module.params.get('password')
@@ -163,16 +202,16 @@ def main():
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
### server ###
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
### ssl certificate ###
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
### client ###
# client
options.force_join = ansible_module.params.get('force_join')
### certificate system ###
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
@@ -180,36 +219,30 @@ def main():
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options.ca_subject = ansible_module.params.get('ca_subject')
### additional ###
# additional
options.server = ansible_module.params.get('server')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
kra_enabled = ansible_module.params.get('_kra_enabled')
dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
http_pkcs12_info = ansible_module.params.get('_http_pkcs12_info')
pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options._top_dir = ansible_module.params.get('_top_dir')
options._add_to_ipaservers = ansible_module.params.get('_add_to_ipaservers')
options._add_to_ipaservers = ansible_module.params.get(
'_add_to_ipaservers')
options._ca_subject = ansible_module.params.get('_ca_subject')
options._subject_base = ansible_module.params.get('_subject_base')
dirman_password = ansible_module.params.get('dirman_password')
config_setup_ca = ansible_module.params.get('config_setup_ca')
config_master_host_name = ansible_module.params.get('config_master_host_name')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
config_ca_host_name = ansible_module.params.get('config_ca_host_name')
config_ips = ansible_module_get_parsed_ip_addresses(ansible_module,
"config_ips")
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALLER ==")
options = installer
@@ -247,7 +280,8 @@ def main():
ansible_log.debug("-- INSTALL_CA_CERT --")
# Update and istall updated CA file
cafile = install_ca_cert(conn, api.env.basedn, api.env.realm, cafile)
cafile = install_ca_cert(conn, api.env.basedn, api.env.realm,
cafile)
install_ca_cert(conn, api.env.basedn, api.env.realm, cafile,
destfile=paths.KDC_CA_BUNDLE_PEM)
install_ca_cert(conn, api.env.basedn, api.env.realm, cafile,
@@ -264,5 +298,6 @@ def main():
config_master_host_name=config.master_host_name,
config_ca_host_name=config.ca_host_name)
if __name__ == '__main__':
main()

View File

@@ -37,6 +37,41 @@ short description: KRB enable SSL
description:
KRB enable SSL
options:
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description: The installer _ca_file setting
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas Woerner
'''
@@ -47,29 +82,35 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, krbinstance, redirect_stdout
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
#### additional ###
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_dirsrv_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_pkinit_pkcs12_info=dict(required=False),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -78,36 +119,32 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
#installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
options._pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
options._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
pkinit_pkcs12_info = installer._pkinit_pkcs12_info
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
@@ -116,7 +153,7 @@ def main():
config.dirman_password = dirman_password
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
#installer._remote_api = remote_api
# installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
@@ -133,6 +170,8 @@ def main():
krb.init_info(api.env.realm, api.env.host,
setup_pkinit=not options.no_pkinit,
subject_base=options.subject_base)
krb.pkcs12_info = options._pkinit_pkcs12_info
krb.master_fqdn = master_host_name
ansible_log.debug("-- KRB ENABLE_SSL --")
@@ -143,5 +182,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -37,7 +37,7 @@ description:
options:
master_password:
description: kerberos master password (normally autogenerated)
required: false
required: yes
author:
- Thomas Woerner
'''
@@ -51,43 +51,31 @@ password:
returned: always
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
ipa_generate_password
)
def main():
module = AnsibleModule(
argument_spec = dict(
#basic
dm_password=dict(required=True, no_log=True),
argument_spec=dict(
# basic
master_password=dict(required=False, no_log=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
options.dm_password = module.params.get('dm_password')
options.master_password = module.params.get('master_password')
master_password = module.params.get('master_password')
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
# This will override any settings passed in on the cmdline
if os.path.isfile(paths.ROOT_IPA_CACHE):
# dm_password check removed, checked already
try:
cache_vars = read_cache(options.dm_password)
options.__dict__.update(cache_vars)
except Exception as e:
module.fail_json(msg="Cannot process the cache file: %s" % str(e))
if not options.master_password:
options.master_password = ipa_generate_password()
if not master_password:
master_password = ipa_generate_password()
module.exit_json(changed=True,
password=options.master_password)
password=master_password)
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load Diff

View File

@@ -38,23 +38,25 @@ description:
Promote openldap.conf
options:
setup_kra:
description:
required: no
description: Configure a dogtag KRA
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
config_setup_ca:
description:
required: yes
description: The config setup_ca setting
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
author:
- Thomas Woerner
'''
@@ -65,23 +67,30 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, redirect_stdout, promote_openldap_conf
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### server ###
argument_spec=dict(
# server
setup_kra=dict(required=False, type='bool'),
### certificate system ###
# certificate system
subject_base=dict(required=True),
### additional ###
# additional
ccache=dict(required=True),
_top_dir = dict(required=True),
_top_dir=dict(required=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -90,30 +99,25 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_kra = ansible_module.params.get('setup_kra')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
config_setup_ca = ansible_module.params.get('config_setup_ca')
installer.setup_ca = config_setup_ca
config_master_host_name = ansible_module.params.get('config_master_host_name')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
@@ -125,7 +129,6 @@ def main():
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
with redirect_stdout(ansible_log):
@@ -137,5 +140,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -38,23 +38,25 @@ description:
Promote sssd
options:
setup_kra:
description:
required: no
description: Configure a dogtag KRA
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
config_setup_ca:
description:
required: yes
description: The config setup_ca setting
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
author:
- Thomas Woerner
'''
@@ -65,23 +67,30 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, redirect_stdout, promote_sssd
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### server ###
argument_spec=dict(
# server
setup_kra=dict(required=False, type='bool'),
### certificate system ###
# certificate system
subject_base=dict(required=True),
### additional ###
# additional
ccache=dict(required=True),
_top_dir = dict(required=True),
_top_dir=dict(required=True),
config_setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -90,29 +99,25 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_kra = ansible_module.params.get('setup_kra')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
config_setup_ca = ansible_module.params.get('config_setup_ca')
installer.setup_ca = config_setup_ca
config_master_host_name = ansible_module.params.get('config_master_host_name')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
@@ -124,7 +129,6 @@ def main():
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
with redirect_stdout(ansible_log):
@@ -136,5 +140,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -37,6 +37,38 @@ short description: Restart KDC
description:
Restart KDC
options:
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
_ca_file:
description: The installer _ca_file setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
dirman_password:
description: Directory Manager (master) password
required: no
author:
- Thomas Woerner
'''
@@ -47,30 +79,35 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, service,
krbinstance
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
#### additional ###
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_dirsrv_pkcs12_info = dict(required=False),
#_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -79,36 +116,28 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
#installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
#pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
#pkinit_pkcs12_info = installer._pkinit_pkcs12_info
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
@@ -117,7 +146,6 @@ def main():
config.dirman_password = dirman_password
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
#installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
@@ -144,5 +172,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -38,23 +38,41 @@ description:
Setup adtrust
options:
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
subject_base:
description:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
enable_compat:
description: Enable support for trusted domains for old clients
required: yes
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
required: yes
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
required: yes
adtrust_netbios_name:
description: The adtrust netbios_name setting
required: no
adtrust_reset_netbios_name:
description: The adtrust reset_netbios_name setting
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
setup_ca:
description:
required: yes
description: Configure a dogtag CA
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
author:
- Thomas Woerner
'''
@@ -65,30 +83,37 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, adtrust
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### server ###
argument_spec=dict(
# server
setup_kra=dict(required=False, type='bool'),
### certificate system ###
# certificate system
subject_base=dict(required=True),
### ad trust ###
# ad trust
enable_compat=dict(required=False, type='bool', default=False),
rid_base=dict(required=False, type='int'),
secondary_rid_base=dict(required=False, type='int'),
### additional ###
# additional
adtrust_netbios_name=dict(required=True),
adtrust_reset_netbios_name=dict(required=True, type='bool'),
### additional ###
# additional
ccache=dict(required=True),
_top_dir = dict(required=True),
_top_dir=dict(required=True),
setup_ca=dict(required=True),
config_master_host_name=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -97,34 +122,34 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_kra = ansible_module.params.get('setup_kra')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### ad trust ###
# ad trust
options.enable_compat = ansible_module.params.get('enable_compat')
options.rid_base = ansible_module.params.get('rid_base')
options.secondary_rid_base = ansible_module.params.get('secondary_rid_base') ### additional ###
options.secondary_rid_base = ansible_module.params.get(
'secondary_rid_base')
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
options.setup_ca = ansible_module.params.get('setup_ca')
config_master_host_name = ansible_module.params.get('config_master_host_name')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
adtrust.netbios_name = ansible_module.params.get('adtrust_netbios_name')
adtrust.reset_netbios_name = \
ansible_module.params.get('adtrust_reset_netbios_name')
adtrust.reset_netbios_name = ansible_module.params.get(
'adtrust_reset_netbios_name')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
@@ -135,7 +160,6 @@ def main():
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
api.Backend.ldap2.connect()
@@ -149,5 +173,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -37,59 +37,67 @@ short description: Setup CA
description:
Setup CA
options:
pki_config_override:
description: Path to ini file with config overrides
required: yes
setup_ca:
description:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description:
required: yes
no_ui_redirect:
description:
description: Disable pkinit setup steps
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_ca_enabled:
description:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description:
description: The installer _ca_file setting
required: yes
_kra_enabled:
description: The installer _kra_enabled setting
required: yes
_kra_host_name:
description: The installer _kra_host_name setting
required: yes
_dirsrv_pkcs12_info:
description:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_pkinit_pkcs12_info:
description:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
_ca_subject:
description:
required: yes
description: The installer _ca_subject setting
required: no
_subject_base:
description:
required: yes
description: The installer _subject_base setting
required: no
dirman_password:
description:
required: yes
description: Directory Manager (master) password
required: no
config_setup_ca:
description:
required: yes
description: The config setup_ca setting
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
config_ca_host_name:
description:
required: yes
description: The config ca_host_name setting
required: no
config_ips:
description:
description: The config ips setting
required: yes
author:
- Thomas Woerner
@@ -101,26 +109,38 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
ansible_module_get_parsed_ip_addresses,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, ca,
custodiainstance
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# basic
pki_config_override=dict(required=False),
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
#### additional ###
# additional
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_dirsrv_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False),
_dirsrv_pkcs12_info=dict(required=False),
_pkinit_pkcs12_info=dict(required=False),
_top_dir=dict(required=True),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
dirman_password=dict(required=True, no_log=True),
@@ -129,7 +149,7 @@ def main():
config_ca_host_name=dict(required=True),
config_ips=dict(required=False, type='list', default=[]),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -138,22 +158,29 @@ def main():
# get parameters #
options = installer
### server ###
# basic
options.pki_config_override = ansible_module.params.get(
'pki_config_override')
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
#installer._ccache = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
installer._dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
installer._pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
kra_enabled = ansible_module.params.get('_kra_enabled')
kra_host_name = ansible_module.params.get('_kra_host_name')
installer._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
installer._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
options._ca_subject = ansible_module.params.get('_ca_subject')
if options._ca_subject is not None:
@@ -163,21 +190,17 @@ def main():
options._subject_base = DN(options._subject_base)
dirman_password = ansible_module.params.get('dirman_password')
config_setup_ca = ansible_module.params.get('config_setup_ca')
config_master_host_name = ansible_module.params.get('config_master_host_name')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
config_ca_host_name = ansible_module.params.get('config_ca_host_name')
config_ips = ansible_module_get_parsed_ip_addresses(ansible_module,
"config_ips")
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
pkinit_pkcs12_info = installer._pkinit_pkcs12_info
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
@@ -190,17 +213,18 @@ def main():
config.ca_host_name = config_ca_host_name
config.ips = config_ips
config.promote = options.promote
config.kra_enabled = kra_enabled
config.kra_host_name = kra_host_name
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
options._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
# ntpinstance
api.Backend.ldap2.connect()
#conn.connect(ccache=ccache)
# conn.connect(ccache=ccache)
ansible_log.debug("-- INSTALL CA --")
@@ -213,7 +237,10 @@ def main():
if not hasattr(custodiainstance, "get_custodia_instance"):
ca.install(False, config, options)
else:
if ca_enabled:
if kra_enabled:
# A KRA peer always provides a CA, too.
mode = custodiainstance.CustodiaModes.KRA_PEER
elif ca_enabled:
mode = custodiainstance.CustodiaModes.CA_PEER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
@@ -225,5 +252,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -48,13 +48,16 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, redirect_stdout, configure_certmonger
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -62,8 +65,6 @@ def main():
# get parameters #
options = installer
with redirect_stdout(ansible_log):
ansible_log.debug("-- CONFIGURE_CERTMONGER --")
@@ -74,5 +75,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -38,38 +38,49 @@ description:
Setup custodia
options:
setup_ca:
description:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_ca_enabled:
description:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description:
description: The installer _ca_file setting
required: yes
_kra_enabled:
description: The installer _kra_enabled setting
required: yes
_kra_host_name:
description: The installer _kra_host_name setting
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
dirman_password:
description:
required: yes
description: Directory Manager (master) password
required: no
author:
- Thomas Woerner
'''
@@ -80,30 +91,38 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, custodiainstance
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
#### additional ###
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_dirsrv_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_kra_enabled=dict(required=False, type='bool'),
_kra_host_name=dict(required=False),
_pkinit_pkcs12_info=dict(required=False),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -112,36 +131,34 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
#installer._ccache = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
options._pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
kra_enabled = ansible_module.params.get('_kra_enabled')
kra_host_name = ansible_module.params.get('_kra_host_name')
options._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
pkinit_pkcs12_info = installer._pkinit_pkcs12_info
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
@@ -149,9 +166,10 @@ def main():
config = gen_ReplicaConfig()
config.dirman_password = dirman_password
config.promote = installer.promote
config.kra_enabled = kra_enabled
config.kra_host_name = kra_host_name
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
#installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
@@ -167,14 +185,18 @@ def main():
if not hasattr(custodiainstance, "get_custodia_instance"):
custodia = custodiainstance.CustodiaInstance(config.host_name,
config.realm_name)
if promote:
if promote and \
hasattr(custodiainstance.CustodiaInstance, "create_replica"):
ansible_log.debug("-- CUSTODIA CREATE_REPLICA --")
custodia.create_replica(config.master_host_name)
else:
ansible_log.debug("-- CUSTODIA CREATE_INSTANCE --")
custodia.create_instance()
else:
if ca_enabled:
if kra_enabled:
# A KRA peer always provides a CA, too.
mode = custodiainstance.CustodiaModes.KRA_PEER
elif ca_enabled:
mode = custodiainstance.CustodiaModes.CA_PEER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
@@ -185,5 +207,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -38,26 +38,46 @@ description:
Setup DNS
options:
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
setup_dns:
description:
description: Configure bind with our zone
required: yes
subject_base:
description:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
zonemgr:
description: DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN
required: yes
forwarders:
description: Add DNS forwarders
required: yes
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
dns_ip_addresses:
description: The dns ip_addresses setting
required: no
dns_reverse_zones:
description: The dns reverse_zones setting
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
setup_ca:
description:
required: yes
description: Configure a dogtag CA
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
author:
- Thomas Woerner
'''
@@ -68,30 +88,40 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, dns,
ansible_module_get_parsed_ip_addresses
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### server ###
argument_spec=dict(
# server
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
### certificate system ###
# certificate system
subject_base=dict(required=True),
### dns ###
# dns
zonemgr=dict(required=False),
forwarders=dict(required=False, type='list', default=[]),
forward_policy=dict(default=None, choices=['first', 'only']),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
### additional ###
# additional
dns_ip_addresses=dict(required=True, type='list'),
dns_reverse_zones=dict(required=True, type='list'),
ccache=dict(required=True),
_top_dir = dict(required=True),
_top_dir=dict(required=True),
setup_ca=dict(required=True, type='bool'),
config_master_host_name=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -100,35 +130,34 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### dns ###
# dns
options.zonemgr = ansible_module.params.get('zonemgr')
options.forwarders = ansible_module.params.get('forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
options.no_dnssec_validation = ansible_module.params.get(
'no_dnssec_validationdnssec_validation')
### additional ###
# additional
dns.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module, 'dns_ip_addresses')
dns.reverse_zones = ansible_module.params.get('dns_reverse_zones')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
options._top_dir = ansible_module.params.get('_top_dir')
options.setup_ca = ansible_module.params.get('setup_ca')
config_master_host_name = ansible_module.params.get('config_master_host_name')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
api_bootstrap_finalize(env)
@@ -139,7 +168,6 @@ def main():
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
@@ -158,5 +186,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -45,7 +45,7 @@ options:
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: no
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
@@ -56,82 +56,86 @@ options:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description: List of iles containing CA certificates for the service certificate files
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
setup_adtrust:
description:
description: Configure AD trust capability
required: yes
setup_ca:
description:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
setup_dns:
description:
description: Configure bind with our zone
required: yes
dirserv_cert_files:
description:
no_pkinit:
description: Disable pkinit setup steps
required: yes
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
force_join:
description:
description: Force client enrollment even if already enrolled
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
server:
description:
required: yes
description: Fully qualified name of IPA server to enroll to
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
installer_ccache:
description:
required: yes
description: The installer ccache setting
required: no
_ca_enabled:
description:
required: yes
_kra_enabled:
description:
description: The installer _ca_enabled setting
required: yes
_dirsrv_pkcs12_info:
description:
required: yes
_http_pkcs12_info:
description:
required: yes
_pkinit_pkcs12_info:
description:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
_add_to_ipaservers:
description:
required: yes
description: The installer _add_to_ipaservers setting
required: no
_ca_subject:
description:
required: yes
description: The installer _ca_subject setting
required: no
_subject_base:
description:
required: yes
description: The installer _subject_base setting
required: no
dirman_password:
description:
required: yes
description: Directory Manager (master) password
required: no
config_setup_ca:
description:
required: yes
description: The config setup_ca setting
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
config_ca_host_name:
description:
required: yes
description: The config ca_host_name setting
required: no
config_ips:
description:
description: The config ips setting
required: yes
author:
- Thomas Woerner
@@ -143,13 +147,23 @@ EXAMPLES = '''
RETURN = '''
'''
import os
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths, sysrestore,
ansible_module_get_parsed_ip_addresses,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, redirect_stdout, ipaldap,
install_replica_ds, install_dns_records, ntpinstance, ScriptError
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
dm_password=dict(required=False, no_log=True),
password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
@@ -158,30 +172,27 @@ def main():
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
### server ###
# server
setup_adtrust=dict(required=False, type='bool'),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False),
### ssl certificate ###
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
### client ###
# client
force_join=dict(required=False, type='bool'),
### certificate system ###
# certificate system
subject_base=dict(required=True),
### additional ###
# additional
server=dict(required=True),
ccache=dict(required=True),
installer_ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_kra_enabled=dict(required=False, type='bool'),
_dirsrv_pkcs12_info = dict(required=False),
_http_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_add_to_ipaservers = dict(required=True, type='bool'),
_dirsrv_pkcs12_info=dict(required=False),
_top_dir=dict(required=True),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
dirman_password=dict(required=True, no_log=True),
@@ -190,7 +201,7 @@ def main():
config_ca_host_name=dict(required=True),
config_ips=dict(required=False, type='list', default=[]),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -209,18 +220,19 @@ def main():
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
### server ###
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get('dirsrv_config_file')
### ssl certificate ###
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
### client ###
# client
options.force_join = ansible_module.params.get('force_join')
### certificate system ###
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
@@ -228,34 +240,33 @@ def main():
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options.ca_subject = ansible_module.params.get('ca_subject')
### additional ###
#options._host_name_overridden = ansible_module.params.get(
# '_hostname_overridden')
# additional
# options._host_name_overridden = ansible_module.params.get(
# '_hostname_overridden')
options.server = ansible_module.params.get('server')
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
kra_enabled = ansible_module.params.get('_kra_enabled')
dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
http_pkcs12_info = ansible_module.params.get('_http_pkcs12_info')
pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options._top_dir = ansible_module.params.get('_top_dir')
options._add_to_ipaservers = ansible_module.params.get('_add_to_ipaservers')
options._add_to_ipaservers = ansible_module.params.get(
'_add_to_ipaservers')
options._ca_subject = ansible_module.params.get('_ca_subject')
options._subject_base = ansible_module.params.get('_subject_base')
dirman_password = ansible_module.params.get('dirman_password')
config_setup_ca = ansible_module.params.get('config_setup_ca')
config_master_host_name = ansible_module.params.get('config_master_host_name')
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
config_ca_host_name = ansible_module.params.get('config_ca_host_name')
config_ips = ansible_module_get_parsed_ip_addresses(ansible_module,
"config_ips")
@@ -263,7 +274,6 @@ def main():
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
@@ -338,6 +348,9 @@ def main():
if ntpinstance is not None:
ntpinstance.ntp_ldap_enable(config.host_name, ds.suffix,
remote_api.env.realm)
except (ScriptError, RuntimeError) as e:
ansible_module.fail_json(msg=str(e))
finally:
if conn.isconnected():
ansible_log.debug("-- DISCONNECT --")
@@ -349,5 +362,6 @@ def main():
ds_suffix=str(ds.suffix),
ds_ca_subject=str(ds.ca_subject))
if __name__ == '__main__':
main()

View File

@@ -38,41 +38,46 @@ description:
Setup HTTP
options:
setup_ca:
description:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
config_ca_host_name:
description: The config ca_host_name setting
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_ca_enabled:
description:
description: The installer _ca_enabled setting
required: yes
_ca_file:
description:
description: The installer _ca_file setting
required: yes
_http_pkcs12_info:
description:
description: The installer _http_pkcs12_info setting
required: yes
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
dirman_password:
description:
required: yes
description: Directory Manager (master) password
required: no
author:
- Thomas Woerner
'''
@@ -83,29 +88,38 @@ EXAMPLES = '''
RETURN = '''
'''
import os
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, create_ipa_conf,
install_http
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
config_master_host_name=dict(required=True),
config_ca_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_http_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_http_pkcs12_info=dict(required=False),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -118,17 +132,17 @@ def main():
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.no_ui_redirect = ansible_module.params.get('no_ui_redirect')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ca_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
#installer._ccache = ansible_module.params.get('installer_ccache')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
http_pkcs12_info = ansible_module.params.get('_http_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
@@ -137,11 +151,9 @@ def main():
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
@@ -151,12 +163,12 @@ def main():
config.subject_base = options.subject_base
config.dirman_password = dirman_password
config.setup_ca = options.setup_ca
#config.master_host_name = master_host_name
# config.master_host_name = master_host_name
config.ca_host_name = ca_host_name
config.promote = installer.promote
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
#installer._remote_api = remote_api
# installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
@@ -221,5 +233,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -45,7 +45,7 @@ options:
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: no
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
@@ -56,22 +56,73 @@ options:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description: List of iles containing CA certificates for the service certificate files
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
pki_config_override:
description: Path to ini file with config overrides
required: yes
setup_adtrust:
description:
description: Configure AD trust capability
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
setup_dns:
description:
description: Configure bind with our zone
required: yes
external_ca:
description:
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
force_join:
description: Force client enrollment even if already enrolled
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
server:
description: Fully qualified name of IPA server to enroll to
required: no
config_master_host_name:
description: The config master_host_name setting
required: no
ccache:
description: The local ccache
required: no
installer_ccache:
description: The installer ccache setting
required: no
_ca_enabled:
description: The installer _ca_enabled setting
required: yes
_kra_enabled:
description: The installer _kra_enabled setting
required: yes
_kra_host_name:
description: The installer _kra_host_name setting
required: yes
_top_dir:
description: The installer _top_dir setting
required: no
_add_to_ipaservers:
description: The installer _add_to_ipaservers setting
required: no
_ca_subject:
description: The installer _ca_subject setting
required: no
_subject_base:
description: The installer _subject_base setting
required: no
author:
- Thomas Woerner
'''
@@ -82,13 +133,22 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
ansible_module_get_parsed_ip_addresses,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, custodiainstance,
kra
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
dm_password=dict(required=False, no_log=True),
password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
@@ -97,33 +157,32 @@ def main():
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
### server ###
pki_config_override=dict(required=False),
# server
setup_adtrust=dict(required=False, type='bool'),
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
setup_dns=dict(required=False, type='bool'),
### ssl certificate ###
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
### client ###
# client
force_join=dict(required=False, type='bool'),
### certificate system ###
# certificate system
subject_base=dict(required=True),
### additional ###
# additional
server=dict(required=True),
config_master_host_name=dict(required=True),
ccache=dict(required=True),
installer_ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_kra_enabled=dict(required=False, type='bool'),
_dirsrv_pkcs12_info = dict(required=False),
_http_pkcs12_info = dict(required=False),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_add_to_ipaservers = dict(required=True, type='bool'),
_kra_host_name=dict(required=False),
_top_dir=dict(required=True),
_add_to_ipaservers=dict(required=True, type='bool'),
_ca_subject=dict(required=True),
_subject_base=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -142,16 +201,18 @@ def main():
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
### server ###
options.pki_config_override = ansible_module.params.get(
'pki_config_override')
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
### ssl certificate ###
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
### client ###
# client
options.force_join = ansible_module.params.get('force_join')
### certificate system ###
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
@@ -159,7 +220,7 @@ def main():
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options.ca_subject = ansible_module.params.get('ca_subject')
### dns ###
# dns
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_reverse = ansible_module.params.get('auto_reverse')
@@ -167,38 +228,32 @@ def main():
options.no_forwarders = ansible_module.params.get('no_forwarders')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
### additional ###
# additional
options.server = ansible_module.params.get('server')
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
#os.environ['KRB5CCNAME'] = ccache
# os.environ['KRB5CCNAME'] = ccache
os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
kra_enabled = ansible_module.params.get('_kra_enabled')
dirsrv_pkcs12_info = ansible_module.params.get('_dirsrv_pkcs12_info')
http_pkcs12_info = ansible_module.params.get('_http_pkcs12_info')
pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
kra_host_name = ansible_module.params.get('_kra_host_name')
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
options._top_dir = ansible_module.params.get('_top_dir')
options._add_to_ipaservers = ansible_module.params.get('_add_to_ipaservers')
options._add_to_ipaservers = ansible_module.params.get(
'_add_to_ipaservers')
options._ca_subject = ansible_module.params.get('_ca_subject')
options._subject_base = ansible_module.params.get('_subject_base')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
@@ -206,12 +261,13 @@ def main():
config = gen_ReplicaConfig()
config.subject_base = options.subject_base
config.promote = installer.promote
config.kra_enabled = kra_enabled
config.kra_host_name = kra_host_name
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# ccache = os.environ['KRB5CCNAME']
with redirect_stdout(ansible_log):
ansible_log.debug("-- INSTALL KRA --")
@@ -231,5 +287,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -38,29 +38,31 @@ description:
Setup KRB
options:
setup_ca:
description:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description:
description: Disable pkinit setup steps
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
ccache:
description:
required: yes
description: The local ccache
required: no
_pkinit_pkcs12_info:
description:
description: The installer _pkinit_pkcs12_info setting
required: yes
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
author:
- Thomas Woerner
'''
@@ -71,25 +73,33 @@ EXAMPLES = '''
RETURN = '''
'''
import os
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths, sysrestore,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, api, redirect_stdout, install_krb
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
#### additional ###
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_pkinit_pkcs12_info = dict(required=False),
_top_dir = dict(required=True),
_pkinit_pkcs12_info=dict(required=False),
_top_dir=dict(required=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -98,26 +108,27 @@ def main():
# get parameters #
options = installer
### server ###
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
config_master_host_name = ansible_module.params.get('config_master_host_name')
# additional
config_master_host_name = ansible_module.params.get(
'config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
installer._pkinit_pkcs12_info = ansible_module.params.get('_pkinit_pkcs12_info')
installer._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
options._top_dir = ansible_module.params.get('_top_dir')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
@@ -132,10 +143,6 @@ def main():
config.master_host_name = config_master_host_name
config.subject_base = options.subject_base
remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
#installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
# There is a api.Backend.ldap2.connect call somewhere in ca, ds, dns or
@@ -170,5 +177,6 @@ def main():
ansible_module.exit_json(changed=True,
config_master_host_name=config.master_host_name)
if __name__ == '__main__':
main()

View File

@@ -38,38 +38,37 @@ description:
Setup OTPD
options:
setup_ca:
description:
description: Configure a dogtag CA
required: yes
setup_kra:
description:
description: Configure a dogtag KRA
required: yes
no_pkinit:
description:
description: Disable pkinit setup steps
required: yes
no_ui_redirect:
description:
description: Do not automatically redirect to the Web UI
required: yes
subject_base:
description:
required: yes
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: no
config_master_host_name:
description:
required: yes
description: The config master_host_name setting
required: no
ccache:
description:
required: yes
_ca_enabled:
description:
required: yes
description: The local ccache
required: no
_ca_file:
description:
description: The installer _ca_file setting
required: yes
_top_dir:
description:
required: yes
description: The installer _top_dir setting
required: no
dirman_password:
description:
required: yes
description: Directory Manager (master) password
required: no
author:
- Thomas Woerner
'''
@@ -80,28 +79,35 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, installer, DN, paths,
gen_env_boostrap_finalize_core, constants, api_bootstrap_finalize,
gen_ReplicaConfig, gen_remote_api, api, redirect_stdout, otpdinstance,
ipautil
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
#### server ###
argument_spec=dict(
# server
setup_ca=dict(required=False, type='bool'),
setup_kra=dict(required=False, type='bool'),
no_pkinit=dict(required=False, type='bool'),
no_ui_redirect=dict(required=False, type='bool'),
#### certificate system ###
# certificate system
subject_base=dict(required=True),
#### additional ###
# additional
config_master_host_name=dict(required=True),
ccache=dict(required=True),
_ca_enabled=dict(required=False, type='bool'),
_ca_file=dict(required=False),
_top_dir = dict(required=True),
_top_dir=dict(required=True),
dirman_password=dict(required=True, no_log=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
@@ -113,29 +119,24 @@ def main():
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_kra = ansible_module.params.get('setup_kra')
options.no_pkinit = ansible_module.params.get('no_pkinit')
### certificate system ###
# certificate system
options.subject_base = ansible_module.params.get('subject_base')
if options.subject_base is not None:
options.subject_base = DN(options.subject_base)
### additional ###
# additional
master_host_name = ansible_module.params.get('config_master_host_name')
ccache = ansible_module.params.get('ccache')
os.environ['KRB5CCNAME'] = ccache
#os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
#installer._ccache = ansible_module.params.get('installer_ccache')
ca_enabled = ansible_module.params.get('_ca_enabled')
# os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
# installer._ccache = ansible_module.params.get('installer_ccache')
options._top_dir = ansible_module.params.get('_top_dir')
dirman_password = ansible_module.params.get('dirman_password')
# init #
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
ansible_log.debug("== INSTALL ==")
options = installer
promote = installer.promote
env = gen_env_boostrap_finalize_core(paths.ETC_IPA,
constants.DEFAULT_CONFIG)
@@ -144,7 +145,6 @@ def main():
config.dirman_password = dirman_password
remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
#installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
ccache = os.environ['KRB5CCNAME']
@@ -154,7 +154,6 @@ def main():
api.Backend.ldap2.connect()
conn.connect(ccache=ccache)
cafile = paths.IPA_CA_CRT
with redirect_stdout(ansible_log):
ansible_log.debug("-- INSTALL_OTPD --")
@@ -167,5 +166,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -31,9 +31,91 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: ipareplica_test
short description:
description:
short description: IPA replica deployment tests
description: IPA replica deployment tests
options:
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: yes
servers:
description: Fully qualified name of IPA servers to enroll to
required: yes
realm:
description: Kerberos realm name of the IPA deployment
required: yes
hostname:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
hidden_replica:
description: Install a hidden replica
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
required: yes
pkinit_cert_files:
description:
File containing the Kerberos KDC SSL certificate and private key
required: yes
no_ntp:
description: Do not configure ntp
required: yes
ntp_servers:
description: ntp servers to use
required: yes
ntp_pool:
description: ntp server pool to use
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_reverse:
description: Create necessary reverse zones
required: yes
forwarders:
description: Add DNS forwarders
required: yes
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
author:
- Thomas Woerner
'''
@@ -45,19 +127,24 @@ RETURN = '''
'''
import os
import sys
import logging
import tempfile, shutil
import inspect
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_replica import *
from ansible.module_utils.ansible_ipa_replica import (
AnsibleModuleLog, options, installer, paths, sysrestore,
ansible_module_get_parsed_ip_addresses, service,
redirect_stdout, create_ipa_conf, ipautil,
x509, validate_domain_name, common_check,
IPA_PYTHON_VERSION
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
#dm_password=dict(required=False, no_log=True),
#password=dict(required=False, no_log=True),
argument_spec=dict(
# basic
# dm_password=dict(required=False, no_log=True),
# password=dict(required=False, no_log=True),
ip_addresses=dict(required=False, type='list', default=[]),
domain=dict(required=False),
servers=dict(required=False, type='list', default=[]),
@@ -65,21 +152,21 @@ def main():
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', default=[]),
hidden_replica=dict(required=False, type='bool', default=False),
### server ###
# server
setup_adtrust=dict(required=False, type='bool', default=False),
setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
no_pkinit=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False),
### ssl certificate ###
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
http_cert_files=dict(required=False, type='list', default=[]),
pkinit_cert_files=dict(required=False, type='list', default=[]),
### client ###
# client
no_ntp=dict(required=False, type='bool', default=False),
ntp_servers=dict(required=False, type='list', default=[]),
ntp_pool=dict(required=False),
### dns ###
# dns
no_reverse=dict(required=False, type='bool', default=False),
auto_reverse=dict(required=False, type='bool', default=False),
forwarders=dict(required=False, type='list', default=[]),
@@ -96,10 +183,10 @@ def main():
# get parameters #
### basic ###
#options.dm_password = ansible_module.params.get('dm_password')
##options.password = ansible_module.params.get('password')
#options.password = options.dm_password
# basic
# options.dm_password = ansible_module.params.get('dm_password')
# # options.password = ansible_module.params.get('password')
# options.password = options.dm_password
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
@@ -108,21 +195,22 @@ def main():
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.hidden_replica = ansible_module.params.get('hidden_replica')
### server ###
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get('dirsrv_config_file')
### ssl certificate ###
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
options.http_cert_files = ansible_module.params.get('http_cert_files')
options.pkinit_cert_files = ansible_module.params.get('pkinit_cert_files')
### client ###
# client
options.no_ntp = ansible_module.params.get('no_ntp')
options.ntp_servers = ansible_module.params.get('ntp_servers')
options.ntp_pool = ansible_module.params.get('ntp_pool')
### dns ###
# dns
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_reverse = ansible_module.params.get('auto_reverse')
options.forwarders = ansible_module.params.get('forwarders')
@@ -141,12 +229,12 @@ def main():
else:
installer.server = None
# TODO: Kills ipa-client-install
#if installer.replica_file is None:
# installer.password = installer.admin_password
#else:
# installer.password = installer.dm_password
# if installer.replica_file is None:
# installer.password = installer.admin_password
# else:
# installer.password = installer.dm_password
#installer._ccache = os.environ.get('KRB5CCNAME')
# installer._ccache = os.environ.get('KRB5CCNAME')
# If not defined, set domain from server name
if installer.domain_name is None and installer.server is not None:
@@ -161,17 +249,17 @@ def main():
# version specific tests #
#if options.setup_adtrust and not adtrust_imported:
# #if "adtrust" not in options._allow_missing:
# if options.setup_adtrust and not adtrust_imported:
# # if "adtrust" not in options._allow_missing:
# ansible_module.fail_json(msg="adtrust can not be imported")
# #else:
# # else:
# # options.setup_adtrust = False
# # ansible_module.warn(msg="adtrust is not supported, disabling")
#if options.setup_kra and not kra_imported:
# #if "kra" not in options._allow_missing:
# if options.setup_kra and not kra_imported:
# # if "kra" not in options._allow_missing:
# ansible_module.fail_json(msg="kra can not be imported")
# #else:
# # else:
# # options.setup_kra = False
# # ansible_module.warn(msg="kra is not supported, disabling")
@@ -179,6 +267,14 @@ def main():
ansible_module.fail_json(
msg="Hidden replica is not supported in this version.")
# We need to point to the master in ipa default conf when certmonger
# asks for HTTP certificate in newer ipa versions. In these versions
# create_ipa_conf has the additional master argument.
change_master_for_certmonger = False
argspec = inspect.getargspec(create_ipa_conf)
if "master" in argspec.args:
change_master_for_certmonger = True
# From ipa installer classes
# pkinit is not supported on DL0, don't allow related options
@@ -264,32 +360,38 @@ def main():
msg="You must specify at least one of --forwarder, "
"--auto-forwarders, or --no-forwarders options")
if installer.dirsrv_config_file is not None and not os.path.exists(installer.dirsrv_config_file):
ansible_module.fail_json(msg="File %s does not exist." % installer.dirsrv_config_file)
if installer.dirsrv_config_file is not None and \
not os.path.exists(installer.dirsrv_config_file):
ansible_module.fail_json(
msg="File %s does not exist." % installer.dirsrv_config_file)
if installer.ca_cert_files is not None:
if not isinstance(installer.ca_cert_files, list):
ansible_module.fail_json(msg="Expected list, got {!r}".format(installer.ca_cert_files))
ansible_module.fail_json(
msg="Expected list, got {!r}".format(installer.ca_cert_files))
for cert in installer.ca_cert_files:
if not os.path.exists(cert):
ansible_module.fail_json(msg="'%s' does not exist" % cert)
if not os.path.isfile(cert):
ansible_module.fail_json(msg="'%s' is not a file" % cert)
if not os.path.isabs(cert):
ansible_module.fail_json(msg="'%s' is not an absolute file path" % cert)
ansible_module.fail_json(
msg="'%s' is not an absolute file path" % cert)
try:
x509.load_certificate_from_file(cert)
except Exception:
ansible_module.fail_json(msg="'%s' is not a valid certificate file" % cert)
ansible_module.fail_json(
msg="'%s' is not a valid certificate file" % cert)
if installer.ip_addresses is not None:
for value in installer.ip_addresses:
try:
CheckedIPAddress(value)
ipautil.CheckedIPAddress(value)
except Exception as e:
ansible_module.fail_json(msg="invalid IP address {0}: {1}".format(
value, e))
ansible_module.fail_json(
msg="invalid IP address {0}: {1}".format(
value, e))
if installer.domain_name is not None:
validate_domain_name(installer.domain_name)
@@ -302,7 +404,7 @@ def main():
try:
with redirect_stdout(ansible_log):
common_check(options.no_ntp)
except Exception as msg: #ScriptError as msg:
except Exception as msg: # ScriptError as msg:
_msg = str(msg)
if "server is already configured" in _msg:
ansible_module.exit_json(changed=False,
@@ -318,8 +420,8 @@ def main():
client_enrolled = client_fstore.has_files()
if not client_enrolled:
## One-step replica installation
#if options.dm_password and options.password:
# # One-step replica installation
# if options.dm_password and options.password:
# ansible_module.fail_json(
# msg="--password and --admin-password options are "
# "mutually exclusive")
@@ -332,19 +434,22 @@ def main():
# done #
ansible_module.exit_json(changed=False,
ipa_python_version=IPA_PYTHON_VERSION,
### basic ###
domain=options.domain_name,
realm=options.realm_name,
hostname=options.host_name,
### server ###
setup_adtrust=options.setup_adtrust,
setup_kra=options.setup_kra,
server=options.server,
### additional ###
client_enrolled=client_enrolled,
ansible_module.exit_json(
changed=False,
ipa_python_version=IPA_PYTHON_VERSION,
# basic
domain=options.domain_name,
realm=options.realm_name,
hostname=options.host_name,
# server
setup_adtrust=options.setup_adtrust,
setup_kra=options.setup_kra,
server=options.server,
# additional
client_enrolled=client_enrolled,
change_master_for_certmonger=change_master_for_certmonger,
)
if __name__ == '__main__':
main()

View File

@@ -22,10 +22,31 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
__all__ = ["contextlib", "dnsexception", "dnsresolver", "dnsreversename",
"parse_version", "IPAChangeConf",
"certstore", "sysrestore", "ipa_generate_password", "kinit_keytab",
"IPA_CA_TRUST_FLAGS", "EXTERNAL_CA_TRUST_FLAGS", "DN",
"ScriptError", "services", "tasks", "constants", "errors", "rpc",
"x509", "validate_domain_name",
"no_matching_interface_for_ip_address_warning",
"configure_krb5_conf", "purge_host_keytab", "adtrust",
"bindinstance", "ca", "certs", "dns", "httpinstance", "kra",
"otpdinstance", "custodiainstance", "service", "upgradeinstance",
"find_providing_servers", "find_providing_server", "load_pkcs12",
"is_ipa_configured", "ReplicationManager", "replica_conn_check",
"install_replica_ds", "install_krb", "install_ca_cert",
"install_http", "install_dns_records", "create_ipa_conf",
"check_dirsrv", "check_dns_resolution", "configure_certmonger",
"remove_replica_info_dir", "preserve_enrollment_state",
"uninstall_client", "promote_sssd", "promote_openldap_conf",
"rpc_client", "check_remote_fips_mode", "check_remote_version",
"common_check", "current_domain_level",
"check_domain_level_is_supported", "promotion_check_ipa_domain",
"SSSDConfig", "CalledProcessError", "timeconf", "ntpinstance",
"dnsname", "kernel_keyring", "krbinstance"]
import sys
import logging
import inspect
from contextlib import contextmanager as contextlib_contextmanager
@@ -33,7 +54,7 @@ from ipapython.version import NUM_VERSION, VERSION
if NUM_VERSION < 30201:
# See ipapython/version.py
IPA_MAJOR,IPA_MINOR,IPA_RELEASE = [ int(x) for x in VERSION.split(".", 2) ]
IPA_MAJOR, IPA_MINOR, IPA_RELEASE = [int(x) for x in VERSION.split(".", 2)]
IPA_PYTHON_VERSION = IPA_MAJOR*10000 + IPA_MINOR*100 + IPA_RELEASE
else:
IPA_PYTHON_VERSION = NUM_VERSION
@@ -48,14 +69,8 @@ if NUM_VERSION >= 40600:
import dns.name as dnsname
import dns.resolver as dnsresolver
import dns.reversename as dnsreversename
import os
import shutil
import socket
import tempfile
import traceback
from pkg_resources import parse_version
import six
from ipaclient.install.ipachangeconf import IPAChangeConf
from ipalib.install import certstore, sysrestore
@@ -93,21 +108,18 @@ if NUM_VERSION >= 40600:
make_pkcs12_info, install_replica_ds, install_krb, install_ca_cert,
install_http, install_dns_records, create_ipa_conf, check_dirsrv,
check_dns_resolution, configure_certmonger, remove_replica_info_dir,
#common_cleanup,
# common_cleanup,
preserve_enrollment_state, uninstall_client,
promote_sssd, promote_openldap_conf, rpc_client,
check_remote_fips_mode, check_remote_version, common_check,
current_domain_level, check_domain_level_is_supported,
#enroll_dl0_replica,
#ensure_enrolled,
# enroll_dl0_replica,
# ensure_enrolled,
promotion_check_ipa_domain
)
import SSSDConfig
from subprocess import CalledProcessError
if six.PY3:
unicode = str
try:
from ipaclient.install import timeconf
time_service = "chronyd"
@@ -128,11 +140,12 @@ else:
logger = logging.getLogger("ipa-server-install")
#logger.setLevel(logging.DEBUG)
# logger.setLevel(logging.DEBUG)
standard_logging_setup(
paths.IPAREPLICA_INSTALL_LOG, verbose=False, debug=False,
filemode='a', console_format='%(message)s')
@contextlib_contextmanager
def redirect_stdout(f):
sys.stdout = f
@@ -162,7 +175,7 @@ class AnsibleModuleLog():
pass
def log(self, msg):
#self.write(msg+"\n")
# self.write(msg+"\n")
self.write(msg)
def debug(self, msg):
@@ -173,7 +186,7 @@ class AnsibleModuleLog():
def write(self, msg):
self.module.debug(msg)
#self.module.warn(msg)
# self.module.warn(msg)
class installer_obj(object):
@@ -195,33 +208,34 @@ class installer_obj(object):
# others
self._ccache = None
self.password = None
self.reverse_zones = [ ]
#def _is_promote(self):
# return self.replica_file is None
#self.skip_conncheck = False
self.reverse_zones = []
# def _is_promote(self):
# return self.replica_file is None
# self.skip_conncheck = False
self._replica_install = False
#self.dnssec_master = False # future unknown
#self.disable_dnssec_master = False # future unknown
#self.domainlevel = MAX_DOMAIN_LEVEL # deprecated
#self.domain_level = self.domainlevel # deprecated
# self.dnssec_master = False # future unknown
# self.disable_dnssec_master = False # future unknown
# self.domainlevel = MAX_DOMAIN_LEVEL # deprecated
# self.domain_level = self.domainlevel # deprecated
self.interactive = False
self.unattended = not self.interactive
#self.promote = self.replica_file is None
# self.promote = self.replica_file is None
self.promote = True
self.skip_schema_check = None
#def __getattribute__(self, attr):
# value = super(installer_obj, self).__getattribute__(attr)
# if not attr.startswith("--") and not attr.endswith("--"):
# logger.debug(
# " <-- Accessing installer.%s (%s)" % (attr, repr(value)))
# return value
# def __getattribute__(self, attr):
# value = super(installer_obj, self).__getattribute__(attr)
# if not attr.startswith("--") and not attr.endswith("--"):
# logger.debug(
# " <-- Accessing installer.%s (%s)" % (attr, repr(value)))
# return value
def __getattr__(self, attr):
logger.info(" --> ADDING missing installer.%s" % attr)
logger.info(" --> ADDING missing installer.%s", attr)
setattr(self, attr, None)
return getattr(self, attr)
#def __setattr__(self, attr, value):
# def __setattr__(self, attr, value):
# logger.debug(" --> Setting installer.%s to %s" % (attr, repr(value)))
# return super(installer_obj, self).__setattr__(attr, value)
@@ -240,7 +254,7 @@ options.kasp_db_file = None
options.force = False
# ServerMasterInstall
options.add_sids = True
options.add_sids = False
options.add_agents = False
# ServerReplicaInstall
@@ -248,25 +262,10 @@ options.subject_base = None
options.ca_subject = None
def api_Backend_ldap2(host_name, setup_ca, connect=False):
# we are sure we have the configuration file ready.
cfg = dict(context='installer', confdir=paths.ETC_IPA, in_server=True,
host=host_name,
)
if setup_ca:
# we have an IPA-integrated CA
cfg['ca_host'] = host_name
api.bootstrap(**cfg)
api.finalize()
if connect:
api.Backend.ldap2.connect()
def gen_env_boostrap_finalize_core(etc_ipa, default_config):
env = Env()
#env._bootstrap(context='installer', confdir=paths.ETC_IPA, log=None)
#env._finalize_core(**dict(constants.DEFAULT_CONFIG))
# env._bootstrap(context='installer', confdir=paths.ETC_IPA, log=None)
# env._finalize_core(**dict(constants.DEFAULT_CONFIG))
env._bootstrap(context='installer', confdir=etc_ipa, log=None)
env._finalize_core(**dict(default_config))
return env
@@ -289,26 +288,27 @@ def gen_ReplicaConfig():
def __init__(self, top_dir=None):
super(ExtendedReplicaConfig, self).__init__(top_dir)
#def __getattribute__(self, attr):
# def __getattribute__(self, attr):
# value = super(ExtendedReplicaConfig, self).__getattribute__(attr)
# if attr not in [ "__dict__", "knobs" ]:
# logger.debug(" <== Accessing config.%s (%s)" % (attr, repr(value)))
# if attr not in ["__dict__", "knobs"]:
# logger.debug(" <== Accessing config.%s (%s)" %
# (attr, repr(value)))
# return value
def __getattr__(self, attr):
logger.info(" ==> ADDING missing config.%s" % attr)
logger.info(" ==> ADDING missing config.%s", attr)
setattr(self, attr, None)
return getattr(self, attr)
#def __setattr__(self, attr, value):
# logger.debug(" ==> Setting config.%s to %s" % (attr, repr(value)))
# return super(ExtendedReplicaConfig, self).__setattr__(attr, value)
# def __setattr__(self, attr, value):
# logger.debug(" ==> Setting config.%s to %s" % (attr, repr(value)))
# return super(ExtendedReplicaConfig, self).__setattr__(attr, value)
def knobs(self):
for name in self.__dict__:
yield self, name
#config = ReplicaConfig()
# config = ReplicaConfig()
config = ExtendedReplicaConfig()
config.realm_name = api.env.realm
config.host_name = api.env.host
@@ -321,45 +321,11 @@ def gen_ReplicaConfig():
config.setup_kra = options.setup_kra
config.dir = options._top_dir
config.basedn = api.env.basedn
#config.subject_base = options.subject_base
# config.subject_base = options.subject_base
return config
def ds_init_info(ansible_log, fstore, domainlevel, dirsrv_config_file,
realm_name, host_name, domain_name, dm_password,
idstart, idmax, subject_base, ca_subject,
#no_hbac_allow,
dirsrv_pkcs12_info, no_pkinit,
external_cert_files, dirsrv_cert_files):
if not external_cert_files:
ds = dsinstance.DsInstance(fstore=fstore, domainlevel=domainlevel,
config_ldif=dirsrv_config_file)
ds.set_output(ansible_log)
if dirsrv_cert_files:
_dirsrv_pkcs12_info = dirsrv_pkcs12_info
else:
_dirsrv_pkcs12_info = None
with redirect_stdout(ansible_log):
ds.init_info(realm_name, host_name, domain_name, dm_password,
subject_base, ca_subject, idstart, idmax,
#hbac_allow=not no_hbac_allow,
_dirsrv_pkcs12_info, setup_pkinit=not no_pkinit)
else:
ds = dsinstance.DsInstance(fstore=fstore, domainlevel=domainlevel)
ds.set_output(ansible_log)
with redirect_stdout(ansible_log):
ds.init_info(realm_name, host_name, domain_name, dm_password,
subject_base, ca_subject, 1101, 1100, None,
setup_pkinit=not no_pkinit)
return ds
def replica_ds_init_info(ansible_log,
config, options, ca_is_configured, remote_api,
ds_ca_subject, ca_file,
@@ -376,10 +342,10 @@ def replica_ds_init_info(ansible_log,
# during replica install, this gets invoked before local DS is
# available, so use the remote api.
#if ca_is_configured:
# ca_subject = ca.lookup_ca_subject(_api, config.subject_base)
#else:
# ca_subject = installutils.default_ca_subject_dn(config.subject_base)
# if ca_is_configured:
# ca_subject = ca.lookup_ca_subject(_api, config.subject_base)
# else:
# ca_subject = installutils.default_ca_subject_dn(config.subject_base)
ca_subject = ds_ca_subject
ds = dsinstance.DsInstance(
@@ -425,112 +391,9 @@ def replica_ds_init_info(ansible_log,
return ds
def krb_init_info(ansible_log, fstore, realm_name, host_name, no_pkinit,
subject_base):
krb = krbinstance.KrbInstance(fstore)
krb.set_output(ansible_log)
with redirect_stdout(ansible_log):
krb.init_info(realm_name, host_name, etup_pkinit=not no_pkinit,
subject_base=subject_base)
def replica_krb_init_info(ansible_log, fstore, realm_name, master_host_name,
host_name, domain_name, admin_password,
no_pkinit, subject_base, pkcs12_info=None):
# promote is not needed here
# From replicainstall.install_krb
krb = krbinstance.KrbInstance(fstore=fstore)
krb.set_output(ansible_log)
# pkinit files
if pkcs12_info is None:
pkcs12_info = make_pkcs12_info(config.dir, "pkinitcert.p12",
"pkinit_pin.txt")
#krb.create_replica(realm_name,
# master_host_name, host_name,
# domain_name, dirman_password,
# setup_pkinit, pkcs12_info,
# subject_base=subject_base,
# promote=promote)
with redirect_stdout(ansible_log):
krb.init_info(realm_name, host_name, setup_pkinit=not no_pkinit,
subject_base=subject_base)
# From ipaserver.install.krbinstance.create_replica
krb.pkcs12_info = pkcs12_info
krb.subject_base = subject_base
krb.master_fqdn = master_host_name
krb.config_pkinit = not no_pkinit
#krb.__common_setup(realm_name, host_name, domain_name, admin_password)
krb.fqdn = host_name
krb.realm = realm_name.upper()
krb.host = host_name.split(".")[0]
krb.ip = socket.getaddrinfo(host_name, None, socket.AF_UNSPEC, socket.SOCK_STREAM)[0][4][0]
krb.domain = domain_name
krb.suffix = ipautil.realm_to_suffix(krb.realm)
krb.kdc_password = ipautil.ipa_generate_password()
krb.admin_password = admin_password
krb.dm_password = admin_password
#krb.__setup_sub_dict()
if os.path.exists(paths.COMMON_KRB5_CONF_DIR):
includes = 'includedir {}'.format(paths.COMMON_KRB5_CONF_DIR)
else:
includes = ''
krb.sub_dict = dict(FQDN=krb.fqdn,
IP=krb.ip,
PASSWORD=krb.kdc_password,
SUFFIX=krb.suffix,
DOMAIN=krb.domain,
HOST=krb.host,
SERVER_ID=installutils.realm_to_serverid(krb.realm),
REALM=krb.realm,
KRB5KDC_KADM5_ACL=paths.KRB5KDC_KADM5_ACL,
DICT_WORDS=paths.DICT_WORDS,
KRB5KDC_KADM5_KEYTAB=paths.KRB5KDC_KADM5_KEYTAB,
KDC_CERT=paths.KDC_CERT,
KDC_KEY=paths.KDC_KEY,
CACERT_PEM=paths.CACERT_PEM,
KDC_CA_BUNDLE_PEM=paths.KDC_CA_BUNDLE_PEM,
CA_BUNDLE_PEM=paths.CA_BUNDLE_PEM,
INCLUDES=includes)
# IPA server/KDC is not a subdomain of default domain
# Proper domain-realm mapping needs to be specified
domain = dnsname.from_text(krb.domain)
fqdn = dnsname.from_text(krb.fqdn)
if not fqdn.is_subdomain(domain):
logger.debug("IPA FQDN '%s' is not located in default domain '%s'",
fqdn, domain)
server_domain = fqdn.parent().to_unicode(omit_final_dot=True)
logger.debug("Domain '%s' needs additional mapping in krb5.conf",
server_domain)
dr_map = " .%(domain)s = %(realm)s\n %(domain)s = %(realm)s\n" \
% dict(domain=server_domain, realm=krb.realm)
else:
dr_map = ""
krb.sub_dict['OTHER_DOMAIN_REALM_MAPS'] = dr_map
# Configure KEYRING CCACHE if supported
if kernel_keyring.is_persistent_keyring_supported():
logger.debug("Enabling persistent keyring CCACHE")
krb.sub_dict['OTHER_LIBDEFAULTS'] = \
" default_ccache_name = KEYRING:persistent:%{uid}\n"
else:
logger.debug("Persistent keyring CCACHE is not enabled")
krb.sub_dict['OTHER_LIBDEFAULTS'] = ''
return krb
def ansible_module_get_parsed_ip_addresses(ansible_module,
param='ip_addresses'):
ip_addrs = [ ]
ip_addrs = []
for ip in ansible_module.params.get(param):
try:
ip_parsed = ipautil.CheckedIPAddress(ip)
@@ -542,7 +405,8 @@ def ansible_module_get_parsed_ip_addresses(ansible_module,
def gen_remote_api(master_host_name, etc_ipa):
ldapuri = 'ldaps://%s' % ipautil.format_netloc(master_host_name)
xmlrpc_uri = 'https://{}/ipa/xml'.format(ipautil.format_netloc(master_host_name))
xmlrpc_uri = 'https://{}/ipa/xml'.format(
ipautil.format_netloc(master_host_name))
remote_api = create_api(mode=None)
remote_api.bootstrap(in_server=True,
context='installer',

View File

@@ -5,22 +5,19 @@
- name: Install - Ensure IPA replica packages are installed
package:
name: "{{ item }}"
name: "{{ ipareplica_packages }}"
state: present
with_items: "{{ ipareplica_packages }}"
- name: Install - Ensure IPA replica packages for dns are installed
package:
name: "{{ item }}"
name: "{{ ipareplica_packages_dns }}"
state: present
with_items: "{{ ipareplica_packages_dns }}"
when: ipareplica_setup_dns | bool
- name: Install - Ensure IPA replica packages for adtrust are installed
package:
name: "{{ item }}"
name: "{{ ipareplica_packages_adtrust }}"
state: present
with_items: "{{ ipareplica_packages_adtrust }}"
when: ipareplica_setup_adtrust | bool
when: ipareplica_install_packages | bool
@@ -28,6 +25,11 @@
#- name: Install - Include Python2/3 import test
# import_tasks: "{{ role_path }}/tasks/python_2_3_test.yml"
- name: Install - Set ipareplica_servers
set_fact:
ipareplica_servers: "{{ groups['ipaservers'] | list }}"
when: groups.ipaservers is defined and ipareplica_servers is not defined
- name: Install - Set default principal if no keytab is given
set_fact:
ipaadmin_principal: admin
@@ -41,8 +43,7 @@
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ ipareplica_domain | default(ipaserver_domain) |
default(omit) }}"
servers: "{{ groups.ipaservers | default(groups.ipaserver) |
default(omit) }}"
servers: "{{ ipareplica_servers | default(omit) }}"
realm: "{{ ipareplica_realm | default(omit) }}"
hostname: "{{ ipareplica_hostname | default(ansible_fqdn) }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
@@ -82,9 +83,9 @@
name: ipaclient
vars:
state: present
ipaclient_domain: "{{ result_ipareplica_test.domain }}"
ipaclient_realm: "{{ result_ipareplica_test.realm }}"
ipaclient_servers: ["{{ result_ipareplica_test.server }}"]
ipaclient_domain: "{{ result_ipareplica_test.domain | default(omit) }}"
ipaclient_realm: "{{ result_ipareplica_test.realm | default(omit) }}"
ipaclient_servers: "{{ ipareplica_servers | default(omit) }}"
ipaclient_hostname: "{{ result_ipareplica_test.hostname }}"
ipaclient_no_ntp: "{{ result_ipareplica_test.ipa_python_version
< 40690 }}"
@@ -132,10 +133,13 @@
setup_dns: "{{ ipareplica_setup_dns }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
dirsrv_cert_name: "{{ ipareplica_dirsrv_cert_name | default(omit) }}"
dirsrv_pin: "{{ ipareplica_dirsrv_pin | default(omit) }}"
http_cert_files: "{{ ipareplica_http_cert_files | default([]) }}"
http_cert_name: "{{ ipareplica_http_cert_name | default(omit) }}"
http_pin: "{{ ipareplica_http_pin | default(omit) }}"
pkinit_cert_files: "{{ ipareplica_pkinit_cert_files | default([]) }}"
pkinit_cert_name: "{{ ipareplica_pkinit_cert_name | default(omit) }}"
pkinit_pin: "{{ ipareplica_pkinit_pin | default(omit) }}"
### client ###
keytab: "{{ ipaclient_keytab | default(omit) }}"
@@ -181,7 +185,6 @@
- name: Install - Create dirman password
no_log: yes
ipareplica_master_password:
dm_password: "{{ ipadm_password }}"
master_password: "{{ ipareplica_master_password | default(omit) }}"
register: result_ipareplica_master_password
@@ -222,11 +225,6 @@
server: "{{ result_ipareplica_test.server }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info }}"
_http_pkcs12_info: "{{ result_ipareplica_prepare._http_pkcs12_info }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
@@ -270,10 +268,7 @@
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info }}"
_http_pkcs12_info: "{{ result_ipareplica_prepare._http_pkcs12_info }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
@@ -314,13 +309,10 @@
server: "{{ result_ipareplica_test.server }}"
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info }}"
_http_pkcs12_info: "{{ result_ipareplica_prepare._http_pkcs12_info }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
@@ -343,6 +335,50 @@
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
# We need to point to the master in ipa default conf when certmonger
# asks for HTTP certificate in newer ipa versions. In these versions
# create_ipa_conf has the additional master argument.
- name: Install - Create override IPA conf
ipareplica_create_ipa_conf:
### basic ###
dm_password: "{{ ipadm_password | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ result_ipareplica_test.domain }}"
realm: "{{ result_ipareplica_test.realm }}"
hostname: "{{ result_ipareplica_test.hostname }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
### client ###
force_join: "{{ ipaclient_force_join }}"
### ad trust ###
netbios_name: "{{ ipareplica_netbios_name | default(omit) }}"
rid_base: "{{ ipareplica_rid_base | default(omit) }}"
secondary_rid_base: "{{ ipareplica_secondary_rid_base | default(omit) }}"
### additional ###
server: "{{ result_ipareplica_test.server }}"
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
dirman_password: "{{ ipareplica_dirman_password }}"
master:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
when: result_ipareplica_test.change_master_for_certmonger
- name: Install - DS enable SSL
ipareplica_ds_enable_ssl:
### server ###
@@ -383,6 +419,46 @@
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ ipareplica_dirman_password }}"
# Need to point back to ourself after the cert for HTTP is obtained
- name: Install - Create original IPA conf again
ipareplica_create_ipa_conf:
### basic ###
dm_password: "{{ ipadm_password | default(omit) }}"
password: "{{ ipaadmin_password | default(omit) }}"
ip_addresses: "{{ ipareplica_ip_addresses | default([]) }}"
domain: "{{ result_ipareplica_test.domain }}"
realm: "{{ result_ipareplica_test.realm }}"
hostname: "{{ result_ipareplica_test.hostname }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
setup_dns: "{{ ipareplica_setup_dns }}"
### ssl certificate ###
dirsrv_cert_files: "{{ ipareplica_dirsrv_cert_files | default([]) }}"
### client ###
force_join: "{{ ipaclient_force_join }}"
### ad trust ###
netbios_name: "{{ ipareplica_netbios_name | default(omit) }}"
rid_base: "{{ ipareplica_rid_base | default(omit) }}"
secondary_rid_base: "{{ ipareplica_secondary_rid_base | default(omit) }}"
### additional ###
server: "{{ result_ipareplica_test.server }}"
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
dirman_password: "{{ ipareplica_dirman_password }}"
when: result_ipareplica_test.change_master_for_certmonger
- name: Install - Setup otpd
ipareplica_setup_otpd:
### server ###
@@ -396,7 +472,6 @@
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ ipareplica_dirman_password }}"
@@ -415,6 +490,8 @@
"{{ result_ipareplica_prepare.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
@@ -426,7 +503,8 @@
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
no_ui_redirect: "{{ ipareplica_no_ui_redirect }}"
pki_config_override:
"{{ ipareplica_pki_config_override | default(omit) }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
@@ -434,6 +512,8 @@
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
_subject_base: "{{ result_ipareplica_prepare._subject_base }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
@@ -452,7 +532,6 @@
setup_ca: "{{ ipareplica_setup_ca }}"
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
no_pkinit: "{{ ipareplica_no_pkinit }}"
# no_ui_redirect: "{{ ipareplica_no_ui_redirect }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###
@@ -497,6 +576,8 @@
hostname: "{{ result_ipareplica_test.hostname }}"
ca_cert_files: "{{ ipareplica_ca_cert_files | default([]) }}"
no_host_dns: "{{ ipareplica_no_host_dns }}"
pki_config_override:
"{{ ipareplica_pki_config_override | default(omit) }}"
### replica ###
setup_adtrust: "{{ result_ipareplica_test.setup_adtrust }}"
setup_ca: "{{ ipareplica_setup_ca }}"
@@ -516,9 +597,7 @@
installer_ccache: "{{ result_ipareplica_prepare.installer_ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_dirsrv_pkcs12_info: "{{ result_ipareplica_prepare._dirsrv_pkcs12_info }}"
_http_pkcs12_info: "{{ result_ipareplica_prepare._http_pkcs12_info }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
_add_to_ipaservers: "{{ result_ipareplica_prepare._add_to_ipaservers }}"
_ca_subject: "{{ result_ipareplica_prepare._ca_subject }}"
@@ -538,9 +617,7 @@
config_master_host_name:
"{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
# _pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ ipareplica_dirman_password }}"
@@ -560,7 +637,8 @@
ccache: "{{ result_ipareplica_prepare.ccache }}"
_ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
_ca_file: "{{ result_ipareplica_prepare._ca_file }}"
_pkinit_pkcs12_info: "{{ result_ipareplica_prepare._pkinit_pkcs12_info }}"
_kra_enabled: "{{ result_ipareplica_prepare._kra_enabled }}"
_kra_host_name: "{{ result_ipareplica_prepare.config_kra_host_name }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
dirman_password: "{{ ipareplica_dirman_password }}"
config_setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
@@ -607,6 +685,8 @@
not none else omit }}"
no_dnssec_validation: "{{ ipareplica_no_dnssec_validation }}"
### additional ###
dns_ip_addresses: "{{ result_ipareplica_prepare.dns_ip_addresses }}"
dns_reverse_zones: "{{ result_ipareplica_prepare.dns_reverse_zones }}"
ccache: "{{ result_ipareplica_prepare.ccache }}"
_top_dir: "{{ result_ipareplica_prepare._top_dir }}"
setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
@@ -640,6 +720,8 @@
hostname: "{{ result_ipareplica_test.hostname }}"
hidden_replica: "{{ ipareplica_hidden_replica }}"
### server ###
### replica ###
setup_kra: "{{ result_ipareplica_test.setup_kra }}"
### certificate system ###
subject_base: "{{ result_ipareplica_prepare.subject_base }}"
### additional ###

View File

@@ -10,9 +10,9 @@
- "vars/default.yml"
- name: Install IPA replica
include_tasks: tasks/install.yml
include_tasks: install.yml
when: state|default('present') == 'present'
- name: Uninstall IPA replica
include_tasks: tasks/uninstall.yml
include_tasks: uninstall.yml
when: state|default('present') == 'absent'

View File

@@ -34,8 +34,7 @@
# failed_when: False
# delegate_to: "{{ groups.ipaserver[0] | default(fail) }}"
# - name: Remove IPA replica packages
# package:
# name: "{{ item }}"
# state: absent
# with_items: "{{ ipareplica_packages }}"
#- name: Remove IPA replica packages
# package:
# name: "{{ ipareplica_packages }}"
# state: absent

View File

@@ -0,0 +1,5 @@
# defaults file for ipareplica
# vars/RedHat-8.yml
ipareplica_packages: [ "@idm:DL1/server" ]
ipareplica_packages_dns: [ "@idm:DL1/dns" ]
ipareplica_packages_adtrust: [ "@idm:DL1/adtrust" ]

View File

@@ -1,4 +1,4 @@
# vars/Ubuntu.yml
ipareplica_packages: [ "freeipa-server" ]
ipareplica_packages_dns: [ "freeipa-server-dns" ]
ipareplica_packages_adtrust: [ ]
ipareplica_packages_adtrust: [ "freeipa-server-trust-ad" ]

View File

@@ -6,8 +6,51 @@ Description
This role allows to configure and IPA server.
**Note**: The ansible playbooks and role require a configured ansible environment where the ansible nodes are reachable and are properly set up to have an IP address and a working package manager.
Features
--------
* Server deployment
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.5 and up are supported by the server role.
Supported Distributions
-----------------------
* RHEL/CentOS 7.6+
* Fedora 26+
* Ubuntu
Requirements
------------
**Controller**
* Ansible version: 2.8+
**Node**
* Supported FreeIPA version (see above)
* Supported distribution (needed for package installation only, see above)
Limitations
-----------
External signed CA
External signed CA is now supported. But the currently needed two step process is an issue for the processing in a simple playbook.
Work is planned to have a new method to handle CSR for external signed CAs in a separate step before starting the server installation.
Usage
-----
=====
Example inventory file with fixed domain and realm, setting up of the DNS server and using forwarders from /etc/resolv.conf:
@@ -63,111 +106,187 @@ Example playbook to setup the IPA server using admin and dirman passwords from i
- role: ipaserver
state: present
Example playbook to setup the IPA primary with external signed CA using the previous inventory file:
Server installation step 1: Generate CSR, copy to controller as `<ipaserver hostname>-ipa.csr`
```yaml
---
- name: Playbook to configure IPA server step1
hosts: ipaserver
become: true
vars:
ipaserver_external_ca: yes
roles:
- role: ipaserver
state: present
post_tasks:
- name: Copy CSR /root/ipa.csr from node to "{{ groups.ipaserver[0] + '-ipa.csr' }}"
fetch:
src: /root/ipa.csr
dest: "{{ groups.ipaserver[0] + '-ipa.csr' }}"
flat: yes
```
Sign with CA: This is up to you
Server installatin step 2: Copy `<ipaserver hostname>-chain.crt` to the IPA server and continue with installation of the primary.
```yaml
- name: Playbook to configure IPA server step3
hosts: ipaserver
become: true
vars:
ipaserver_external_cert_files: "/root/chain.crt"
pre_tasks:
- name: Copy "{{ groups.ipaserver[0] + '-chain.crt' }}" to /root/chain.crt on node
copy:
src: "{{ groups.ipaserver[0] + '-chain.crt' }}"
dest: "/root/chain.crt"
force: yes
roles:
- role: ipaserver
state: present
```
The files can also be copied automatically: Set `ipaserver_copy_csr_to_controller` to true in the server installation step 1 and set `ipaserver_external_cert_files_from_controller` to point to the `chain.crt` file in the server installatin step 2.
Playbooks
=========
The playbooks needed to deploy or undeploy a server are part of the repository in the playbooks folder. There are also playbooks to deploy and undeploy clusters.
```
install-server.yml
uninstall-server.yml
```
Please remember to link or copy the playbooks to the base directory of ansible-freeipa if you want to use the roles within the source archive.
How to setup a server
---------------------
```bash
ansible-playbook -v -i inventory/hosts install-server.yml
```
This will deploy the server defined in the inventory file.
Variables
---------
=========
**ipaserver** - Group with the IPA server hostname
(list of strings)
Base Variables
--------------
**ipaadmin_password** - The password for the IPA admin user.
(string, optional)
**ipadm_password** - The password for the Directory Manager.
(string, optional)
**ipaserver_domain** - The primary DNS domain of an existing IPA deployment.
(string)
Variable | Description | Required
-------- | ----------- | --------
`ipaserver` | This group with the single IPA server full qualified hostname. (list of strings) | yes
`ipadm_password` | The password for the Directory Manager. (string) | no
`ipaadmin_password` | The password for the IPA admin user (string) | no
`ipaserver_ip_addresses` | The list of master server IP addresses. (list of strings) | no
`ipaserver_domain` | The primary DNS domain of an existing IPA deployment. (string) | no
`ipaserver_realm` | The Kerberos realm of an existing IPA deployment. (string) | no
`ipaserver_hostname` | Fully qualified name of the server. (string) | no
`ipaserver_no_host_dns` | Do not use DNS for hostname lookup during installation. (bool, default: false) | no
**ipaserver_realm** - The Kerberos realm of an existing IPA deployment.
(string)
Server Variables
----------------
**ipaserver_idstart** - The starting user and group id number (default random).
(integer, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_setup_adtrust` | Configure AD Trust capability. (bool, default: false) | no
`ipaserver_setup_kra` | Install and configure a KRA on this server. (bool, default: false) | no
`ipaserver_setup_dns` | Configure an integrated DNS server, create DNS zone specified by domain. (bool, default: false) | no
`ipaserver_idstart` | The starting user and group id number. (integer, default: random) | no
`ipaserver_idmax` | The maximum user and group id number. (integer, default: idstart+199999) | no
`ipaserver_no_hbac_allow` | Do not install allow_all HBAC rule. (bool) | no
`ipaserver_no_ui_redirect` | Do not automatically redirect to the Web UI. (bool) | no
`ipaserver_dirsrv_config_file` | The path to LDIF file that will be used to modify configuration of dse.ldif during installation. (string) | no
`ipaserver_pki_config_override` | Path to ini file with config overrides. This is only usable with recent FreeIPA versions. (string) | no
**ipaserver_idmax** - The maximum user and group id number (default: idstart+199999).
(integer, optional)
SSL certificate Variables
-------------------------
**ipaserver_no_hbac_allow** - Do not install allow_all HBAC rule.
(bool, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_dirsrv_cert_files` | Files containing the Directory Server SSL certificate and private keys. (list of strings) | no
`ipaserver_http_cert_file` | File containing the Apache Server SSL certificate and private key. (string) | no
`ipaserver_pkinit_cert_file` | File containing the Kerberos KDC SSL certificate and private key. (string) | no
`ipaserver_dirsrv_pin` | The password to unlock the Directory Server private key. (string) | no
`ipaserver_http_pin` | The password to unlock the Apache Server private key. (string) | no
`ipaserver_pkinit_pin` | The password to unlock the Kerberos KDC private key. (string) | no
`ipaserver_dirsrv_cert_name` | Name of the Directory Server SSL certificate to install. (string) | no
`ipaserver_http_cert_name` | Name of the Apache Server SSL certificate to install. (string) | no
`ipaserver_pkinit_cert_name` | Name of the Kerberos KDC SSL certificate to install. (string) | no
**ipaserver_no_ui_redirect** - Do not automatically redirect to the Web UI.
(bool, optional)
Client Variables
----------------
**ipaserver_dirsrv_config_file** - The path to LDIF file that will be used to modify configuration of dse.ldif during installation.
(string, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipaclient_ntp_servers` | The list defines the NTP servers to be used. | no
`ipaclient_ntp_pool` | The string value defines the ntp server pool to be used. | no
`ipaclient_no_ntp` | The bool value defines if NTP will not be configured and enabled. `ipaclient_no_ntp` defaults to `no`. | no
`ipaclient_ssh_trust_dns` | The bool value defines if OpenSSH client will be configured to trust DNS SSHFP records. `ipaclient_ssh_trust_dns` defaults to `no`. | no
`ipaclient_no_ssh` | The bool value defines if OpenSSH client will be configured. `ipaclient_no_ssh` defaults to `no`. | no
`ipaclient_no_sshd` | The bool value defines if OpenSSH server will be configured. `ipaclient_no_sshd` defaults to `no`. | no
`ipaclient_no_sudo` | The bool value defines if SSSD will be configured as a data source for sudo. `ipaclient_no_sudo` defaults to `no`. | no
`ipaclient_no_dns_sshfp` | The bool value defines if DNS SSHFP records will not be created automatically. `ipaclient_no_dns_sshfp` defaults to `no`. | no
**ipaserver_setup_kra** - Install and configure a KRA on this server.
(bool, optional)
Certificate system Variables
----------------------------
**ipaserver_setup_dns** - Configure an integrated DNS server, create DNS zone specified by domain
(string, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_external_ca` | Generate a CSR for the IPA CA certificate to be signed by an external CA. (bool, default: false) | no
`ipaserver_external_ca_type` | Type of the external CA. (choice: generic,ms-cs) | no
`ipaserver_external_ca_profile` | Specify the certificate profile/template to use at the external CA. (string) | no
`ipaserver_external_cert_files` | Files containing the IPA CA certificates and the external CA certificate chains (list of string) | no
`ipaserver_subject_base` | The certificate subject base (default O=<realm-name>). RDNs are in LDAP order (most specific RDN first). (string) | no
`ipaserver_ca_subject` | The CA certificate subject DN (default CN=Certificate Authority,O=<realm-name>). RDNs are in LDAP order (most specific RDN first). (string) | no
`ipaserver_ca_signing_algorithm` | Signing algorithm of the IPA CA certificate. (choice: SHA1withRSA,SHA256withRSA,SHA512withRSA) | no
**ipaserver_forwarders** - Add DNS forwarders to the DNS configuration.
(list of strings, optional)
DNS Variables
-------------
**ipaserver_no_forwarders** - Do not add any DNS forwarders. Root DNS servers will be used instead.
(bool, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_allow_zone_overlap` | Allow creation of (reverse) zone even if the zone is already resolvable. (bool, default: false) | no
`ipaserver_reverse_zones` | The reverse DNS zones to use. (list of strings) | no
`ipaserver_no_reverse` | Do not create reverse DNS zone. (bool, default: false) | no
`ipaserver_auto_reverse` | Try to resolve reverse records and reverse zones for server IP addresses. (bool, default: false) | no
`ipaserver_zonemgr` | The e-mail address of the DNS zone manager. (string, default: hostmaster@DOMAIN.) | no
`ipaserver_forwarders` | Add DNS forwarders to the DNS configuration. (list of strings) | no
`ipaserver_no_forwarders` | Do not add any DNS forwarders. Root DNS servers will be used instead. (bool, default: false) | no
`ipaserver_auto_forwarders` | Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS. (bool, default: false) | no
`ipaserver_forward_policy` | DNS forwarding policy for global forwarders specified using other options. (choice: first|only) | no
`ipaserver_no_dnssec_validation` | Disable DNSSEC validation on this server. (bool, default: false) | no
**ipaserver_auto_forwarders** - Add DNS forwarders configured in /etc/resolv.conf to the list of forwarders used by IPA DNS.
(bool, optional)
AD trust Variables
------------------
**ipaserver_forward_policy** - DNS forwarding policy for global forwarders specified using other options. first|only
(choice, optional)
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_enable_compat`| Enables support for trusted domains users for old clients through Schema Compatibility plugin. (bool, default: false) | no
`ipaserver_netbios_name` | The NetBIOS name for the IPA domain. (string) | no
`ipaserver_rid_base` | First RID value of the local domain. (integer) | no
`ipaserver_secondary_rid_base` | Start value of the secondary RID range. (integer) | no
**ipaserver_reverse_zones** - The reverse DNS zones to use.
(list of strings, optional)
Special Variables
-----------------
**ipaserver_no_reverse** - Do not create reverse DNS zone.
(bool, optional)
**ipaserver_auto_reverse** - Try to resolve reverse records and reverse zones for server IP addresses.
(bool, optional)
**ipaserver_zonemgr** - The e-mail address of the DNS zone manager. Defaults to hostmaster@DOMAIN.
(string, optional)
**ipaserver_no_host_dns** - Do not use DNS for hostname lookup during installation.
(bool, optional)
**ipaserver_pki_config_override** - Path to ini file with config overrides.
(string, optional)
**ipaserver_no_dnssec_validation** - Disable DNSSEC validation on this server.
(bool, optional)
**ipaserver_allow_zone_overlap** - Allow creation of (reverse) zone even if the zone is already resolvable.
(bool, optional)
**ipaserver_setup_adtrust** - Configure AD Trust capability.
(bool, optional)
**ipaserver_netbios_name** - The NetBIOS name for the IPA domain.
(string, optional)
**ipaserver_rid_base** - First RID value of the local domain.
(integer, optional)
**ipaserver_secondary_rid_base** - Start value of the secondary RID range.
(integer, optional)
**ipaserver_enable_compat** - Enables support for trusted domains users for old clients through Schema Compatibility plugin.
(bool, optional)
**ipaclient_force_join** - Set force_join to yes to join the host even if it is already enrolled.
(bool, optional)
**ipaclient_no_ntp** - Set to no to not configure and enable NTP
(bool, optional)
**ipaclient_mkhomedir** - Set to yes to configure PAM to create a users home directory if it does not exist.
(string, optional)
Requirements
------------
freeipa-server v4.5 or later
Variable | Description | Required
-------- | ----------- | --------
`ipaserver_install_packages` | The bool value defines if the needed packages are installed on the node. (bool, default: true) | no
`ipaserver_setup_firewalld` | The value defines if the needed services will automatically be openen in the firewall managed by firewalld. (bool, default: true) | no
`ipaserver_external_cert_files_from_controller` | Files containing the IPA CA certificates and the external CA certificate chains on the controller that will be copied to the ipaserver host to `/root` folder. (list of string) | no
`ipaserver_copy_csr_to_controller` | Copy the generated CSR from the ipaserver to the controller as `"{{ inventory_hostname }}-ipa.csr"`. (bool) | no
Authors
-------
=======
Thomas Woerner

View File

@@ -36,7 +36,7 @@ ipaserver_install_packages: yes
ipaserver_setup_firewalld: yes
### additional ###
ipaserver_allow_missing: [ ]
ipaserver_copy_csr_to_controller: no
### uninstall ###
ipaserver_ignore_topology_disconnect: no

View File

@@ -1,536 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Florence Blanc-Renaud <frenaud@redhat.com>
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2017 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
ANSIBLE_METADATA = {'metadata_version': '1.0',
'status': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: ipaserver
short description: Configures a server machine as IPA server
description:
Configures a server machine to use IPA for authentication and
identity services.
The enrollment requires one authentication method among the 3 following:
- Kerberos principal and password (principal/password)
- Kerberos keytab file (keytab)
- One-Time-Password (otp)
options:
state:
description: the server state
required: false
default: present
choices: [ "present", "absent" ]
domain:
description: The primary DNS domain of an existing IPA deployment
required: true
realm:
description: The Kerberos realm of an existing IPA deployment
required: true
password:
description: The password for the kerberos admin
required: true
dm_password:
description: The password for the Directory Manager
required: true
# ip_addresses:
# description: Master Server IP Addresses
# required: false
# hostname:
# description: Fully qualified name of this host
# required: false
mkhomedir:
description: Create home directories for users on their first login
required: false
default: no
setup_dns:
description: Configure bind with our zone
required: false
default: no
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: false
default: no
no_ntp:
description: Do not configure ntp
required: false
default: no
idstart:
description: The starting value for the IDs range (default random)
required: false
idmax:
description: The max value for the IDs range (default: idstart+199999)
required: false
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: false
default: no
# ignore_topology_disconnect:
# description: Do not check whether server uninstall disconnects the topology (domain level 1+)
# required: false
# default: no
# ignore_last_of_role:
# description: Do not check whether server uninstall removes last CA/DNS server or DNSSec master (domain level 1+)
# required: false
no_pkinit:
description: Disables pkinit setup steps
required: false
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: false
ssh_trust_dns:
description: Configure OpenSSH client to trust DNS SSHFP records
required: false
no_ssh:
description: Do not configure OpenSSH client
required: false
no_sshd:
description: Do not configure OpenSSH server
required: false
no_dns_sshfp:
description: Do not automatically create DNS SSHFP records
required: false
dirsrv_config_file:
description: The path to LDIF file that will be used to modify configuration of dse.ldif during installation of the directory server instance
required: false
external_ca:
description: Generate a CSR for the IPA CA certificate to be signed by an external CA
required: false
external_ca_type:
description: Type of the external CA
required: false
external_cert_files:
description: File containing the IPA CA certificate and the external CA certificate chain
required: false
dirsrv_cert_files:
description: File containing the Directory Server SSL certificate and private key
required: false
dirsrv_pin:
description: The password to unlock the Directory Server private key
required: false
dirsrv_cert_name:
description: Name of the Directory Server SSL certificate to install
required: false
http_cert_files:
description: File containing the Apache Server SSL certificate and private key
required: false
http_pin:
description: The password to unlock the Apache Server private key
required: false
http_cert_name:
description: Name of the Apache Server SSL certificate to install
required: false
pkinit_cert_files:
description: File containing the Kerberos KDC SSL certificate and private key
required: false
pkinit_pin:
description: The password to unlock the Kerberos KDC private key
required: false
pkinit_cert_name:
description: Name of the Kerberos KDC SSL certificate to install
required: false
ca_cert_files:
description: File containing CA certificates for the service certificate files
required: false
subject:
description: The certificate subject base (default O=<realm-name>)
required: false
ca_signing_algorithm:
description: Signing algorithm of the IPA CA certificate
required: false
forwarders:
description: Add DNS forwarders
required: false
author:
- Florence Blanc-Renaud
- Thomas Woerner
'''
EXAMPLES = '''
# Example from Ansible Playbooks
# Unenroll server
- ipaserver:
state: absent
# Enroll server using admin credentials, with auto-discovery
- ipaserver:
password: MySecretPassword
dm_password: MySecretPassword
'''
RETURN = '''
tbd
'''
import os
from six.moves.configparser import RawConfigParser
from ansible.module_utils.basic import AnsibleModule
try:
from ipalib.install.sysrestore import SYSRESTORE_STATEFILE
except ImportError:
from ipapython.sysrestore import SYSRESTORE_STATEFILE
from ipaplatform.paths import paths
def is_server_configured():
"""
Check if ipa server is configured.
IPA server is configured when /etc/ipa/default.conf exists and
/var/lib/ipa/sysrestore/sysrestore.state exists.
:returns: boolean
"""
return (os.path.isfile(paths.IPA_DEFAULT_CONF) and
os.path.isfile(os.path.join(paths.SYSRESTORE,
SYSRESTORE_STATEFILE)))
def get_ipa_conf():
"""
Return IPA configuration read from /etc/ipa/default.conf
:returns: dict containing key,value
"""
parser = RawConfigParser()
parser.read(paths.IPA_DEFAULT_CONF)
result = dict()
for item in ['basedn', 'realm', 'domain', 'server', 'host', 'xmlrpc_uri']:
if parser.has_option('global', item):
value = parser.get('global', item)
else:
value = None
if value:
result[item] = value
return result
def main():
module = AnsibleModule(
supports_check_mode=True,
argument_spec=dict(
state=dict(default='present', choices=['present', 'absent']),
# basic
dm_password=dict(required=False, no_log=True),
password=dict(required=False, no_log=True),
# ip_addresses=dict(required=False, type='list'),
domain=dict(required=True),
realm=dict(required=True),
# hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list'),
no_host_dns=dict(required=False, type='bool', default=False),
# server
# setup_adtrust=dict(required=False, type='bool', default=F#alse),
# setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
idstart=dict(required=False, type='int', default=0),
idmax=dict(required=False, type='int', default=0),
no_hbac_allow=dict(required=False, type='bool', default=False),
no_pkinit=dict(required=False, type='bool', default=False),
no_ui_redirect=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False),
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list'),
dirsrv_pin=dict(required=False),
dirsrv_cert_name=dict(required=False),
http_cert_files=dict(required=False, type='list'),
http_pin=dict(required=False),
http_cert_name=dict(required=False),
pkinit_cert_files=dict(required=False, type='list'),
pkinit_pin=dict(required=False),
pkinit_cert_name=dict(required=False),
# client
mkhomedir=dict(required=False, type='bool', default=False),
no_ntp=dict(required=False, type='bool', default=False),
ssh_trust_dns=dict(required=False, type='bool', default=False),
no_ssh=dict(required=False, type='bool', default=False),
no_sshd=dict(required=False, type='bool', default=False),
no_dns_sshfp=dict(required=False, type='bool', default=False),
# certificate system
external_ca=dict(required=False),
external_ca_type=dict(default='generic',
choices=['generic', 'ms-cs']),
external_cert_files=dict(required=False, type='list'),
subject_base=dict(required=False),
ca_signing_algorithm=dict(required=False),
# dns
allow_zone_overlap=dict(required=False, type='bool', default=False),
reverse_zones=dict(required=False, type='list'),
no_reverse=dict(required=False, type='bool', default=False),
auto_reverse=dict(required=False, type='bool', default=False),
zone_manager=dict(required=False),
forwarders=dict(required=False, type='list'),
no_forwarders=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
forward_policy=dict(default='first', choices=['first', 'only']),
no_dnssec_validation=dict(required=False, type='bool', default=False),
# ad trust
enable_compat=dict(required=False, type='bool', default=False),
netbios_name=dict(required=False),
rid_base=dict(required=False),
secondary_rid_base=dict(required=False),
),
)
module._ansible_debug = True
state = module.params.get('state')
domain = module.params.get('domain')
realm = module.params.get('realm')
password = module.params.get('password')
dm_password = module.params.get('dm_password')
#ip_addresses = module.params.get('ip_addresses')
#hostname = module.params.get('hostname')
mkhomedir = module.params.get('mkhomedir')
setup_dns = module.params.get('setup_dns')
no_host_dns = module.params.get('no_host_dns')
no_ntp = module.params.get('no_ntp')
idstart = module.params.get('idstart')
idmax = module.params.get('idmax')
no_hbac_allow = module.params.get('no_hbac_allow')
ignore_topology_disconnect = module.params.get('ignore_topology_disconnect')
ignore_last_of_role = module.params.get('ignore_last_of_role')
no_pkinit = module.params.get('no_pkinit')
no_ui_redirect = module.params.get('no_ui_redirect')
ssh_trust_dns = module.params.get('ssh_trust_dns')
no_ssh = module.params.get('no_ssh')
no_sshd = module.params.get('no_sshd')
no_dns_sshfp = module.params.get('no_dns_sshfp')
dirsrv_config_file = module.params.get('dirsrv_config_file')
external_ca = module.params.get('external_ca')
external_ca_type = module.params.get('external_ca_type')
external_cert_files = module.params.get('external_cert_files')
dirsrv_cert_files=module.params.get('dirsrv_cert_files')
dirsrv_pin=module.params.get('dirsrv_pin')
dirsrv_cert_name=module.params.get('dirsrv_cert_name')
http_cert_files=module.params.get('http_cert_files')
http_pin=module.params.get('http_pin')
http_cert_name=module.params.get('http_cert_name')
pkinit_cert_files=module.params.get('pkinit_cert_files')
pkinit_pin=module.params.get('pkinit_pin')
pkinit_cert_name=module.params.get('pkinit_cert_name')
ca_cert_files=module.params.get('ca_cert_files')
subject=module.params.get('subject')
ca_signing_algorithm=module.params.get('ca_signing_algorithm')
forwarders = module.params.get('forwarders')
if state == 'present':
if not password or not dm_password:
module.fail_json(
msg="Password and dm password need to be specified")
# Check if ipa server is already configured
if is_server_configured():
# Check that realm and domain match
current_config = get_ipa_conf()
if domain and domain != current_config.get('domain'):
module.fail_json(msg="IPA server already installed "
"with a conflicting domain")
if realm and realm != current_config.get('realm'):
module.fail_json(msg="IPA server already installed "
"with a conflicting realm")
# server is already configured and no inconsistency
# detected
return module.exit_json(changed=False, domain=domain, realm=realm)
# ipa server not installed
if module.check_mode:
# Do nothing, just return changed=True
return module.exit_json(changed=True)
# basic options
cmd = [
module.get_bin_path("ipa-server-install"),
"-U",
"--ds-password", dm_password,
"--admin-password", password,
"--domain", domain,
"--realm", realm,
]
#for ip in ip_addresses:
# cmd.append("--ip-address=%s" % ip)
#if hostname:
# cmd.append("--hostname=%s" % hostname)
for cert_file in ca_cert_files:
cmd.append("--ca-cert-file=%s" % cert_file)
if no_host_dns:
cmd.append("--no-host-dns")
# server options
#if setup_adtrust:
# cmd.append("--setup-adtrust")
#if setup_kra:
# cmd.append("--setup-kra")
if setup_dns:
cmd.append("--setup-dns")
if idstart:
cmd.append("--idstart=%d", idstart)
if idmax:
cmd.append("--idstart=%d", idmax)
if no_hbac_allow:
cmd.append("--no_hbac_allow")
if no_pkinit:
cmd.append("--no-pkinit")
if no_ui_redirect:
cmd.append("--no-ui-redirect")
if dirsrv_config_file:
cmd.append("--dirsrv-config-file=%s" % dirsrv_config_file)
# ssl certificate options
for cert_file in dirsrv_cert_files:
cmd.append("--dirsrv-cert-file=%s" % cert_file)
if dirsrv_pin:
cmd.append("--dirsrv-pin=%s" % dirserv_pin)
if dirsrv_cert_name:
cmd.append("--dirsrv-cert-name=%s" % dirsrv_cert_name)
for cert_file in http_cert_files:
cmd.append("--http-cert-file=%s" % cert_file)
if http_pin:
cmd.append("--http-pin=%s" % http_pin)
if http_cert_name:
cmd.append("--http-cert-name=%s" % http_cert_name)
for cert_file in pkinit_cert_files:
cmd.append("--pkinit-cert-file=%s" % cert_file)
if pkinit_pin:
cmd.append("--pkinit-pin=%s" % pkinit_pin)
if pkinit_cert_name:
cmd.append("--pkinit-cert-name=%s" % pkinit_cert_name)
# client options
if mkhomedir:
cmd.append("--mkhomedir")
if no_ntp:
cmd.append("--no-ntp")
if ssh_trust_dns:
cmd.append("--ssh-trust-dns")
if no_ssh:
cmd.append("--no-ssh")
if no_sshd:
cmd.append("--no-sshd")
if no_dns_sshfp:
cmd.append("--no-dns-sshfp")
# certificate system options
if external_ca:
cmd.append("--external-ca")
if external_ca_type:
cmd.append("--external-ca-type=%s" % external_ca_type)
for cert_file in external_cert_files:
cmd.append("--external-cert-file=%s" % cert_file)
if subject_base:
cmd.append("--subject=%s" % subject)
if ca_signing_algorithm:
cmd.append("--ca-signing-algorithm=%s" % ca_signing_algorithm)
# dns options
if allow_zone_overlop:
cmd.append("--allow-zone-overlap")
for reverse_zone in reverse_zones:
cmd.append("--reverse-zone=%s" % reverse_zone)
if no_reverse:
cmd.append("--no-reverse")
if auto_reverse:
cmd.append("--auto-reverse")
if zonemgr:
cmd.append("--zonemgr=%s" % zonemgr)
for forwarder in forwarders:
cmd.append("--forwarder=%s" % forwarder)
if no_forwarders:
cmd.append("--no-forwarders")
if auto_forwarders:
cmd.append("--auto-forwarders")
if forward_policy:
cmd.append("--forward-policy=%s" % forward_policy)
if no_dnssec_validation:
cmd.append("--no-dnssec-validation")
# ad trust options
#if enable_compat:
# cmd.append("--enable-compat")
#if netbios_name:
# cmd.append("--netbios-name=%s" % netbios_name)
#if rid_base:
# cmd.append("--rid-base=%s" % rid_base)
#if secondary_rid_base:
# cmd.append("--secondary-rid-base=%s" % rid_base)
else: # state == adsent
if not is_server_configured():
# Nothing to do
module.exit_json(changed=False)
# Server is configured
# If in check mode, do nothing but return changed=True
if module.check_mode:
module.exit_json(changed=True)
cmd = [
module.get_bin_path('ipa-server-install'),
"--uninstall",
"-U",
]
if ignore_topology_disconnect:
cmd.append("--ignore-topology-disconnect")
if ignore_last_of_role:
cmd.append("--ignore-last-of-role")
retcode, stdout, stderr = module.run_command(cmd)
if retcode != 0:
module.fail_json(msg="Failed to uninstall IPA server: %s" % stderr)
module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -32,10 +32,19 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: enable_ipa
short description:
description:
module: ipaserver_enable_ipa
short description: Enable IPA
description: Enable IPA
options:
hostname:
description: Fully qualified name of this host
required: yes
setup_dns:
description: Configure bind with our zone
required: no
setup_ca:
description: Configure a dogtag CA
required: no
author:
- Thomas Woerner
'''
@@ -47,11 +56,15 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options, paths, api, sysrestore, tasks,
service, bindinstance, redirect_stdout, services
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
hostname=dict(required=False),
setup_dns=dict(required=True, type='bool'),
setup_ca=dict(required=True, type='bool'),
@@ -87,9 +100,8 @@ def main():
# setup ds ######################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
if NUM_VERSION < 40600:
if hasattr(tasks, "configure_tmpfiles"):
# Make sure the files we crated in /var/run are recreated at startup
tasks.configure_tmpfiles()
@@ -109,5 +121,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -33,10 +33,12 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: ipaserver_load_cache
short description:
description:
short description: Load cache file
description: Load cache file
options:
dm_password:
description: Directory Manager password
required: no
author:
- Thomas Woerner
'''
@@ -47,23 +49,27 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
options, paths, read_cache
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
),
)
ansible_module._ansible_debug = True
ansible_log = AnsibleModuleLog(ansible_module)
# set values ############################################################
### basic ###
# basic
options.dm_password = ansible_module.params.get('dm_password')
# restore cache #########################################################
@@ -72,7 +78,7 @@ def main():
if options.dm_password is None:
ansible_module.fail_json(msg="Directory Manager password required")
try:
cache_vars = read_cache(dm_password)
cache_vars = read_cache(options.dm_password)
options.__dict__.update(cache_vars)
if cache_vars.get('external_ca', False):
options.external_ca = False
@@ -81,14 +87,15 @@ def main():
ansible_module.fail_json(
msg="Cannot process the cache file: %s" % str(e))
kwargs = { "changed": True }
kwargs = {"changed": True}
for name in options.__dict__:
kwargs[name] = options.__dict__[name]
ansible_module.exit_json(kwargs)
ansible_module.exit_json(**kwargs)
# done ##################################################################
ansible_module.exit_json(changed=False)
if __name__ == '__main__':
main()

View File

@@ -30,14 +30,17 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: master_password
module: ipaserver_master_password
short description: Generate kerberos master password if not given
description:
Generate kerberos master password if not given
options:
dm_password:
description: Directory Manager password
required: no
master_password:
description: kerberos master password (normally autogenerated)
required: false
required: yes
author:
- Thomas Woerner
'''
@@ -54,16 +57,19 @@ password:
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
options, paths, read_cache, ipa_generate_password
)
def main():
module = AnsibleModule(
argument_spec = dict(
#basic
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
master_password=dict(required=False, no_log=True),
),
supports_check_mode = True,
supports_check_mode=True,
)
module._ansible_debug = True
@@ -71,9 +77,6 @@ def main():
options.dm_password = module.params.get('dm_password')
options.master_password = module.params.get('master_password')
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
# This will override any settings passed in on the cmdline
if os.path.isfile(paths.ROOT_IPA_CACHE):
# dm_password check removed, checked already
@@ -89,5 +92,6 @@ def main():
module.exit_json(changed=True,
password=options.master_password)
if __name__ == '__main__':
main()

View File

@@ -33,37 +33,116 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: ipaserver_prepare
short description:
description:
short description: Prepare IPA server deployment
description: Prepare IPA server deployment
options:
force:
description: Installer force parameter
required: yes
dm_password:
description: Directory Manager password
required: no
password:
description: Admin user kerberos password
required: no
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
ca_cert_files:
description:
List of files containing CA certificates for the service certificate
files
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
external_ca:
description: External ca setting
required: yes
external_ca_type:
description: Type of the external CA
required: yes
external_ca_profile:
description:
Specify the certificate profile/template to use at the external CA
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
allow_zone_overlap:
description: Create DNS zone even if it already exists
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_reverse:
description: Create necessary reverse zones
required: yes
forwarders:
description: Add DNS forwarders
required: yes
no_forwarders:
description: Do not add any DNS forwarders, use root servers instead
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
enable_compat:
description: Enable support for trusted domains for old clients
required: yes
netbios_name:
description: NetBIOS name of the IPA domain
required: yes
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
required: yes
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
_hostname_overridden:
description: The installer _hostname_overridden setting
required: yes
author:
- Thomas Woerner
'''
@@ -74,13 +153,23 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options, sysrestore, paths,
ansible_module_get_parsed_ip_addresses,
redirect_stdout, adtrust, api, default_subject_base,
default_ca_subject_dn, ipautil, installutils, ca, kra, dns,
get_server_ip_address, no_matching_interface_for_ip_address_warning,
services, logger, tasks, update_hosts_file, ScriptError
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
force=dict(required=False, type='bool', default=False),
dm_password=dict(required=True, no_log=True),
password=dict(required=True, no_log=True),
@@ -90,19 +179,22 @@ def main():
hostname=dict(required=False),
ca_cert_files=dict(required=False, type='list', default=[]),
no_host_dns=dict(required=False, type='bool', default=False),
### server ###
# server
setup_adtrust=dict(required=False, type='bool', default=False),
setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
### ssl certificate ###
### client ###
### certificate system ###
external_ca=dict(required=False),
# ssl certificate
# client
# certificate system
external_ca=dict(required=False, type='bool'),
external_ca_type=dict(required=False),
external_ca_profile=dict(required=False),
external_cert_files=dict(required=False, type='list', default=[]),
subject_base=dict(required=False),
ca_subject=dict(required=False),
### dns ###
allow_zone_overlap=dict(required=False, type='bool', default=False),
# dns
allow_zone_overlap=dict(required=False, type='bool',
default=False),
reverse_zones=dict(required=False, type='list', default=[]),
no_reverse=dict(required=False, type='bool', default=False),
auto_reverse=dict(required=False, type='bool', default=False),
@@ -112,23 +204,29 @@ def main():
forward_policy=dict(default=None, choices=['first', 'only']),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
### ad trust ###
# ad trust
enable_compat=dict(required=False, type='bool', default=False),
netbios_name=dict(required=False),
rid_base=dict(required=False, type='int'),
secondary_rid_base=dict(required=False, type='int'),
### additional ###
# additional
setup_ca=dict(required=False, type='bool', default=False),
_hostname_overridden=dict(required=False, type='bool',
default=False),
default=False),
),
supports_check_mode = True,
supports_check_mode=True,
)
ansible_module._ansible_debug = True
ansible_log = AnsibleModuleLog(ansible_module)
# initialize return values for flake ############################
# These are set by ca.install_check
options._subject_base = None
options._ca_subject = None
# set values ####################################################
options.force = ansible_module.params.get('force')
@@ -141,23 +239,28 @@ def main():
options.host_name = ansible_module.params.get('hostname')
options.ca_cert_files = ansible_module.params.get('ca_cert_files')
options.no_host_dns = ansible_module.params.get('no_host_dns')
### server ###
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
#options.no_pkinit = ansible_module.params.get('no_pkinit')
### ssl certificate ###
#options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
### client ###
#options.no_ntp = ansible_module.params.get('no_ntp')
### certificate system ###
# options.no_pkinit = ansible_module.params.get('no_pkinit')
# ssl certificate
# options.dirsrv_cert_files = ansible_module.params.get(
# 'dirsrv_cert_files')
# client
# options.no_ntp = ansible_module.params.get('no_ntp')
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_ca_type = ansible_module.params.get('external_ca_type')
options.external_ca_profile = ansible_module.params.get(
'external_ca_profile')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
### dns ###
options.allow_zone_overlap = ansible_module.params.get('allow_zone_overlap')
# dns
options.allow_zone_overlap = ansible_module.params.get(
'allow_zone_overlap')
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_reverse = ansible_module.params.get('auto_reverse')
@@ -167,10 +270,10 @@ def main():
options.forward_policy = ansible_module.params.get('forward_policy')
options.no_dnssec_validation = ansible_module.params.get(
'no_dnssec_validation')
### ad trust ###
# ad trust
options.enable_compat = ansible_module.params.get('enable_compat')
options.netbios_name = ansible_module.params.get('netbios_name')
### additional ###
# additional
options.setup_ca = ansible_module.params.get('setup_ca')
options._host_name_overridden = ansible_module.params.get(
'_hostname_overridden')
@@ -190,116 +293,126 @@ def main():
if not options.ca_subject:
options.ca_subject = str(default_ca_subject_dn(options.subject_base))
# Configuration for ipalib, we will bootstrap and finalize later, after
# we are sure we have the configuration file ready.
cfg = dict(
context='installer',
confdir=paths.ETC_IPA,
in_server=True,
# make sure host name specified by user is used instead of default
host=options.host_name,
)
if options.setup_ca:
# we have an IPA-integrated CA
cfg['ca_host'] = options.host_name
try:
# Create the management framework config file and finalize api
target_fname = paths.IPA_DEFAULT_CONF
fd = open(target_fname, "w")
fd.write("[global]\n")
fd.write("host=%s\n" % options.host_name)
fd.write("basedn=%s\n" % ipautil.realm_to_suffix(options.realm_name))
fd.write("realm=%s\n" % options.realm_name)
fd.write("domain=%s\n" % options.domain_name)
fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % \
ipautil.format_netloc(options.host_name))
fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % \
installutils.realm_to_serverid(options.realm_name))
if options.setup_ca:
fd.write("enable_ra=True\n")
fd.write("ra_plugin=dogtag\n")
fd.write("dogtag_version=10\n")
else:
fd.write("enable_ra=False\n")
fd.write("ra_plugin=none\n")
fd.write("mode=production\n")
fd.close()
# Configuration for ipalib, we will bootstrap and finalize later, after
# we are sure we have the configuration file ready.
cfg = dict(
context='installer',
confdir=paths.ETC_IPA,
in_server=True,
# make sure host name specified by user is used instead of default
host=options.host_name,
)
if options.setup_ca:
# we have an IPA-integrated CA
cfg['ca_host'] = options.host_name
# Must be readable for everyone
os.chmod(target_fname, 0o644)
# Create the management framework config file and finalize api
target_fname = paths.IPA_DEFAULT_CONF
fd = open(target_fname, "w")
fd.write("[global]\n")
fd.write("host=%s\n" % options.host_name)
fd.write("basedn=%s\n" % ipautil.realm_to_suffix(options.realm_name))
fd.write("realm=%s\n" % options.realm_name)
fd.write("domain=%s\n" % options.domain_name)
fd.write("xmlrpc_uri=https://%s/ipa/xml\n" %
ipautil.format_netloc(options.host_name))
fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" %
installutils.realm_to_serverid(options.realm_name))
if options.setup_ca:
fd.write("enable_ra=True\n")
fd.write("ra_plugin=dogtag\n")
fd.write("dogtag_version=10\n")
else:
fd.write("enable_ra=False\n")
fd.write("ra_plugin=none\n")
fd.write("mode=production\n")
fd.close()
api.bootstrap(**cfg)
api.finalize()
# Must be readable for everyone
os.chmod(target_fname, 0o644)
if options.setup_ca:
with redirect_stdout(ansible_log):
ca.install_check(False, None, options)
if options.setup_kra:
with redirect_stdout(ansible_log):
kra.install_check(api, None, options)
api.bootstrap(**cfg)
api.finalize()
if options.setup_dns:
with redirect_stdout(ansible_log):
dns.install_check(False, api, False, options, options.host_name)
ip_addresses = dns.ip_addresses
else:
ip_addresses = get_server_ip_address(options.host_name,
not options.interactive, False,
options.ip_addresses)
if options.setup_ca:
with redirect_stdout(ansible_log):
ca.install_check(False, None, options)
if options.setup_kra:
with redirect_stdout(ansible_log):
kra.install_check(api, None, options)
# check addresses here, dns module is doing own check
no_matching_interface_for_ip_address_warning(ip_addresses)
options.ip_addresses = ip_addresses
options.reverse_zones = dns.reverse_zones
if options.setup_dns:
with redirect_stdout(ansible_log):
dns.install_check(False, api, False, options,
options.host_name)
ip_addresses = dns.ip_addresses
else:
ip_addresses = get_server_ip_address(options.host_name,
not options.interactive,
False,
options.ip_addresses)
instance_name = "-".join(options.realm_name.split("."))
dirsrv = services.knownservices.dirsrv
if (options.external_cert_files
and dirsrv.is_installed(instance_name)
and not dirsrv.is_running(instance_name)):
logger.debug('Starting Directory Server')
services.knownservices.dirsrv.start(instance_name)
# check addresses here, dns module is doing own check
no_matching_interface_for_ip_address_warning(ip_addresses)
options.ip_addresses = ip_addresses
options.reverse_zones = dns.reverse_zones
if options.setup_adtrust:
with redirect_stdout(ansible_log):
adtrust.install_check(False, options, api)
instance_name = "-".join(options.realm_name.split("."))
dirsrv = services.knownservices.dirsrv
if options.external_cert_files \
and dirsrv.is_installed(instance_name) \
and not dirsrv.is_running(instance_name):
logger.debug('Starting Directory Server')
services.knownservices.dirsrv.start(instance_name)
_update_hosts_file = False
# options needs to update hosts file when DNS subsystem will be
# installed or custom addresses are used
if options.ip_addresses or options.setup_dns:
_update_hosts_file = True
if options.setup_adtrust:
with redirect_stdout(ansible_log):
adtrust.install_check(False, options, api)
if options._host_name_overridden:
tasks.backup_hostname(fstore, sstore)
tasks.set_hostname(options.host_name)
_update_hosts_file = False
# options needs to update hosts file when DNS subsystem will be
# installed or custom addresses are used
if options.ip_addresses or options.setup_dns:
_update_hosts_file = True
if _update_hosts_file:
update_hosts_file(ip_addresses, options.host_name, fstore)
if options._host_name_overridden:
tasks.backup_hostname(fstore, sstore)
tasks.set_hostname(options.host_name)
if hasattr(tasks, "configure_pkcs11_modules"):
if tasks.configure_pkcs11_modules(fstore):
ansible_log.info("Disabled p11-kit-proxy")
if _update_hosts_file:
update_hosts_file(ip_addresses, options.host_name, fstore)
if hasattr(tasks, "configure_pkcs11_modules"):
if tasks.configure_pkcs11_modules(fstore):
ansible_log.info("Disabled p11-kit-proxy")
except (RuntimeError, ValueError, ScriptError,
ipautil.CalledProcessError) as e:
ansible_module.fail_json(msg=str(e))
ansible_module.exit_json(
changed=True,
# basic
ip_addresses=[str(ip) for ip in ip_addresses],
# certificate system
subject_base=options.subject_base,
_subject_base=options._subject_base,
ca_subject=options.ca_subject,
_ca_subject=options._ca_subject,
# dns
reverse_zones=options.reverse_zones,
forward_policy=options.forward_policy,
forwarders=options.forwarders,
no_dnssec_validation=options.no_dnssec_validation,
# additional
dns_ip_addresses=[str(ip) for ip
in dns.ip_addresses],
dns_reverse_zones=dns.reverse_zones,
adtrust_netbios_name=adtrust.netbios_name,
adtrust_reset_netbios_name=adtrust.reset_netbios_name)
ansible_module.exit_json(changed=True,
### basic ###
ip_addresses=[ str(ip) for ip in ip_addresses ],
### certificate system ###
subject_base=options.subject_base,
_subject_base=options._subject_base,
ca_subject=options.ca_subject,
_ca_subject=options._ca_subject,
### dns ###
reverse_zones=options.reverse_zones,
forward_policy=options.forward_policy,
forwarders=options.forwarders,
no_dnssec_validation=options.no_dnssec_validation,
### additional ###
dns_ip_addresses=[ str(ip) for ip
in dns.ip_addresses ],
dns_reverse_zones=dns.reverse_zones,
adtrust_netbios_name=adtrust.netbios_name,
adtrust_reset_netbios_name=adtrust.reset_netbios_name)
if __name__ == '__main__':
main()

View File

@@ -32,10 +32,68 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: set_ds_password
short description:
description:
module: ipaserver_set_ds_password
short description: Set DS password
description: Set DS password
options:
dm_password:
description: Directory Manager password
required: no
password:
description: Admin user kerberos password
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
setup_ca:
description: Configure a dogtag CA
required: no
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
description: The max value for the IDs range (default: idstart+199999)
required: no
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
domainlevel:
description: The domain level
required: yes
author:
- Thomas Woerner
'''
@@ -47,18 +105,22 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
MAX_DOMAIN_LEVEL, AnsibleModuleLog, options, sysrestore, paths,
api_Backend_ldap2, ds_init_info, redirect_stdout
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
password=dict(required=True, no_log=True),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=True),
### server ###
# server
setup_ca=dict(required=True, type='bool'),
idstart=dict(required=True, type='int'),
idmax=dict(required=True, type='int'),
@@ -66,13 +128,13 @@ def main():
no_pkinit=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False),
_dirsrv_pkcs12_info=dict(required=False),
### ssl certificate ###
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
subject_base=dict(required=False),
ca_subject=dict(required=False),
### certificate system ###
# certificate system
external_cert_files=dict(required=False, type='list', default=[]),
### additional ###
# additional
domainlevel=dict(required=False, type='int',
default=MAX_DOMAIN_LEVEL),
),
@@ -83,36 +145,36 @@ def main():
# set values ####################################################
### basic ###
# basic
options.dm_password = ansible_module.params.get('dm_password')
options.admin_password = ansible_module.params.get('password')
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
### server ###
# server
options.setup_ca = ansible_module.params.get('setup_ca')
options.idstart = ansible_module.params.get('idstart')
options.idmax = ansible_module.params.get('idmax')
options.no_hbac_allow = ansible_module.params.get('no_hbac_allow')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get('dirsrv_config_file')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
### ssl certificate ###
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
### certificate system ###
# certificate system
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
### additional ###
# additional
options.domainlevel = ansible_module.params.get('domainlevel')
options.domain_level = options.domainlevel
# init ##########################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
@@ -134,5 +196,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -32,10 +32,35 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: setup_adtrust
short description:
description:
module: ipaserver_setup_adtrust
short description: Setup trust ad
description: Setup trust ad
options:
hostname:
description: Fully qualified name of this host
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
enable_compat:
description: Enable support for trusted domains for old clients
required: yes
rid_base:
description: Start value for mapping UIDs and GIDs to RIDs
required: yes
secondary_rid_base:
description:
Start value of the secondary range for mapping UIDs and GIDs to RIDs
required: yes
adtrust_netbios_name:
description: The adtrust netbios_name setting
required: no
adtrust_reset_netbios_name:
description: The adtrust reset_netbios_name setting
required: no
author:
- Thomas Woerner
'''
@@ -47,22 +72,26 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options, sysrestore, paths,
api_Backend_ldap2, redirect_stdout, adtrust, api
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
# basic
hostname=dict(required=False),
setup_ca=dict(required=False, type='bool', default=False),
setup_adtrust=dict(required=False, type='bool', default=False),
### ad trust ###
# ad trust
enable_compat=dict(required=False, type='bool', default=False),
rid_base=dict(required=False, type='int'),
secondary_rid_base=dict(required=False, type='int'),
### additional ###
# additional
adtrust_netbios_name=dict(required=True),
adtrust_reset_netbios_name=dict(required=True, type='bool')
adtrust_reset_netbios_name=dict(required=True, type='bool'),
),
)
@@ -74,19 +103,19 @@ def main():
options.host_name = ansible_module.params.get('hostname')
options.setup_ca = ansible_module.params.get('setup_ca')
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
### ad trust ###
# ad trust
options.enable_compat = ansible_module.params.get('enable_compat')
options.rid_base = ansible_module.params.get('rid_base')
options.secondary_rid_base = ansible_module.params.get('secondary_rid_base')
### additional ###
options.secondary_rid_base = ansible_module.params.get(
'secondary_rid_base')
# additional
adtrust.netbios_name = ansible_module.params.get('adtrust_netbios_name')
adtrust.reset_netbios_name = \
ansible_module.params.get('adtrust_reset_netbios_name')
adtrust.reset_netbios_name = ansible_module.params.get(
'adtrust_reset_netbios_name')
# init ##########################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
@@ -99,5 +128,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -33,39 +33,119 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: ipaserver_setup_ca
short description:
description:
short description: Setup CA
description: Setup CA
options:
dm_password:
description: Directory Manager password
required: no
password:
description: Admin user kerberos password
required: no
master_password:
description: kerberos master password (normally autogenerated)
required: no
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
pki_config_override:
description: Path to ini file with config overrides
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
description: The max value for the IDs range (default: idstart+199999)
required: no
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
external_ca:
description: External ca setting
required: yes
external_ca_type:
description: Type of the external CA
required: yes
external_ca_profile:
description:
Specify the certificate profile/template to use at the external CA
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: yes
_subject_base:
description: The installer _subject_base setting
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
_ca_subject:
description: The installer _ca_subject setting
required: yes
ca_signing_algorithm:
description: Signing algorithm of the IPA CA certificate
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
domainlevel:
description: The domain level
required: yes
_http_ca_cert:
description: The installer _http_ca_cert setting
required: yes
author:
- Thomas Woerner
'''
@@ -76,13 +156,21 @@ EXAMPLES = '''
RETURN = '''
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options, sysrestore, paths,
ansible_module_get_parsed_ip_addresses,
api_Backend_ldap2, redirect_stdout, ca, installutils, ds_init_info,
custodiainstance, write_cache, x509
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
password=dict(required=True, no_log=True),
master_password=dict(required=True, no_log=True),
@@ -92,7 +180,7 @@ def main():
hostname=dict(required=False),
no_host_dns=dict(required=False, type='bool', default=False),
pki_config_override=dict(required=False),
### server ###
# server
setup_adtrust=dict(required=False, type='bool', default=False),
setup_kra=dict(required=False, type='bool', default=False),
setup_dns=dict(required=False, type='bool', default=False),
@@ -104,19 +192,22 @@ def main():
dirsrv_config_file=dict(required=False),
dirsrv_cert_files=dict(required=False, type='list'),
_dirsrv_pkcs12_info=dict(required=False),
### certificate system ###
# certificate system
external_ca=dict(required=False, type='bool', default=False),
external_cert_files=dict(required=False, type='list', default=[]),
external_ca_type=dict(required=False),
external_ca_profile=dict(required=False),
external_cert_files=dict(required=False, type='list',
default=None),
subject_base=dict(required=False),
_subject_base=dict(required=False),
ca_subject=dict(required=False),
_ca_subject=dict(required=False),
ca_signing_algorithm=dict(required=False),
### dns ###
# dns
reverse_zones=dict(required=False, type='list', default=[]),
no_reverse=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
### additional ###
# additional
domainlevel=dict(required=False, type='int'),
_http_ca_cert=dict(required=False),
),
@@ -127,7 +218,7 @@ def main():
# set values ############################################################
### basic ###
# basic
options.dm_password = ansible_module.params.get('dm_password')
options.admin_password = ansible_module.params.get('password')
options.master_password = ansible_module.params.get('master_password')
@@ -139,7 +230,7 @@ def main():
options.no_host_dns = ansible_module.params.get('no_host_dns')
options.pki_config_override = ansible_module.params.get(
'pki_config_override')
### server ###
# server
options.setup_adtrust = ansible_module.params.get('setup_adtrust')
options.setup_kra = ansible_module.params.get('setup_kra')
options.setup_dns = ansible_module.params.get('setup_dns')
@@ -148,12 +239,16 @@ def main():
options.idmax = ansible_module.params.get('idmax')
options.no_hbac_allow = ansible_module.params.get('no_hbac_allow')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.dirsrv_config_file = ansible_module.params.get('dirsrv_config_file')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
### certificate system ###
# certificate system
options.external_ca = ansible_module.params.get('external_ca')
options.external_ca_type = ansible_module.params.get('external_ca_type')
options.external_ca_profile = ansible_module.params.get(
'external_ca_profile')
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
@@ -162,19 +257,27 @@ def main():
options._ca_subject = ansible_module.params.get('_ca_subject')
options.ca_signing_algorithm = ansible_module.params.get(
'ca_signing_algorithm')
### dns ###
# dns
options.reverse_zones = ansible_module.params.get('reverse_zones')
options.no_reverse = ansible_module.params.get('no_reverse')
options.auto_forwarders = ansible_module.params.get('auto_forwarders')
### additional ###
# additional
options.domainlevel = ansible_module.params.get('domainlevel')
options._http_ca_cert = ansible_module.params.get('_http_ca_cert')
#options._update_hosts_file = ansible_module.params.get('update_hosts_file')
# tions._update_hosts_file = ansible_module.params.get(
# 'update_hosts_file')
# init #################################################################
options.promote = False # first master, no promotion
# Repeat from ca.install_check
# ca.external_cert_file and ca.external_ca_file need to be set
if options.external_cert_files:
ca.external_cert_file, ca.external_ca_file = \
installutils.load_external_cert(
options.external_cert_files, options._ca_subject)
fstore = sysrestore.FileStore(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
@@ -190,53 +293,62 @@ def main():
# setup CA ##############################################################
with redirect_stdout(ansible_log):
if hasattr(custodiainstance, "get_custodia_instance"):
if hasattr(custodiainstance.CustodiaModes, "FIRST_MASTER"):
mode = custodiainstance.CustodiaModes.FIRST_MASTER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
custodia = custodiainstance.get_custodia_instance(options, mode)
if hasattr(custodiainstance, "get_custodia_instance"):
if hasattr(custodiainstance.CustodiaModes, "FIRST_MASTER"):
mode = custodiainstance.CustodiaModes.FIRST_MASTER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
custodia = custodiainstance.get_custodia_instance(options, mode)
custodia.set_output(ansible_log)
with redirect_stdout(ansible_log):
custodia.create_instance()
if options.setup_ca:
if not options.external_cert_files and options.external_ca:
# stage 1 of external CA installation
cache_vars = {n: options.__dict__[n] for o, n in options.knobs()
if n in options.__dict__}
write_cache(cache_vars)
if options.setup_ca:
if not options.external_cert_files and options.external_ca:
# stage 1 of external CA installation
cache_vars = {n: options.__dict__[n] for o, n in options.knobs()
if n in options.__dict__}
write_cache(cache_vars)
if hasattr(custodiainstance, "get_custodia_instance"):
ca.install_step_0(False, None, options, custodia=custodia)
else:
ca.install_step_0(False, None, options)
try:
with redirect_stdout(ansible_log):
if hasattr(custodiainstance, "get_custodia_instance"):
ca.install_step_0(False, None, options, custodia=custodia)
else:
ca.install_step_0(False, None, options)
except SystemExit:
ansible_module.exit_json(changed=True,
csr_generated=True)
else:
# Put the CA cert where other instances expect it
x509.write_certificate(options._http_ca_cert, paths.IPA_CA_CRT)
os.chmod(paths.IPA_CA_CRT, 0o444)
if not options.no_pkinit:
x509.write_certificate(options._http_ca_cert,
paths.KDC_CA_BUNDLE_PEM)
else:
# Put the CA cert where other instances expect it
x509.write_certificate(options._http_ca_cert, paths.IPA_CA_CRT)
os.chmod(paths.IPA_CA_CRT, 0o444)
with open(paths.KDC_CA_BUNDLE_PEM, 'w'):
pass
os.chmod(paths.KDC_CA_BUNDLE_PEM, 0o444)
if not options.no_pkinit:
x509.write_certificate(options._http_ca_cert,
paths.KDC_CA_BUNDLE_PEM)
else:
with open(paths.KDC_CA_BUNDLE_PEM, 'w'):
pass
os.chmod(paths.KDC_CA_BUNDLE_PEM, 0o444)
x509.write_certificate(options._http_ca_cert, paths.CA_BUNDLE_PEM)
os.chmod(paths.CA_BUNDLE_PEM, 0o444)
x509.write_certificate(options._http_ca_cert, paths.CA_BUNDLE_PEM)
os.chmod(paths.CA_BUNDLE_PEM, 0o444)
with redirect_stdout(ansible_log):
# we now need to enable ssl on the ds
ds.enable_ssl()
if options.setup_ca:
with redirect_stdout(ansible_log):
if hasattr(custodiainstance, "get_custodia_instance"):
ca.install_step_1(False, None, options, custodia=custodia)
else:
ca.install_step_1(False, None, options)
if options.setup_ca:
with redirect_stdout(ansible_log):
if hasattr(custodiainstance, "get_custodia_instance"):
ca.install_step_1(False, None, options, custodia=custodia)
else:
ca.install_step_1(False, None, options)
ansible_module.exit_json(changed=True,
csr_generated=False)
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -33,12 +33,18 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: ipaserver_setup_custodia
short description:
description:
short description: Setup custodia
description: Setup custodia
options:
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
author:
- Thomas Woerner
'''
@@ -50,11 +56,16 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options,
api_Backend_ldap2,
custodiainstance, redirect_stdout
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
# basic
realm=dict(required=True),
hostname=dict(required=False),
@@ -74,8 +85,6 @@ def main():
# init ##################################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
# setup custodia ########################################################
@@ -97,5 +106,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -32,17 +32,46 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: setup_dns
short description:
description:
module: ipaserver_setup_dns
short description: Setup DNS
description: Setup DNS
options:
ip_addresses:
description: List of Master Server IP Addresses
required: yes
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: no
setup_dns:
description: Configure bind with our zone
required: no
setup_ca:
description: Configure a dogtag CA
required: no
zonemgr:
description: DNS zone manager e-mail address. Defaults to hostmaster@DOMAIN
required: yes
forwarders:
description: Add DNS forwarders
required: no
forward_policy:
description: DNS forwarding policy for global forwarders
required: yes
no_dnssec_validation:
description: Disable DNSSEC validation
required: yes
dns_ip_addresses:
description: The dns ip_addresses setting
required: no
dns_reverse_zones:
description: The dns reverse_zones setting
required: no
author:
- Thomas Woerner
'''
@@ -54,23 +83,31 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options, paths, dns,
ansible_module_get_parsed_ip_addresses, sysrestore, api_Backend_ldap2,
redirect_stdout, bindinstance
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
ip_addresses=dict(required=False, type='list', default=[]),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=True),
### server ###
# server
setup_dns=dict(required=True, type='bool'),
setup_ca=dict(required=True, type='bool'),
### dns ###
# dns
zonemgr=dict(required=False),
forwarders=dict(required=True, type='list'),
forward_policy=dict(default='first', choices=['first', 'only']),
no_dnssec_validation=dict(required=False, type='bool',
default=False),
### additional ###
# additional
dns_ip_addresses=dict(required=True, type='list'),
dns_reverse_zones=dict(required=True, type='list'),
),
@@ -81,18 +118,22 @@ def main():
# set values ############################################################
### basic ###
# basic
options.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module)
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
### server ###
# server
options.setup_dns = ansible_module.params.get('setup_dns')
options.setup_ca = ansible_module.params.get('setup_ca')
### dns ###
# dns
options.zonemgr = ansible_module.params.get('zonemgr')
options.forwarders = ansible_module.params.get('forwarders')
options.forward_policy = ansible_module.params.get('forward_policy')
options.no_dnssec_validation = ansible_module.params.get(
'no_dnssec_validation')
### additional ###
# additional
dns.ip_addresses = ansible_module_get_parsed_ip_addresses(
ansible_module, 'dns_ip_addresses')
dns.reverse_zones = ansible_module.params.get('dns_reverse_zones')
@@ -112,8 +153,9 @@ def main():
# Create a BIND instance
bind = bindinstance.BindInstance(fstore)
bind.set_output(ansible_log)
bind.setup(host_name, ip_addresses, realm_name,
domain_name, (), 'first', (),
bind.setup(options.host_name, options.ip_addresses,
options.realm_name,
options.domain_name, (), 'first', (),
zonemgr=options.zonemgr,
no_dnssec_validation=options.no_dnssec_validation)
bind.create_file_with_system_records()
@@ -122,5 +164,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -33,21 +33,64 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: ipaserver_setup_ds
short description:
description:
short description: Configure directory server
description: Configure directory server
options:
dm_password:
description: Directory Manager password
required: no
password:
description: Admin user kerberos password
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
no_pkinit:
description: The max value for the IDs range (default: idstart+199999)
required: no
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: yes
ca_subject:
setup_ca
description: The installer ca_subject setting
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
author:
- Thomas Woerner
'''
@@ -59,31 +102,37 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options, sysrestore, paths,
api_Backend_ldap2, redirect_stdout, api, NUM_VERSION, tasks,
dsinstance, ntpinstance, IPAAPI_USER
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
### basic ###
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
password=dict(required=True, no_log=True),
domain=dict(required=True),
realm=dict(required=True),
hostname=dict(required=False),
### server ###
# server
idstart=dict(required=True, type='int'),
idmax=dict(required=True, type='int'),
no_hbac_allow=dict(required=False, type='bool', default=False),
no_pkinit=dict(required=False, type='bool', default=False),
dirsrv_config_file=dict(required=False),
### ssl certificate ###
# ssl certificate
dirsrv_cert_files=dict(required=False, type='list', default=[]),
### certificate system ###
_dirsrv_pkcs12_info=dict(required=False),
# certificate system
external_cert_files=dict(required=False, type='list', default=[]),
subject_base=dict(required=False),
ca_subject=dict(required=False),
### additional ###
# additional
setup_ca=dict(required=False, type='bool', default=False),
),
)
@@ -93,26 +142,29 @@ def main():
# set values ############################################################
### basic ###
# basic
options.dm_password = ansible_module.params.get('dm_password')
options.domain_name = ansible_module.params.get('domain')
options.realm_name = ansible_module.params.get('realm')
options.host_name = ansible_module.params.get('hostname')
### server ###
# server
options.idstart = ansible_module.params.get('idstart')
options.idmax = ansible_module.params.get('idmax')
options.no_pkinit = ansible_module.params.get('no_pkinit')
options.no_hbac_allow = ansible_module.params.get('no_hbac_allow')
options.dirsrv_config_file = ansible_module.params.get('dirsrv_config_file')
### ssl certificate ###
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
# ssl certificate
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
### certificate system ###
# certificate system
options.external_cert_files = ansible_module.params.get(
'external_cert_files')
options.subject_base = ansible_module.params.get('subject_base')
options.ca_subject = ansible_module.params.get('ca_subject')
### additional ###
# additional
options.setup_ca = ansible_module.params.get('setup_ca')
# init ##################################################################
@@ -127,7 +179,7 @@ def main():
# Make sure tmpfiles dir exist before installing components
if NUM_VERSION == 40504:
tasks.create_tmpfiles_dirs(IPAAPI_USER)
elif NUM_VERSION >= 40500 and NUM_VERSION <= 40503:
elif 40500 <= NUM_VERSION <= 40503:
tasks.create_tmpfiles_dirs()
# Create a directory server instance
@@ -138,9 +190,9 @@ def main():
ds.set_output(ansible_log)
if options.dirsrv_cert_files:
_dirsrv_pkcs12_info=options.dirsrv_pkcs12_info
_dirsrv_pkcs12_info = options._dirsrv_pkcs12_info
else:
_dirsrv_pkcs12_info=None
_dirsrv_pkcs12_info = None
with redirect_stdout(ansible_log):
ds.create_instance(options.realm_name, options.host_name,
@@ -173,5 +225,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -32,10 +32,111 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: setup_ds
short description:
description:
module: ipaserver_setup_http
short description: Setup HTTP
description: Setup HTTP
options:
dm_password:
description: Directory Manager password
required: no
password:
description: Admin user kerberos password
required: no
master_password:
description: kerberos master password (normally autogenerated)
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
http_cert_files:
description:
File containing the Apache Server SSL certificate and private key
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
no_ui_redirect:
description: Do not automatically redirect to the Web UI
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: yes
_subject_base:
description: The installer _subject_base setting
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
_ca_subject:
description: The installer _ca_subject setting
required: yes
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
description: The max value for the IDs range (default: idstart+199999)
required: no
domainlevel:
description: The domain level
required: yes
dirsrv_config_file:
description:
The path to LDIF file that will be used to modify configuration of
dse.ldif during installation of the directory server instance
required: yes
dirsrv_cert_files:
description:
Files containing the Directory Server SSL certificate and private key
required: yes
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
_dirsrv_pkcs12_info:
description: The installer _dirsrv_pkcs12_info setting
required: yes
_http_pkcs12_info:
description: The installer _http_pkcs12_info setting
required: yes
author:
- Thomas Woerner
'''
@@ -47,11 +148,17 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options, sysrestore, paths,
ansible_module_get_parsed_ip_addresses,
api_Backend_ldap2, redirect_stdout, ds_init_info,
krbinstance, httpinstance, ca, service, tasks
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
password=dict(required=True, no_log=True),
@@ -90,8 +197,10 @@ def main():
no_reverse=dict(required=False, type='bool', default=False),
auto_forwarders=dict(required=False, type='bool', default=False),
#_update_hosts_file=dict(required=False, type='bool', default=False),
# _update_hosts_file=dict(required=False, type='bool',
# default=False),
_dirsrv_pkcs12_info=dict(required=False),
_http_pkcs12_info=dict(required=False),
),
)
@@ -135,12 +244,16 @@ def main():
options.idstart = ansible_module.params.get('idstart')
options.idmax = ansible_module.params.get('idmax')
options.domainlevel = ansible_module.params.get('domainlevel')
options.dirsrv_config_file = ansible_module.params.get('dirsrv_config_file')
options.dirsrv_config_file = ansible_module.params.get(
'dirsrv_config_file')
options.dirsrv_cert_files = ansible_module.params.get('dirsrv_cert_files')
#options._update_hosts_file = ansible_module.params.get('_update_hosts_file')
# options._update_hosts_file = ansible_module.params.get(
# '_update_hosts_file')
options._dirsrv_pkcs12_info = ansible_module.params.get(
'_dirsrv_pkcs12_info')
options._http_pkcs12_info = ansible_module.params.get(
'_http_pkcs12_info')
# init ##################################################################
@@ -173,13 +286,16 @@ def main():
with redirect_stdout(ansible_log):
if options.http_cert_files:
http.create_instance(
options.realm_name, options.host_name, options.domain_name, options.dm_password,
pkcs12_info=options._http_pkcs12_info, subject_base=options.subject_base,
options.realm_name, options.host_name, options.domain_name,
options.dm_password,
pkcs12_info=options._http_pkcs12_info,
subject_base=options.subject_base,
auto_redirect=not options.no_ui_redirect,
ca_is_configured=options.setup_ca)
else:
http.create_instance(
options.realm_name, options.host_name, options.domain_name, options.dm_password,
options.realm_name, options.host_name, options.domain_name,
options.dm_password,
subject_base=options.subject_base,
auto_redirect=not options.no_ui_redirect,
ca_is_configured=options.setup_ca)
@@ -204,5 +320,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -32,10 +32,28 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: setup_kra
short description:
description:
module: ipaserver_setup_kra
short description: Setup KRA
description: Setup KRA
options:
dm_password:
description: Directory Manager password
required: no
hostname:
description: Fully qualified name of this host
required: no
setup_ca:
description: Configure a dogtag CA
required: no
setup_kra:
description: Configure a dogtag KRA
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
pki_config_override:
description: Path to ini file with config overrides
required: yes
author:
- Thomas Woerner
'''
@@ -47,11 +65,15 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options,
api_Backend_ldap2, redirect_stdout, api, custodiainstance, kra
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
hostname=dict(required=True),
@@ -78,18 +100,17 @@ def main():
# init ##########################################################
fstore = sysrestore.FileStore(paths.SYSRESTORE)
sstore = sysrestore.StateFile(paths.SYSRESTORE)
api_Backend_ldap2(options.host_name, options.setup_ca, connect=True)
# setup kra #####################################################
with redirect_stdout(ansible_log):
if hasattr(custodiainstance, "get_custodia_instance"):
custodia = custodiainstance.get_custodia_instance(
options, custodiainstance.CustodiaModes.MASTER_PEER)
custodia.create_instance()
if hasattr(custodiainstance.CustodiaModes, "FIRST_MASTER"):
mode = custodiainstance.CustodiaModes.FIRST_MASTER
else:
mode = custodiainstance.CustodiaModes.MASTER_PEER
custodia = custodiainstance.get_custodia_instance(options, mode)
kra.install(api, None, options, custodia=custodia)
else:
@@ -99,5 +120,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

View File

@@ -32,10 +32,83 @@ ANSIBLE_METADATA = {
DOCUMENTATION = '''
---
module: setup_ds
short description:
description:
module: ipaserver_setup_krb
short description: Setup KRB
description: Setup KRB
options:
dm_password:
description: Directory Manager password
required: no
password:
description: Admin user kerberos password
required: no
master_password:
description: kerberos master password (normally autogenerated)
required: no
domain:
description: Primary DNS domain of the IPA deployment
required: no
realm:
description: Kerberos realm name of the IPA deployment
required: no
hostname:
description: Fully qualified name of this host
required: yes
ip_addresses:
description: List of Master Server IP Addresses
required: yes
reverse_zones:
description: The reverse DNS zones to use
required: yes
setup_adtrust:
description: Configure AD trust capability
required: yes
setup_kra:
description: Configure a dogtag KRA
required: yes
setup_dns:
description: Configure bind with our zone
required: yes
setup_ca:
description: Configure a dogtag CA
required: yes
no_host_dns:
description: Do not use DNS for hostname lookup during installation
required: yes
no_pkinit:
description: Disable pkinit setup steps
required: yes
no_hbac_allow:
description: Don't install allow_all HBAC rule
required: yes
external_cert_files:
description:
File containing the IPA CA certificate and the external CA certificate
chain
required: yes
subject_base:
description:
The certificate subject base (default O=<realm-name>).
RDNs are in LDAP order (most specific RDN first).
required: yes
ca_subject:
description: The installer ca_subject setting
required: yes
idstart:
description: The starting value for the IDs range (default random)
required: no
idmax:
description: The max value for the IDs range (default: idstart+199999)
required: no
no_reverse:
description: Do not create new reverse DNS zone
required: yes
auto_forwarders:
description: Use DNS forwarders configured in /etc/resolv.conf
required: yes
_pkinit_pkcs12_info:
description: The installer _pkinit_pkcs12_info setting
required: yes
author:
- Thomas Woerner
'''
@@ -47,11 +120,16 @@ RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_ipa_server import *
from ansible.module_utils.ansible_ipa_server import (
AnsibleModuleLog, options, sysrestore, paths,
ansible_module_get_parsed_ip_addresses,
api_Backend_ldap2, redirect_stdout, krbinstance
)
def main():
ansible_module = AnsibleModule(
argument_spec = dict(
argument_spec=dict(
# basic
dm_password=dict(required=True, no_log=True),
password=dict(required=True, no_log=True),
@@ -125,7 +203,8 @@ def main():
options._pkinit_pkcs12_info = ansible_module.params.get(
'_pkinit_pkcs12_info')
#options._update_hosts_file = ansible_module.params.get('update_hosts_file')
# options._update_hosts_file = ansible_module.params.get(
# 'update_hosts_file')
# init ##################################################################
@@ -152,5 +231,6 @@ def main():
ansible_module.exit_json(changed=True)
if __name__ == '__main__':
main()

Some files were not shown because too many files have changed in this diff Show More