Compare commits

...

98 Commits

Author SHA1 Message Date
Rafael Guterres Jeffman
1dd2b54e77 Merge pull request #155 from t-woerner/ipahost-extension
ipahost: Extension to be able handle several hosts and all settings
2019-12-02 14:01:21 -03:00
Thomas Woerner
a62e355f9c Merge pull request #157 from t-woerner/centos8
ipa[server,replica,client]: Add support for CentOS-8
2019-12-02 17:30:50 +01:00
Thomas Woerner
fbe2880452 Merge pull request #156 from t-woerner/env_krb5ccname
ansible_freeipa_module: Better support for KRB5CCNAME environment variable
2019-12-02 17:30:42 +01:00
Thomas Woerner
94b1f25b37 ipahost: Extension to be able handle several hosts and all settings
The ipahost management module was not able to add several hosts at once.
Addtionally there have been settings missing.

ansible_freeipa_module has been extended to provide two additional functions
that are needed to simplify the extension of the ipahost module:

    gen_add_del_lists(user_list, res_list)
    encode_certificate(cert)

gen_add_del_lists will generate the lists for the addition and removal of
members using the provided user and ipa settings.

encode_certificate will encode a certificate using base64 with also taking
FreeIPA and Python versions into account.

The missing settings in ipahost have been:

    certificate
    managedby_host
    principal
    create_keytab_[user,group,host,hostgroup]
    retrieve_keytab_[user,group,host,hostgroup]
    sshpubkey
    userclass
    auth_ind
    requires_pre_auth
    ok_as_delegate
    ok_to_auth_as_delegate

The README-host.md file has been updated to provide information about the
new settings and also the members. Also examples for the new things have
been added.

New example playbooks have been added:

    playbooks/host/add-host.yml
    playbooks/host/host-member-allow_create_keytab-absent.yml
    playbooks/host/host-member-allow_create_keytab-present.yml
    playbooks/host/host-member-allow_retrieve_keytab-absent.yml
    playbooks/host/host-member-allow_retrieve_keytab-present.yml
    playbooks/host/host-member-certificate-absent.yml
    playbooks/host/host-member-certificate-present.yml
    playbooks/host/host-member-managedby_host-absent.yml
    playbooks/host/host-member-managedby_host-present.yml
    playbooks/host/host-member-principal-absent.yml
    playbooks/host/host-member-principal-present.yml
    playbooks/host/host-present-with-allow_create_keytab.yml
    playbooks/host/host-present-with-allow_retrieve_keytab.yml
    playbooks/host/host-present-with-certificate.yml
    playbooks/host/host-present-with-managedby_host.yml
    playbooks/host/host-present-with-principal.yml
    playbooks/host/host-present-with-randompassword.yml
    playbooks/host/host-present.yml
    playbooks/host/hosts-member-certificate-absent.yml
    playbooks/host/hosts-member-certificate-present.yml
    playbooks/host/hosts-member-managedby_host-absent.yml
    playbooks/host/hosts-member-managedby_host-present.yml
    playbooks/host/hosts-member-principal-absent.yml
    playbooks/host/hosts-member-principal-present.yml
    playbooks/host/hosts-present-with-certificate.yml
    playbooks/host/hosts-present-with-managedby_host.yml
    playbooks/host/hosts-present-with-randompasswords.yml

New tests have been added for the module:

    tests/host/certificate/cert1.der
    tests/host/certificate/cert1.pem
    tests/host/certificate/cert2.der
    tests/host/certificate/cert2.pem
    tests/host/certificate/cert3.der
    tests/host/certificate/cert3.pem
    tests/host/certificate/private1.key
    tests/host/certificate/private2.key
    tests/host/certificate/private3.key
    tests/host/certificate/test_host_certificate.yml
    tests/host/certificate/test_hosts_certificate.yml
    tests/host/test_host.yml
    tests/host/test_host_allow_create_keytab.yml
    tests/host/test_host_allow_retrieve_keytab.yml
    tests/host/test_host_managedby_host.yml
    tests/host/test_host_principal.yml
    tests/host/test_host_random.yml
    tests/host/test_hosts.yml
    tests/host/test_hosts_managedby_host.yml
    tests/host/test_hosts_principal.yml
2019-12-02 17:23:04 +01:00
Thomas Woerner
5d7f2788f3 ipa[server,replica,client]: Add support for CentOS-8
The files for RHEL-8 (RedHat-8.yml) have simply been linked to CentOS-8.yml
for the ipaserver, ipareplica and ipaclient roles.

Fixes issue #121 (roles/*/vars needs CentOS-8.yml files)
2019-12-02 15:58:47 +01:00
Thomas Woerner
e77f4daaa9 ansible_freeipa_module: Better support for KRB5CCNAME environment variable
The use of gssapi.creds.Credentials is not good if krb5 ticket forwarding
is used. It will fail. gssapi.Credentials with usage and store is the proper
way to do this.
2019-12-02 15:51:00 +01:00
Thomas Woerner
8da4b73b44 Merge pull request #153 from rjeffman/api_context_change
Added context configuration to api_connect.
2019-11-29 18:22:46 +01:00
Rafael Guterres Jeffman
608614110d Added context configuration to api_connect.
This patch allows the connection to the ipa api to use a context different
than 'server', if needed.
2019-11-29 12:59:33 -03:00
Rafael Guterres Jeffman
16cbb87126 Merge pull request #147 from t-woerner/ipaclient_sssd_option_name_fix
ipaclient: Fix misspelled sssd options
2019-11-21 10:12:04 -03:00
Varun Mylaraiah
db49ac66d7 Merge pull request #148 from t-woerner/return_random_passwords
ipauser, ipahost: Return random password
2019-11-21 11:57:01 +05:30
Thomas Woerner
c36cb9543b ipahost: Return generated random password
The random password is only returned if random is yes and the host did
not exist or update_password is yes.

If only one host is handled by the module, the returned dict is containing
this dict:

  { "randompassword": "<the host random password>" }

If several hosts are handled by the module (future feature):

  { "<host>": { "randompassword": "<the host random password>" } }

Fixes issue #134 (ipahost does not return the random password)
2019-11-20 19:50:39 +01:00
Thomas Woerner
b5f209225b ipauser: Return generated random password
The random password is only returned if random is yes and user did not exist
or update_password is yes.

If only one user is handled by the module, the returned dict is containing
this dict:

  { "randompassword": "<the user random password>" }

If several users are handled by the module:

  { "<user>": { "randompassword": "<the user random password>" } }

This is related to issue #134 (ipahost does not return the random password)
2019-11-20 19:49:32 +01:00
Thomas Woerner
6ad82e6bc7 ipaclient: Fix misspelled sssd options
The sssd options in the ipaclient role missed a 's' in the role. The readme
of the role used the proper names with 3 's'. The names in the role have
been fixed and if the old setting are used, they will be used in the first
place.

Also utils/ansible-ipa-client-install has been adaped to use the proper
option names now.

This fixes issue #145 (The ipaclient role misspells sssd)
2019-11-20 12:26:29 +01:00
Thomas Woerner
63924dd6fc Update README-user.md
Add missing information about action variable.
2019-11-19 15:25:53 +01:00
Thomas Woerner
d7a109b7bf Update README-user.md
Fix "Example playbook to delete a user is absent, but preserved"
2019-11-19 15:24:19 +01:00
Thomas Woerner
439552ed8a Merge pull request #143 from cdchapman/feature/support-sn-alias
Support 'sn' alias of 'last' for surname
2019-11-15 16:48:56 +01:00
Thomas Woerner
80d9c05e66 Update ipauser.py: Fix typo in users.name description 2019-11-15 16:37:07 +01:00
Thomas Woerner
f816d3e7ff Update galaxy.yml: Update description, drop empty dependencies
Update description, drop empty dependencies.
Fixes #146 (ansible-freeipa collection not installable by 2.9 ansible-galaxy collection install)
2019-11-12 16:12:37 +01:00
Thomas Woerner
539e15aab3 Update README.md: Add ansible-galaxy collection command for ansible 2.9+
Add command and information about ansible-galaxy collection install. Installing collections
using the ansible-galaxy command is only supported with ansible 2.9+. The mazer tool can
be used for to install the collection for ansible 2.8:
2019-11-12 10:54:07 +01:00
Chris Chapman
f7eef810af Add 'sn' as an alias of 'last' 2019-11-09 11:45:19 -07:00
Chris Chapman
1e3235e281 Only change one to test that 'sn' returns the same value as 'last' 2019-11-09 11:44:52 -07:00
Chris Chapman
12408e0143 Support 'sn' alias of 'last' for surname 2019-11-07 14:05:03 -07:00
Rafael Guterres Jeffman
b06ef3fc09 Merge pull request #142 from t-woerner/ipahostgroup_tests
ipahostgroup: Fix changed flag, support IPA 4.6 on RHEL-7, new test cases
2019-11-07 09:52:05 -03:00
Thomas Woerner
dba8c204ff Merge pull request #141 from rjeffman/sudorule
New sudorule (Sudo Rule) management module
2019-11-07 13:46:16 +01:00
Rafael Guterres Jeffman
2f62160846 New sudorule (Sudo Rule) management module
There is a new sudorule (Sudo Rule) management module placed in the plugins
folder:

  plugins/modules/ipasudorule.py

The sudorule module allows to ensure presence and absence of Sudo Rules.

Here is the documentation for the module:

  README-sudorule.md

New example playbooks have been added:

    playbooks/sudorule/ensure-sudorule-host-member-is-absent.yml
    playbooks/sudorule/ensure-sudorule-host-member-is-present.yml
    playbooks/sudorule/ensure-sudorule-hostgroup-member-is-absent.yml
    playbooks/sudorule/ensure-sudorule-hostgroup-member-is-present.yml
    playbooks/sudorule/ensure-sudorule-is-absent.yml
    playbooks/sudorule/ensure-sudorule-is-disabled.yml
    playbooks/sudorule/ensure-sudorule-is-enabled.yml
    playbooks/sudorule/ensure-sudorule-is-present.yml
    playbooks/sudorule/ensure-sudorule-sudocmd-is-absent.yml
    playbooks/sudorule/ensure-sudorule-sudocmd-is-present.yml

New tests added for the module:

  tests/hbacrule/test_sudorule.yml
2019-11-07 09:37:45 -03:00
Thomas Woerner
209e471553 Merge pull request #102 from Uumas/preotp
Added support for predefining client OTP using ipaclient_otp
2019-11-07 13:34:42 +01:00
Thomas Woerner
0e64c80cd1 ipahostgroup: Fix changed flag, support IPA 4.6 on RHEL-7, new test cases
The changed flag returned by ipahostgroup calls have not always been correct.
The use of the module with IPA version 4.6 on RHEL-7 resulted in encoding
errors. All this has been fixed.

Addtitionally new test cases have been added to make sure that the issues
are solved.
2019-11-07 12:46:50 +01:00
Thomas Woerner
0c30020a7b Merge pull request #140 from t-woerner/ipahbacrule
New hbacrule (HBAC Rule) management module
2019-11-05 12:49:58 +01:00
Thomas Woerner
d36d25d62a New hbacrule (HBAC Rule) management module
There is a new hbacrule (HBAC Rule) management module placed in the plugins
folder:

  plugins/modules/ipahbacrule.py

The hbacrule module allows to ensure presence and absence of HBAC Rules.

Here is the documentation for the module:

  README-hbacrule.md

New example playbooks have been added:

  playbooks/hbacrule/ensure-hbarule-allhosts-absent.yml
  playbooks/hbacrule/ensure-hbarule-allhosts-disabled.yml
  playbooks/hbacrule/ensure-hbarule-allhosts-enabled.yml
  playbooks/hbacrule/ensure-hbarule-allhosts-present.yml
  playbooks/hbacrule/ensure-hbarule-allhosts-server-member-absent.yml
  playbooks/hbacrule/ensure-hbarule-allhosts-server-member-present.yml

New tests added for the module:

  tests/hbacrule/test_hbacrule.yml
2019-11-05 10:56:22 +01:00
Thomas Woerner
6af0d9b7c7 Merge pull request #139 from t-woerner/ipauser_passwordexpiration_info
ipauser: Add info about version limitation of passwordexpiration
2019-10-31 15:54:31 +01:00
Thomas Woerner
dd2e1d3aaa ipauser: Add info about version limitation of passwordexpiration
The information about the version limitation of the passwordexpiration
parameter has been missing. The parameter is only usable for IPA versions
4.7 and up.
2019-10-31 11:41:50 +01:00
Thomas Woerner
d8cddb3c7c Merge pull request #138 from t-woerner/ipagroup_fix_changed
ipagroup: Fix changed flag, new test cases
2019-10-31 11:06:00 +01:00
Thomas Woerner
1aaa3b30e0 Merge pull request #137 from t-woerner/ipagroup_pre_4_7_support
ipagroup: Properly support IPA versions 4.6 and RHEL-7
2019-10-31 11:05:40 +01:00
Thomas Woerner
ff9ce6b86a ipagroup: Fix changed flag, new test cases
The changed flag returned by ipagroup calls have not been correct. This
change fixes this. Addtitionally new test cases have been added to make
sure that the changed flag is correct.
2019-10-30 16:27:12 +01:00
Thomas Woerner
a4a15defa9 ipagroup: Properly support IPA versions 4.6 and RHEL-7
group_add_member is only supporting services in more recent IPA versions.
This is 4.7+. Code has been added to detect if services are supported by
the used IPA version and used in the parameters of the module. In this case
an error is printed.

Additionally all parameters will be get from the module using
module_params_get provided by ansible_freeipa_module. Additional to_text
conversions have been removed as they are not needed anymore with this.
2019-10-30 16:12:18 +01:00
Varun Mylaraiah
6e6e193ab2 Merge pull request #136 from t-woerner/ipahbacsvcgroup
New hbacsvcgroup (HBAC Service Group) management module
2019-10-25 23:09:34 +05:30
Thomas Woerner
4b9860e1d2 New hbacsvcgroup (HBAC Service Group) management module
There is a new hbacsvcgroup (HBAC Service Group) management module placed
in the plugins folder:

  plugins/modules/ipahbacsvcgroup.py

The hbacsvc module allows to ensure presence and absence of HBAC Service
Groups.

Here is the documentation for the module:

  README-hbacsvcgroup.md

New example playbooks have been added:

  playbooks/hbacsvcgroup/ensure-hbacsvcgroup-absent.yml
  playbooks/hbacsvcgroup/ensure-hbacsvcgroup-member-absent.yml
  playbooks/hbacsvcgroup/ensure-hbacsvcgroup-member-present.yml
  playbooks/hbacsvcgroup/ensure-hbacsvcgroup-present.yml

New tests added for the module:

   tests/hbacsvcgroup/test_hbacsvcgroup.yml
2019-10-25 12:51:37 +02:00
Thomas Woerner
5a462ece9b Update README.md
Updated requirements for python3-gssapi
2019-10-25 11:18:32 +02:00
Varun Mylaraiah
a9cf33f3b9 Merge pull request #135 from t-woerner/ipahbacsvc
New hbacsvc (HBAC Service) management module
2019-10-24 18:41:15 +05:30
Thomas Woerner
42eaadfbbf New hbacsvc (HBAC Service) management module
There is a new hbacsvc (HBAC Service) management module placed in the plugins
folder:

  plugins/modules/ipahbacsvc.py

The hbacsvc module allows to ensure presence and absence of HBAC Services.

Here is the documentation for the module:

  README-hbacsvc.md

New example playbooks have been added:

  playbooks/hbacsvc/ensure-hbacsvc-absent.yml
  playbooks/hbacsvc/ensure-hbacsvc-present.yml

New tests added for pwpolicy:

  tests/hbacsvc/test_hbacsvc.yml
2019-10-24 14:35:12 +02:00
Thomas Woerner
13eb30f1e2 Merge pull request #132 from t-woerner/ipapwpolicy
Ipapwpolicy
2019-10-22 12:46:10 +02:00
Thomas Woerner
b3fd3a518e New pwpolicy management module
There is a new pwpolicy management module placed in the plugins folder:

  plugins/modules/ipapwpolicy.py

The pwpolicy module allows to ensure presence and absence of pwpolicies for
groups.

Here is the documentation for the module:

  README-pwpolicy.md

New example playbooks have been added:

  playbooks/pwpolicy/pwpolicy_absent.yml
  playbooks/pwpolicy/pwpolicy_present.yml

New tests added for pwpolicy:

  tests/pwpolicy/test_pwpolicy.yml
2019-10-22 12:41:45 +02:00
Thomas Woerner
5d435c375c ansible_freeipa_module: Convert int to string in compare_args_ipa
With IPA 4.5 integers for examle in pwpolicy_find are returned as
integer values. The internally generated value will be converted from
integer to string (using to_text) if the value from find call result
is a string (or unicode for Python2).
2019-10-22 12:41:07 +02:00
Thomas Woerner
ccc001ada0 Merge pull request #133 from rjeffman/sudocmdgrp
New sudocmdgroup management module.
2019-10-22 12:07:17 +02:00
Rafael Guterres Jeffman
fce3935d03 New sudocmdgroup management module.
There is a new sudocmdgroup management module placed in the plugins folder:

plugins/modules/ipasudocmdgroup.py

The sudocmdgroup module allows to add or remove sudo command groups..

The sudocmdgroup module is as compatible as possible to the Ansible upstream
ipa_sudocmdgroup module, and additionally offers to ensure member presence
and absence.

Here is the documentation for the module:

  README-sudocmdgroup.md

New example playbooks have been added:

  playbooks/sudocmd/ensure-sudocmdgroup-is-absent.yml
  playbooks/sudocmd/ensure-sudocmdgroup-is-present.yml
  playbooks/sudocmd/ensure-sudocmd-is-absent-in-sudocmdgroup.yml
  playbooks/sudocmd/ensure-sudocmd-is-present-in-sudocmdgroup.yml

A test playbook is provided in:

  tests/sudocmdgroup/test_sudocmdgroup.yml

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2019-10-22 06:53:37 -03:00
Thomas Woerner
12c4227385 Merge pull request #130 from rjeffman/sudocmd
New sudocmd management module.
2019-10-22 11:44:56 +02:00
Rafael Guterres Jeffman
5d962c06ca New sudocmd management module.
There is a new sudocmd management module placed in the plugins folder:

  plugins/modules/ipasudocmd.py

The sudocmd module allows to add or remove sudo commands.

The sudocmd module is as compatible as possible to the Ansible upstream
ipa_sudocmd module.

Here is the documentation for the module:

  README-sudocmd.md

New example playbooks have been added:

  playbooks/sudocmd/ensure-sudocmd-is-absent.yml
  playbooks/sudocmd/ensure-sudocmd-is-present.yml

Signed-off-by: Rafael Guterres Jeffman <rjeffman@redhat.com>
2019-10-22 06:39:30 -03:00
Thomas Woerner
bf664f6861 Merge pull request #131 from t-woerner/ipauser-rework
Ipauser rework
2019-10-22 11:16:31 +02:00
Thomas Woerner
40713e71f9 ipauser: User module extension
The ipauser module now supports all user settings and additionally to ensure
the presence of several users with the new users setting. The users setting
can also be used with other states, but it has to be limited to only contain
the name of the users.

There updated user management module is placed in the plugins folder:

  plugins/modules/ipauser.py

The user module now additionally allows to handle these user settings:

  initials
  principalexpiration
  random
  city
  userstate
  postalcode
  mobile
  pager
  fax
  orgunit
  manager
  carlicense
  sshpubkey
  userauthtype
  userclass
  radius
  radiususer
  departmentnumber
  employeenumber
  employeetype
  preferredlanguage
  certificate
  certmapdata
  noprivate
  nomembers

Here is the updated documentation for the module:

  README-user.md

New example playbooks have been added:

  playbooks/user/user_certificate_absent.yml
  playbooks/user/user_certificate_present.yml
  playbooks/user/user_present.yml
  playbooks/user/users_absent.yml
  playbooks/user/users_certificate_absent.yml
  playbooks/user/users_certificate_present.yml
  playbooks/user/users_present.yml
  plugins/modules/ipauser.py

New tests added for ipauser:

  tests/user/certificate/cert1.der
  tests/user/certificate/cert1.pem
  tests/user/certificate/cert2.der
  tests/user/certificate/cert2.pem
  tests/user/certificate/cert3.der
  tests/user/certificate/cert3.pem
  tests/user/certificate/private1.key
  tests/user/certificate/private2.key
  tests/user/certificate/private3.key
  tests/user/certificate/test_user_certificate.yml
  tests/user/certificate/test_users_certificate.yml
  tests/user/certmapdata/test_user_certmapdata.yml
  tests/user/certmapdata/test_user_certmapdata_issuer_subject.yml
  tests/user/certmapdata/test_users_certmapdata.yml
  tests/user/test_user.yml
  tests/user/test_users.yml
  tests/user/test_users_absent.yml
  tests/user/test_users_invalid_cert.yml
  tests/user/test_users_present.yml
  tests/user/test_users_present_slice.yml
  tests/user/users_absent.json
  tests/user/users_absent.sh
  tests/user/users_present.json
  tests/user/users_present.sh
2019-10-21 15:44:00 +02:00
Thomas Woerner
1428143d73 ansible_freeipa_module: New function api_get_realm
The function api_get_realm is returning the realm of a connected FreeIPA
api. This is needed for proper principal checks in the extended ipauser
module that supports principals now.
2019-10-21 15:43:59 +02:00
Thomas Woerner
8932842288 ansible_freeipa_module: Convert tuple to list in compare_args_ipa
The conversion is needed because older FreeIPA versions are returning
tuples in some cases instead of lists. To be able to compare them the
conversion to a list is needed.
2019-10-21 15:43:58 +02:00
Thomas Woerner
b1a8427132 ansible_freeipa_module: Add missing to_text import for _afm_convert
to_text has not been imported from ansible.module_utils._text but it was
used in _afm_convert. The import has been added.
2019-10-18 16:39:17 +02:00
Thomas Woerner
b16280455c ansible_freeipa_module: New functions module_params_get and _afm_convert
The module_params_get function can and should be used as a replacement of
ansible_module.params.get. For Python2 it is needed to convert parameters
to unicode. Otherwise there will be an error in the FreeIPA API command.

The private function _afm_convert has been added to do the conversion
recursively.
2019-10-09 12:05:00 +02:00
Thomas Woerner
3390d6742d ansible_freeipa_module: New function api_check_param
api_check_param can be used to verify if params are available for a command
in the used FreeIPA version. The function has been added as api is normally
not imported into modules.
2019-10-09 12:05:00 +02:00
Thomas Woerner
57188c890a ansible_freeipa_module: compare_args_ipa needs to compare lists orderless
The order of lists returned by find commands is not guaranteed. Therefore
lists are now converted to sets to compare them properly.
2019-10-09 12:05:00 +02:00
Thomas Woerner
bc0f211c29 ansible_freeipa_module: api_command should not have extra try clause
api_command is always used within try clause, therefore it is not needed
to have an extra try clause within api_command. Additionally it is needed
to get the dofferent errors in the next level.
2019-10-09 12:04:51 +02:00
Thomas Woerner
6e2fa7e7d6 Merge pull request #125 from tscherf/typo_fixes
fix various typos in README files
2019-10-07 16:09:54 +02:00
Thorsten Scherf
4d5a2c2437 fix various typos in README files 2019-10-07 12:56:51 +02:00
Varun Mylaraiah
74e954b97f Merge pull request #123 from t-woerner/ipagroup-rework
ipagroup: Rework to use same mechanisms as ipahostgroup module
2019-10-02 09:48:07 +05:30
Thomas Woerner
c5e0b1b453 ipagroup: Rework to use same mechanisms as ipahostgroup module
The ipagroup module was not using the failed and completed items in the dict
that is returned with api_command. But it was creating add and remove
lists for users, groups and services. This is not needed if the failures
"already a member" and "not a member" in the result failures are ignored.
Only other failures are reported.
2019-10-01 10:42:07 +02:00
Varun Mylaraiah
00066d2c28 Merge pull request #122 from t-woerner/external-ca-tests
tests/external-signed-ca tests: Fix external-ca.sh to use proper serials
2019-09-27 19:04:32 +05:30
Thomas Woerner
2a197cc7b1 tests/external-signed-ca tests: Fix external-ca.sh to use proper serials
The serial numbers have not been set for the creation of the CA and also
to sign the request. Because of this the local time has been used, which
resulted sometimes in the use of the same time stamp for the CA and the
signing reuqest. The import failed then with same issuer and serial number
error.

The cat to generate the chain.crt has been replaces with openssl x509 calls.

Some comments have also been added.

The script in external-signed-ca-with-manual-copy has been replaced with a
link to the external-signed-ca-with-automatic-copy directory.
2019-09-27 15:25:26 +02:00
Varun Mylaraiah
e8173dd9b5 Merge pull request #119 from t-woerner/hostgroup
New hostgroup management module
2019-09-26 15:29:36 +05:30
Thomas Woerner
0324ffd56d external-ca tests: Fix typo in inventory files
ipaservcer:vars has been changed to ipaserver:vars.
2019-09-25 13:21:08 +02:00
Thomas Woerner
e814b1faf5 ipagroup: Remove unused member_[present,absent] states
The states member_present and member_absent are not used and should also not
be used. This is a remain of the first try to ensure absence and presence
of users (members) in the group. This has been replaced with the setting
action: member.
2019-09-24 12:05:09 +02:00
Thomas Woerner
dd85868cc2 README-group: Fix typo in state description 2019-09-24 12:04:10 +02:00
Thomas Woerner
2abebc683b New hostgroup management module
There is a new hostgroup management module placed in the plugins folder:

  plugins/modules/ipahostgroup.py

The hostgroup module allows to add, remove and disable hosts.

The hostgroup module is as compatible as possible to the Ansible upstream
ipa_hostgroup module, but addtionally offers to ensure member presence and
absence.

Here is the documentation for the module:

  README-hostgroup.md

New example playbooks have been added:

  playbooks/hostgroup/ensure-hostgroup-is-absent.yml
  playbooks/hostgroup/ensure-hostgroup-is-present.yml
  playbooks/hostgroup/ensure-hosts-and-hostgroups-are-absent-in-hostgroup.yml
  playbooks/hostgroup/ensure-hosts-and-hostgroups-are-present-in-hostgroup.yml
2019-09-23 17:30:38 +02:00
Thomas Woerner
74ea40f66f New hostgroup management module
There is a new hostgroup management module placed in the plugins folder:

  plugins/modules/ipahostgroup.py

The hostgroup module allows to add, remove and disable hosts.

The hostgroup module is as compatible as possible to the Ansible upstream
ipa_hostgroup module, but addtionally offers to ensure member presence and
absence.

Here is the documentation for the module:

  README-hostgroup.md

New example playbooks have been added:

  playbooks/hostgroup/ensure-hostgroup-is-absent.yml
  playbooks/hostgroup/ensure-hostgroup-is-present.yml
  playbooks/hostgroup/ensure-hosts-and-hostgroups-are-absent-in-hostgroup.yml
  playbooks/hostgroup/ensure-hosts-and-hostgroups-are-present-in-hostgroup.yml
2019-09-23 17:08:38 +02:00
Thomas Woerner
8a56962ce6 Update README files for proper description of states
With Ansible there is no add or remove user, there is only ensure presence
or absence of users. The descriptions have been adapted to make sure that
the description is correct now.
2019-09-10 10:13:43 +02:00
Thomas Woerner
4fc722f73b New host management module
There is a new user management module placed in the plugins folder:

  plugins/modules/ipauser.py

The host module allows to add, remove and disable hosts.

The host module is as compatible as possible to the Ansible upstream
ipa_host` module, but addtionally offers to disable hosts.

Here is the documentation for the module:

  README-host.md

New example playbooks have been added:

  playbooks/host/add-host.yml
  playbooks/host/delete-host.yml
  playbooks/host/disable-host.yml
2019-09-09 23:35:05 +02:00
Thomas Woerner
5bb44245c6 ansible_ipa_client: Drop import of configure_nsswitch_database
configure_nsswitch_database has been removed with the freeipa commit

41ef8fba31

The 4.4 compatibility hack leads to a ALREADY installed error in
ipaclient_test because of the removal. This affects ipaclient and
ipareplica roles and also the ipaclient deployment part in ipaserver.

configure_nsswitch_database is not used any more in ipaclient role modules
and therefore simply can be removed from ansible_ipa_client.
2019-09-04 14:47:01 +02:00
Thomas Woerner
f4680ceb5a utils/ansible-ipa-[server,replica,client]-install: New --ansible-verbose option
This option defines the verbose level for the internal ansible-playbook
run.
2019-08-15 21:29:03 +02:00
Thomas Woerner
3a3fb51109 utils/ansible-ipa-server-install: Add deprecated (unused) --domain-level option
This is option is used in test scripts.
2019-08-15 17:32:42 +02:00
Thomas Woerner
09ab29b4e7 ansible_freeipa_module: Add support for GSSAPI
The GSSAPI can be enabled in the management modules with either the
KRB5CCNAME or the KRB5_CLIENT_KTNAME environment variable.

For KRB5CCNAME it is needed to create a ccache file

  kinit admin@TEST.LOCAL -c /root/admin.ccache

that is transferred to the nodes (here into /root) and activated in the
playbook with

  environment:
    KRB5CCNAME: /root/admin.ccache

For KRB5_CLIENT_KTNAME a admin keytab has to be generated

  ipa-getkeytab -s ipaserver.test.local -p admin@TEST.LOCAL -k \
  /root/admin.keytab

that is transferred to the nodes (here into /root) and activated in the
playbook with

  environment:
    KRB5_CLIENT_KTNAME: /root/admin.keytab

It will be needed to set ipaadmin_principal if the admin principal is not
admin.

The management modules can be used without a password in this case.
2019-08-12 19:18:06 +02:00
Thomas Woerner
c69d0bc53f ansible_freeipa_module: Add ansible module argument to valid_creds function
For debug and error reporting it is needed to have the ansible module also
in the valid_creds function.
2019-08-12 19:18:05 +02:00
Thomas Woerner
455ca83ef5 ipauser, ipagroup: Fix typo in only one error message 2019-08-12 19:18:04 +02:00
Thomas Woerner
1d5b5d38b7 utils/ansible-ipa-[server,replica,client]-install: New --become-method option
This option is the same as the --become-method option with ansible-playbook.
If this option is set, become_method will be set in the generated playbook.
2019-08-06 12:42:21 +02:00
Thomas Woerner
d43b4429e6 utils/ansible-ipa-[server,replica,client]-install: Print excessive args
Excessive args are printed now. The simple print of the message too many
arguments was not helping.
2019-08-06 12:39:03 +02:00
Thomas Woerner
45af7348fe utils/ansible-ipa-[server,replica,client]-install: Add p.wait() for returncode
The p.wait() call has been missing in the normal case, therefore no proper
returncode has been returned.
2019-08-06 11:32:55 +02:00
Thomas Woerner
b636ab3112 utils/ansible-ipa-[server,replica,client]-install: New --playbook-dir option
If the --playbook-dir option is used, the inventory and playbook files will
be generated in this directory. The files will not be removed after the
playbook processing ended.

If the directory does not exist an error message will be printed and the
utility will not continue.
2019-08-06 09:17:59 +02:00
Thomas Woerner
ff08ee7ee6 ipaserver_test,ipareplica_prepare: Do not return _pkcs12_file settings
These settings are file descriptors if external certificates are used and
are not used later in the roles. Therefore these settings have been removed.

Fixes: #110 (Ansible error with external certificates)
2019-07-30 11:48:31 +02:00
Thomas Woerner
ab25078b47 ansible-ipa-*-install: Get continuous output working for python2 also
The used code for continuous output from the ansible-playbook call was
only working for Python2. The output has only been printed when the command
finised. This code has been replaced with code that is working with Python2
and Python3.
2019-07-29 13:03:24 +02:00
Thomas Woerner
781ac6e90b ansible-ipa-client-install: The proper option is ipaclient-install-packages
The wrong name has been used for the option of _install_packages.
2019-07-29 13:02:30 +02:00
Thomas Woerner
5179514e0c ansible-ipa-*-install: Use /usr/bin/python by default, fix _install_packages
/usr/bin/python should be used by default. Fixed typo in _install_packages
setting in the inventory file.
2019-07-29 12:33:25 +02:00
Thomas Woerner
203735e143 Utils scripts: ansible-ipa-[server,replica,client]-install
These are utils scripts to do a server,replica or client deployment and
undeployment using the ansible roles. A client inventory and playbook is
generated by the script which is then used with ansible-playbook.

The command line options or the normal command line installers
ipa-server-install, ipa-replica-install and ipa-client-install are all
supported also by these scripts.

Additonally to the commadn line of the normal installers it is needed to
add the fqdn of the host to be installed.

It is needed that the ansible-freeipa roles are available and also usable
by ansible.
2019-07-29 11:57:51 +02:00
Varun Mylaraiah
01b2f8efcf Merge pull request #108 from t-woerner/topologysegment_reinitialize
ipatopologysegment: Fail if given entry can not be found for reinitia…
2019-07-26 23:08:52 +05:30
Thomas Woerner
c212b43516 ipatopologysegment: Fail for missing entry with reinitialized
Currently it is ignored if the entry for reinitialized can not be found if
the name or left and right are not correct. Now there is a failure in this
case.

Fixes: #107 (Reinitialize are failed to find the node in ipatopology ..)
Signed-off-by: Thomas Woerner <twoerner@redhat.com>
2019-07-26 19:30:11 +02:00
Varun Mylaraiah
f786658606 Merge pull request #109 from t-woerner/topologysegment_add
ipatopologysegment: Store suffix for commands in command list
2019-07-26 22:50:09 +05:30
Thomas Woerner
e4497c18e9 ipatopologysegment: Store suffix for commands in command list
With adding the domain and ca suffixes with `suffix: domain+ca` only ca
has been added as the suffix was only used from the last command. The
suffix is now stored together with the command and the argument. This
will fix this error.

Fixes: #106 (Last suffix adding twice in the list of topology segments)
2019-07-26 18:33:41 +02:00
Thomas Woerner
ad7e17ea94 roles/ipareplica/README: _http_cert_files and _pkinit_cert_files are lists
In the README these settings have been single values instead of string
lists:
  ipareplica_http_cert_file
  ipareplica_pkinit_cert_file
instead of
  ipareplica_http_cert_files
  ipareplica_pkinit_cert_files
2019-07-26 13:59:10 +02:00
Thomas Woerner
515f57eb09 utils/galaxyify-playbook.py: Support to galaxify rule lines in playbooks 2019-07-24 19:21:51 +02:00
Thomas Woerner
62097ee368 utils/[galaxyify-playbook,gen_module_docs].py: flake8 fixes 2019-07-24 19:21:48 +02:00
Thomas Woerner
4cd4f2cf71 Update README.md: Add information about roles in usage 2019-07-24 16:19:11 +02:00
Thomas Woerner
4fc9ebe5d8 Merge pull request #101 from Uumas/debian
Add debian support for ipaclient
2019-07-24 11:06:50 +02:00
Uumas
d1af0ff44b Added support for predefining client OTP using ipaclient_otp 2019-07-23 21:18:41 +03:00
Uumas
bf7902b7cc Add debian support for ipaclient 2019-07-23 19:51:41 +03:00
Thomas Woerner
0240ec34a5 utils/build-galaxy-release.sh: Fix module_utils import in management modules
The prefix has been fixed in the wrong files.
2019-07-23 17:01:05 +02:00
Thomas Woerner
5790f4a703 utils/gen_module_docs.py: Drop parameter name dirserv_cert_files
This parameter name is not used and therefore not needed anymore.
2019-07-23 16:58:17 +02:00
176 changed files with 22954 additions and 401 deletions

View File

@@ -4,9 +4,9 @@ Group module
Description
-----------
The group module allows to add, remove, enable, disable, unlock und undelete groups.
The group module allows to ensure presence and absence of groups and members of 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.
The group module is as compatible as possible to the Ansible upstream `ipa_group` module, but additionally offers to add users to a group and also to remove users from a group.
Features
@@ -142,9 +142,9 @@ Variable | Description | Required
`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
`service` | List of service name strings assigned to this group. Only usable with IPA versions 4.7 and up. | 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
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
Authors

158
README-hbacrule.md Normal file
View File

@@ -0,0 +1,158 @@
HBACrule module
===============
Description
-----------
The hbacrule (HBAC Rule) module allows to ensure presence and absence of HBAC Rules and host, hostgroups, HBAC Services, HBAC Service Groups, users, and user groups as members of HBAC Rule.
Features
--------
* HBAC Rule management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahbacrule 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 make sure HBAC Rule login exists:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Rule login is present
- ipahbacrule:
ipaadmin_password: MyPassword123
name: login
```
Example playbook to make sure HBAC Rule login exists with the only HBAC Service sshd:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Rule login is present with the only HBAC Service sshd
- ipahbacrule:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
```
Example playbook to make sure HBAC Service sshd is present in HBAC Rule login:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service sshd is present in HBAC Rule login
- ipahbacrule:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
action: member
```
Example playbook to make sure HBAC Service sshd is absent in HBAC Rule login:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service sshd is present in HBAC Rule login
- ipahbacrule:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
action: member
state: absent
```
Example playbook to make sure HBAC Rule login is absent:
```yaml
---
- name: Playbook to handle hbacrules
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Rule login is present
- ipahbacrule:
ipaadmin_password: MyPassword123
name: login
state: absent
```
Variables
=========
ipahbacrule
---------------
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 hbacrule name strings. | yes
`description` | The hbacrule description string. | no
`usercategory` \| `usercat` | User category the rule applies to. Choices: ["all"] | no
`hostcategory` \| `hostcat` | Host category the rule applies to. Choices: ["all"] | no
`servicecategory` \| `servicecat` | HBAC service category the rule applies to. Choices: ["all"] | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`host` | List of host name strings assigned to this hbacrule. | no
`hostgroup` | List of host group name strings assigned to this hbacrule. | no
`hbacsvc` | List of HBAC Service name strings assigned to this hbacrule. | no
`hbacsvcgroup` | List of HBAC Service Group name strings assigned to this hbacrule. | no
`user` | List of user name strings assigned to this hbacrule. | no
`group` | List of user group name strings assigned to this hbacrule. | no
`action` | Work on hbacrule or member level. It can be on of `member` or `hbacrule` and defaults to `hbacrule`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled` or `disabled`, default: `present`. | no
Authors
=======
Thomas Woerner

109
README-hbacsvc.md Normal file
View File

@@ -0,0 +1,109 @@
HBACsvc module
==============
Description
-----------
The hbacsvc (HBAC Service) module allows to ensure presence and absence of HBAC Services.
Features
--------
* HBACsvc management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahbacsvc 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 make sure HBAC Service for http is present
```yaml
---
- name: Playbook to handle HBAC Services
hosts: ipaserver
become: true
tasks:
# Ensure HBAC Service for http is present
- ipahbacsvc:
ipaadmin_password: MyPassword123
name: http
description: Web service
```
Example playbook to make sure HBAC Service for tftp is present
```yaml
---
- name: Playbook to handle HBAC Services
hosts: ipaserver
become: true
tasks:
# Ensure HBAC Service for tftp is present
- ipahbacsvc:
ipaadmin_password: MyPassword123
name: tftp
description: TFTPWeb service
```
Example playbook to make sure HBAC Services for http and tftp are absent
```yaml
---
- name: Playbook to handle HBAC Services
hosts: ipaserver
become: true
tasks:
# Ensure HBAC Service for http and tftp are absent
- ipahbacsvc:
ipaadmin_password: MyPassword123
name: http,tftp
state: absent
```
Variables
=========
ipahbacsvc
----------
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` \| `service` | The list of hbacsvc name strings. | no
`description` | The hbacsvc description string. | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors
=======
Thomas Woerner

150
README-hbacsvcgroup.md Normal file
View File

@@ -0,0 +1,150 @@
HBACsvcgroup module
===================
Description
-----------
The hbacsvcgroup (HBAC Service Group) module allows to ensure presence and absence of HBAP Service Groups and members of the groups.
Features
--------
* HBAC Service Group management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahbacsvcgroup 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 make sure HBAC Service Group login exists:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service Group login is present
- ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
```
Example playbook to make sure HBAC Service Group login exists with the only HBAC Service sshd:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service Group login is present with the only HBAC Service sshd
- ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
```
Example playbook to make sure HBAC Service sshd is present in HBAC Service Group login:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service sshd is present in HBAC Service Group login
- ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
action: member
```
Example playbook to make sure HBAC Service sshd is absent in HBAC Service Group login:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service sshd is present in HBAC Service Group login
- ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
action: member
state: absent
```
Example playbook to make sure HBAC Service Group login is absent:
```yaml
---
- name: Playbook to handle hbacsvcgroups
hbacsvcs: ipaserver
become: true
tasks:
# Ensure HBAC Service Group login is present
- ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
state: absent
```
Variables
=========
ipahbacsvcgroup
---------------
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 hbacsvcgroup name strings. | no
`description` | The hbacsvcgroup description string. | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`hbacsvc` | List of hbacsvc name strings assigned to this hbacsvcgroup. | no
`action` | Work on hbacsvcgroup or member level. It can be on of `member` or `hbacsvcgroup` and defaults to `hbacsvcgroup`. | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors
=======
Thomas Woerner

311
README-host.md Normal file
View File

@@ -0,0 +1,311 @@
Host module
===========
Description
-----------
The host module allows to ensure presence, absence and disablement of hosts.
The host module is as compatible as possible to the Ansible upstream `ipa_host` module, but additionally offers to disable hosts.
Features
--------
* Host management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahost 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 ensure host presence:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is present
- ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
description: Example host
ip_address: 192.168.0.123
locality: Lab
ns_host_location: Lab
ns_os_version: CentOS 7
ns_hardware_platform: Lenovo T61
mac_address:
- "08:00:27:E3:B1:2D"
- "52:54:00:BD:97:1E"
state: present
```
Example playbook to ensure host presence without DNS:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is present without DNS
- ipahost:
ipaadmin_password: MyPassword123
name: host02.example.com
description: Example host
force: yes
```
Example playbook to ensure host presence with a random password:
```yaml
---
- name: Ensure host with random password
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with random password
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
random: yes
force: yes
register: ipahost
- name: Print generated random password
debug:
var: ipahost.host.randompassword
```
Please remember that the `force` tag will also force the generation of a new random password even if the host already exists and if `update_password` is limited to `on_create`.
Example playbook to ensure presence of several hosts with a random password:
```yaml
---
- name: Ensure hosts with random password
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.example.com present with random passwords
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.example.com
random: yes
force: yes
- name: host02.example.com
random: yes
force: yes
register: ipahost
- name: Print generated random password for host01.example.com
debug:
var: ipahost.host["host01.example.com"].randompassword
- name: Print generated random password for host02.example.com
debug:
var: ipahost.host["host02.example.com"].randompassword
```
Please remember that the `force` tag will also force the generation of a new random password even if the host alreay exists and if `update_password` is limited to `on_create`.
Example playbook to ensure presence of host member principal:
```yaml
---
- name: Host present with principal
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with principals host/testhost01.example.com and host/myhost01.example.com
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
principal:
- host/testhost01.example.com
- host/myhost01.example.com
action: member
```
Example playbook to ensure presence of host member certificate:
```yaml
- name: Host present with certificate
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with certificate
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
certificate:
- MIIC/zCCAeegAwIBAg...
action: member
```
Example playbook to ensure presence of member managedby_host for serveral hosts:
```yaml
---
- name: Host present with managedby_host
hosts: ipaserver
become: true
tasks:
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.exmaple.com
managedby_host: server.exmaple.com
- name: host02.exmaple.com
managedby_host: server.exmaple.com
action: member
```
Example playbook to disable a host:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is disabled
- ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
update_dns: yes
state: disabled
```
`update_dns` controls if the DNS entries will be updated.
Example playbook to ensure a host is absent:
```yaml
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
# Ensure host is absent
- ipahost:
ipaadmin_password: password1
name: host01.example.com
state: absent
```
Variables
=========
ipahost
-------
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` \| `fqdn` | The list of host name strings. `name` with *host variables* or `hosts` containing *host variables* need to be used. | no
**Host variables** | Only used with `name` variable in the first level. | no
`hosts` | The list of host dicts. Each `hosts` dict entry can contain **host variables**.<br>There is one required option in the `hosts` dict:| no
&nbsp; | `name` \| `fqdn` - The user name string of the entry. | yes
&nbsp; | **Host variables** | no
`update_password` | Set password for a host in present state only on creation or always. It can be one of `always` or `on_create` and defaults to `always`. | no
`action` | Work on host or member level. It can be on of `member` or `host` and defaults to `host`. | no
`state` | The state to ensure. It can be one of `present`, `absent` or `disabled`, default: `present`. | yes
**Host Variables:**
Variable | Description | Required
-------- | ----------- | --------
`description` | The host description. | no
`locality` | Host locality (e.g. "Baltimore, MD"). | no
`location` \| `ns_host_location` | Host location (e.g. "Lab 2"). | no
`platform` \| `ns_hardware_platform` | Host hardware platform (e.g. "Lenovo T61"). | no
`os` \| `ns_os_version` | Host operating system and version (e.g. "Fedora 9"). | no
`password` \| `user_password` \| `userpassword` | Password used in bulk enrollment. | no
`random` \| `random_password` | Initiate the generation of a random password to be used in bulk enrollment. | no
`certificate` \| `usercertificate` | List of base-64 encoded host certificates | no
`managedby` \| `principalname` \| `krbprincipalname` | List of hosts that can manage this host | no
`principal` \| `principalname` \| `krbprincipalname` | List of principal aliases for this host | no
`allow_create_keytab_user` \| `ipaallowedtoperform_write_keys_user` | Users allowed to create a keytab of this host. <br>Options: | no
`allow_create_keytab_group` \| `ipaallowedtoperform_write_keys_group` | Groups allowed to create a keytab of this host. <br>Options: | no
`allow_create_keytab_host` \| `ipaallowedtoperform_write_keys_host` | Hosts allowed to create a keytab of this host. <br>Options: | no
`allow_create_keytab_hostgroup` \| `ipaallowedtoperform_write_keys_hostgroup` | Host groups allowed to create a keytab of this host. <br>Options: | no
`allow_retrieve_keytab_user` \| `ipaallowedtoperform_read_keys_user` | Users allowed to retieve a keytab of this host. <br>Options: | no
`allow_retrieve_keytab_group` \| `ipaallowedtoperform_read_keys_group` | Groups allowed to retieve a keytab of this host. <br>Options: | no
`allow_retrieve_keytab_host` \| `ipaallowedtoperform_read_keys_host` | Hosts allowed to retieve a keytab of this host. <br>Options: | no
`allow_retrieve_keytab_hostgroup` \| `ipaallowedtoperform_read_keys_hostgroup` | Host groups allowed to retieve a keytab of this host. <br>Options: | no
`mac_address` \| `macaddress` | List of hardware MAC addresses. | no
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys | no
`userclass` \| `class` | Host category (semantics placed on this attribute are for local interpretation) | no
`auth_ind` \| `krbprincipalauthind` | Defines a whitelist for Authentication Indicators. Use 'otp' to allow OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA authentications. Other values may be used for custom configurations. choices: ["radius", "otp", "pkinit", "hardened"] | no
`requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service (bool) | no
`ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service (bool) | no
`ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client (bool) | no
`force` | Force host name even if not in DNS. | no
`reverse` | Reverse DNS detection. | no
`ip_address` \| `ipaddress` | The host IP address. | no
`update_dns` | Update DNS entries. | no
Return Values
=============
ipahost
-------
There are only return values if one or more random passwords have been generated.
Variable | Description | Returned When
-------- | ----------- | -------------
`host` | Host dict with random password. (dict) <br>Options: | If random is yes and host did not exist or update_password is yes
&nbsp; | `randompassword` - The generated random password | If only one host is handled by the module
&nbsp; | `name` - The host name of the host that got a new random password. (dict) <br> Options: <br> &nbsp; `randompassword` - The generated random password | If several hosts are handled by the module
Authors
=======
Thomas Woerner

147
README-hostgroup.md Normal file
View File

@@ -0,0 +1,147 @@
Hostgroup module
================
Description
-----------
The hostgroup module allows to ensure presence and absence of hostgroups and members of hostgroups.
The hostgroup module is as compatible as possible to the Ansible upstream `ipa_hostgroup` module, but additionally offers to make sure that hosts are present or absent in a hostgroup.
Features
--------
* Hostgroup management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipahostgroup 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 make sure hostgroup databases exists:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure host-group databases is present
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
```
Example playbook to make sure that hosts and hostgroups are present in existing databases hostgroup:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure hosts and hostgroups are present in existing databases hostgroup
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
```
`action` controls if a the hostgroup or member will be handled. To add or remove members, set `action` to `member`.
Example playbook to make sure hosts and hostgroups are absent in databases hostgroup:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure hosts and hostgroups are absent in databases hostgroup
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
state: absent
```
Example playbook to make sure host-group databases is absent:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure host-group databases is absent
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
state: absent
```
Variables
=========
ipahostgroup
-------
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 hostgroup name strings. | no
`description` | The hostgroup description string. | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`host` | List of host name strings assigned to this hostgroup. | no
`hostgroup` | List of hostgroup name strings assigned to this hostgroup. | no
`action` | Work on hostgroup or member level. It can be on of `member` or `hostgroup` and defaults to `hostgroup`. | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors
=======
Thomas Woerner

102
README-pwpolicy.md Normal file
View File

@@ -0,0 +1,102 @@
Pwpolicy module
===============
Description
-----------
The pwpolicy module allows to ensure presence and absence of pwpolicies.
Features
--------
* Pwpolicy management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipapwpolicy 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 ensure presence of pwpolicies for exisiting group ops:
```yaml
tasks:
- name: Ensure presence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: MyPassword123
name: ops
minlife: 7
maxlife: 49
history: 5
priority: 1
lockouttime: 300
minlength: 8
maxfail: 3
```
Example playbook to ensure absence of pwpolicies for group ops
```yaml
---
- name: Playbook to handle pwpolicies
hosts: ipaserver
become: true
tasks:
# Ensure absence of pwpolicies for group ops
- ipapwpolicy:
ipaadmin_password: MyPassword123
name: ops
state: absent
```
Variables
=========
ipapwpolicy
-------
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 pwpolicy name strings. | no
`maxlife` \| `krbmaxpwdlife` | Maximum password lifetime in days. (int) | no
`minlife` \| `krbminpwdlife` | Minimum password lifetime in hours. (int) | no
`history` \| `krbpwdhistorylength` | Password history size. (int) | no
`minclasses` \| `krbpwdmindiffchars` | Minimum number of character classes. (int) | no
`minlength` \| `krbpwdminlength` | Minimum length of password. (int) | no
`priority` \| `cospriority` | Priority of the policy, higher number means lower priority. (int) | no
`maxfail` \| `krbpwdmaxfailure` | Consecutive failures before lockout. (int) | no
`failinterval` \| `krbpwdfailurecountinterval` | Period after which failure count will be reset in seconds. (int) | no
`lockouttime` \| `krbpwdlockoutduration` | Period for which lockout is enforced in seconds. (int) | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
Authors
=======
Thomas Woerner

95
README-sudocmd.md Normal file
View File

@@ -0,0 +1,95 @@
Sudocmd module
================
Description
-----------
The sudocmd module allows to ensure presence and absence of sudo command.
The sudocmd module is as compatible as possible to the Ansible upstream `ipa_sudocmd` module.
Features
--------
* Sudo command management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipa_sudocmd 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 make sure sudocmd exists:
```yaml
---
- name: Playbook to handle sudocmd
hosts: ipaserver
become: true
tasks:
# Ensure sudocmd is present
- ipasudocmd:
ipaadmin_password: MyPassword123
name: /usr/bin/su
state: present
```
Example playbook to make sure sudocmd is absent:
```yaml
---
- name: Playbook to handle sudocmd
hosts: ipaserver
become: true
tasks:
# Ensure sudocmd are absent
- ipahostgroup:
ipaadmin_password: MyPassword123
name: /usr/bin/su
state: absent
```
Variables
=========
ipasudocmd
-------
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` \| `sudocmd` | The sudo command strings. | yes
`description` | The command description string. | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors
=======
Rafael Guterres Jeffman

137
README-sudocmdgroup.md Normal file
View File

@@ -0,0 +1,137 @@
Sudocmdgroup module
===================
Description
-----------
The sudocmdgroup module allows to ensure presence and absence of sudocmdgroups and members of sudocmdgroups.
The sudocmdgroup module is as compatible as possible to the Ansible upstream `ipa_sudocmdgroup` module, but additionally offers to make sure that sudocmds are present or absent in a sudocmdgroup.
Features
--------
* Sudocmdgroup management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipasudocmdgroup 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 make sure sudocmdgroup is present:
```yaml
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudocmdgroup is present
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: group01
description: Group of important commands
```
Example playbook to make sure that a sudo command and sudocmdgroups are present in existing sudocmdgroup:
```yaml
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudo commands are present in existing sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: group01
sudocmd:
- /usr/bin/su
- /usr/bin/less
action: member
```
`action` controls if the sudocmdgroup or member will be handled. To add or remove members, set `action` to `member`.
Example playbook to make sure that a sudo command and sudocmdgroups are absent in sudocmdgroup:
```yaml
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudocmds are absent in existing sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: group01
sudocmd:
- /usr/bin/su
- /usr/bin/less
action: member
state: absent
```
Example playbook to make sure sudocmdgroup is absent:
```yaml
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudocmdgroup is absent
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: group01
state: absent
```
Variables
=========
ipasudocmdgroup
-------
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 sudocmdgroup name strings. | no
`description` | The sudocmdgroup description string. | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`sudocmd` | List of sudocmdgroup name strings assigned to this sudocmdgroup. | no
`action` | Work on sudocmdgroup or member level. It can be on of `member` or `sudocmdgroup` and defaults to `sudocmdgroup`. | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors
=======
Rafael Guterres Jeffman

141
README-sudorule.md Normal file
View File

@@ -0,0 +1,141 @@
Sudorule module
===============
Description
-----------
The sudorule (Sudo Rule) module allows to ensure presence and absence of Sudo Rules and host, hostgroups, users, and user groups as members of Sudo Rule.
Features
--------
* Sudo Rule management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipasudorule 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 make sure Sudo Rule is present:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
tasks:
# Ensure Sudo Rule is present
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
```
Example playbook to make sure sudocmds are present in Sudo Rule:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
tasks:
# Ensure Sudo Rule is present
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
cmd:
- /sbin/ifconfig
action: member
```
Example playbook to make sure sudocmds are not present in Sudo Rule:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
tasks:
# Ensure Sudo Rule is present
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
cmd:
- /sbin/ifconfig
action: member
state: absent
```
Example playbook to make sure Sudo Rule is absent:
```yaml
---
- name: Playbook to handle sudorules
hosts: ipaserver
become: true
tasks:
# Ensure Sudo Rule is present
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
```
Variables
=========
ipasudorule
---------------
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 sudorule name strings. | yes
`description` | The sudorule description string. | no
`usercategory` | User category the rule applies to. Choices: ["all"] | no
`hostcategory` | Host category the rule applies to. Choices: ["all"] | no
`cmdcategory` | Command category the rule applies to. Choices: ["all"] | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
`host` | List of host name strings assigned to this sudorule. | no
`hostgroup` | List of host group name strings assigned to this sudorule. | no
`user` | List of user name strings assigned to this sudorule. | no
`group` | List of user group name strings assigned to this sudorule. | no
`cmd` | List of sudocmd name strings assigned to this sudorule. | no
`cmdgroup` | List of sudocmd group name strings assigned wto this sudorule. | no
`action` | Work on sudorule or member level. It can be on of `member` or `sudorule` and defaults to `sudorule`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled` or `disabled`, default: `present`. | no
Authors
=======
Rafael Jeffman

View File

@@ -4,7 +4,7 @@ Topology modules
Description
-----------
These modules allow to manage the topology. That means that topology segments can be added, removed and reinitialized. Also it is possible to verify topology suffixes.
These modules allow to manage the topology. That means that it can made sure that topology segments are present, absent or reinitialized. Also it is possible to verify topology suffixes.
Features
@@ -39,7 +39,7 @@ ipaserver.test.local
```
Example playbook to add a topology segment wiht default name (cn):
Example playbook to add a topology segment with default name (cn):
```yaml
---
@@ -56,7 +56,7 @@ Example playbook to add a topology segment wiht default name (cn):
right: ipareplica2.test.local
state: present
```
The name (cn) can also be set if it should not be the default `{left}-to-{rkight}`.
The name (cn) can also be set if it should not be the default `{left}-to-{right}`.
Example playbook to delete a topology segment:

View File

@@ -4,9 +4,9 @@ User module
Description
-----------
The user module allows to add, remove, enable, disable, unlock und undelete users.
The user module allows to ensure presence, absence, disablement, unlocking and undeletion of 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.
The user module is as compatible as possible to the Ansible upstream `ipa_user` module, but additionally offers to preserve delete, enable, disable, unlock and undelete users.
Features
@@ -41,7 +41,7 @@ ipaserver.test.local
```
Example playbook to add users:
Example playbook to ensure a user is present:
```yaml
---
@@ -50,7 +50,7 @@ Example playbook to add users:
become: true
tasks:
# Create user pinky
# Ensure user pinky is present
- ipauser:
ipaadmin_password: MyPassword123
name: pinky
@@ -64,7 +64,7 @@ Example playbook to add users:
password: "no-brain"
update_password: on_create
# Create user brain
# Ensure user brain is present
- ipauser:
ipaadmin_password: MyPassword123
name: brain
@@ -74,6 +74,133 @@ Example playbook to add users:
`update_password` controls if a password for a user will be set in present state only on creation or every time (always).
These two `ipauser` module calls can be combined into one with the `users` variable:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure users pinky and brain are present
- ipauser:
ipaadmin_password: MyPassword123
users:
- 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"
- name: brain
first: brain
last: Acme
update_password: on_create
```
You can also alternatively use a json file containing the users, here `users_present.json`:
```json
{
"users": [
{
"name": "user1",
"first": "First 1",
"last": "Last 1"
},
{
"name": "user2",
"first": "First 2",
"last": "Last 2"
},
...
]
}
```
And ensure the presence of the users with this example playbook:
```yaml
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Include users_present.json
include_vars:
file: users_present.json
- name: Users present
ipauser:
ipaadmin_password: SomeADMINpassword
users: "{{ users }}"
```
Ensure user pinky is present with a generated random password and print the random password:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure user pinky is present with a random password
- ipauser:
ipaadmin_password: MyPassword123
name: brain
first: brain
last: Acme
random: yes
register: ipauser
- name: Print generated random password
debug:
var: ipauser.user.randompassword
```
Ensure users pinky and brain are present with a generated random password and print the random passwords:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure users pinky and brain are present with random password
- ipauser:
ipaadmin_password: MyPassword123
users:
- 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"
- name: brain
first: brain
last: Acme
register: ipauser
- name: Print generated random password of pinky
debug:
var: ipauser.user.pinky.randompassword
- name: Print generated random password of brain
debug:
var: ipauser.user.brain.randompassword
```
Example playbook to delete a user, but preserve it:
```yaml
@@ -91,6 +218,28 @@ Example playbook to delete a user, but preserve it:
state: absent
```
This can also be done with the `users` variable containing only names, this can be combined into one module call:
Example playbook to delete a user, but preserve it using the `users` variable:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Remove but preserve user pinky
- ipauser:
ipaadmin_password: MyPassword123
users:
- name: pinky
preserve: yes
state: absent
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to undelete a preserved user.
@@ -108,6 +257,8 @@ Example playbook to undelete a preserved user.
state: undeleted
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to disable a user:
@@ -125,6 +276,8 @@ Example playbook to disable a user:
state: disabled
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to enable users:
@@ -142,6 +295,8 @@ Example playbook to enable users:
state: enabled
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to unlock users:
@@ -160,7 +315,7 @@ Example playbook to unlock users:
```
Example playbook to delete users:
Example playbook to ensure users are absent:
```yaml
---
@@ -169,13 +324,34 @@ Example playbook to delete users:
become: true
tasks:
# Remove user pinky and brain
# Ensure users pinky and brain are absent
- ipauser:
ipaadmin_password: MyPassword123
name: pinky,brain
state: absent
```
This can also be done as an alternative with the `users` variable containing only names.
Example playbook to ensure users are absent:
```yaml
---
- name: Playbook to handle users
hosts: ipaserver
become: true
tasks:
# Ensure users pinky and brain are absent
- ipauser:
ipaadmin_password: MyPassword123
users:
- name: pinky
- name: brain
state: absent
```
Variables
=========
@@ -183,29 +359,86 @@ Variables
ipauser
-------
**General Variables:**
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
`name` | The list of user name strings. `name` with *user variables* or `users` containing *user variables* need to be used. | no
**User variables** | Only used with `name` variable in the first level. | no
`users` | The list of user dicts. Each `users` dict entry can contain **user variables**.<br>There is one required option in the `users` dict:| no
&nbsp; | `name` - The user name string of the entry. | yes
&nbsp; | **User variables** | no
`preserve` | Delete a user, keeping the entry available for future use. (bool) | 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
`action` | Work on user or member level. It can be on of `member` or `user` and defaults to `user`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled`, `disabled`, `unlocked` or `undeleted`, default: `present`. Only `names` or `users` with only `name` set are allowed if state is not `present`. | yes
**User Variables:**
Variable | Description | Required
-------- | ----------- | --------
`first` \| `givenname` | The first name string. | no
`last` | The last name | no
`last` \| `sn` | The last name string. | 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
`principal` \| `principalnam` \| `krbprincipalname` | The kerberos principal sptring. | no
`principalexpiration` \| `krbprincipalexpiration` | The kerberos principal 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
`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. Only usable with IPA versions 4.7 and up. | no
`password` | The user password string. | no
`random` | Generate a random user password | no
`uid` \| `uidnumber` | The UID integer. | no
`gid` \| `gidnumber` | The GID integer. | no
`city` | City | no
`userstate` \| `st` | State/Province | no
`postalcode` \| `zip` | Postalcode/ZIP | no
`phone` \| `telephonenumber` | List of telephone number strings, | no
`mobile` | List of mobile telephone number strings. | no
`pager` | List of pager number strings. | no
`fax` \| `facsimiletelephonenumber` | List of fax number strings. | no
`orgunit` | The Organisation unit. | 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
`manager` | List of manager user names. | no
`carlicense` | List of car licenses. | no
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys. | no
`userauthtype` | List of supported user authentication types. Choices: `password`, `radius` and `otp` | no
`userclass` | User category. (semantics placed on this attribute are for local interpretation). | no
`radius` | RADIUS proxy configuration | no
`radiususer` | RADIUS proxy username | no
`departmentnumber` | Department Number | no
`employeenumber` | Employee Number | no
`employeetype` | Employee Type | no
`preferredlanguage` | Preferred Language | no
`certificate` | List of base-64 encoded user certificates. | no
`certmapdata` | List of certificate mappings. Either `certificate` or `issuer` together with `subject` need to be specified. <br>Options: | no
&nbsp; | `certificate` - Base-64 encoded user certificate | no
&nbsp; | `issuer` - Issuer of the certificate | no
&nbsp; | `subject` - Subject of the certificate | no
`noprivate` | Do not create user private group. (bool) | no
`nomembers` | Suppress processing of membership attributes. (bool) | no
Return Values
=============
ipauser
-------
There are only return values if one or more random passwords have been generated.
Variable | Description | Returned When
-------- | ----------- | -------------
`host` | Host dict with random password. (dict) <br>Options: | If random is yes and user did not exist or update_password is yes
&nbsp; | `randompassword` - The generated random password | If only one user is handled by the module
&nbsp; | `name` - The user name of the user that got a new random password. (dict) <br> Options: <br> &nbsp; `randompassword` - The generated random password | If several users are handled by the module
Authors

View File

@@ -1,7 +1,7 @@
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`. Also modules for group, topology and user management.
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, host, 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.
@@ -12,6 +12,15 @@ Features
* One-time-password (OTP) support for client installation
* Repair mode for clients
* Modules for group management
* Modules for hbacrule management
* Modules for hbacsvc management
* Modules for hbacsvcgroup management
* Modules for host management
* Modules for hostgroup management
* Modules for pwpolicy management
* Modules for sudocmd management
* Modules for sudocmdgroup management
* Modules for sudorule management
* Modules for topology management
* Modules for user management
@@ -28,6 +37,7 @@ Supported Distributions
* RHEL/CentOS 7.4+
* Fedora 26+
* Ubuntu
* Debian 10+ (ipaclient only, no server or replica!)
Requirements
------------
@@ -59,17 +69,18 @@ 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:
The simplest method for now is to clone this repository on the controller 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 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 `ansible.cfg` or create links for the roles, modules or directories.
You can either adapt ansible.cfg:
```
roles_path = /my/dir/ansible-freeipa/roles
library = /my/dir/ansible-freeipa/plugins/modules
module_utils = /my/dir/ansible-freeipa/plugins/module_utils
```
@@ -77,18 +88,27 @@ module_utils = /my/dir/ansible-freeipa/plugins/module_utils
Or you can link the directories:
```
ansible-freeipa/roles to ~/.ansible/
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.
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 `plugins/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
ansible-galaxy collection install freeipa.ansible_freeipa
```
Installing collections using the ansible-galaxy command is only supported with ansible 2.9+.
The mazer tool can be used for to install the collection for ansible 2.8:
```bash
mazer install freeipa.ansible_freeipa
```
@@ -343,7 +363,7 @@ If Ansible vault is used for passwords, then it is needed to adapt the playbooks
state: present
```
It is also needed to provide the vault passowrd file on the ansible-playbook command line:
It is also needed to provide the vault password file on the ansible-playbook command line:
```bash
ansible-playbook -v -i inventory/hosts --vault-password-file .vaul_pass.txt install-server.yml
```
@@ -384,6 +404,15 @@ Modules in plugin/modules
=========================
* [ipagroup](README-group.md)
* [ipahbacrule](README-hbacrule.md)
* [ipahbacsvc](README-hbacsvc.md)
* [ipahbacsvcgroup](README-hbacsvc.md)
* [ipahost](README-host.md)
* [ipahostgroup](README-hostgroup.md)
* [ipapwpolicy](README-pwpolicy.md)
* [ipasudocmd](README-sudocmd.md)
* [ipasudocmdgroup](README-sudocmdgroup.md)
* [ipasudorule](README-sudorule.md)
* [ipatopologysegment](README-topology.md)
* [ipatopologysuffix](README-topology.md)
* [ipauser](README-user.md)

View File

@@ -1,7 +1,7 @@
namespace: "freeipa"
name: "ansible_freeipa"
version: "A.B.C"
description: ""
description: "Ansible roles and modules for FreeIPA"
authors:
- "Thomas Woerner <twoerner@redhat.com>"
@@ -11,8 +11,6 @@ documentation: "https://github.com/freeipa/ansible-freeipa/blob/master/README.md
homepage: "https://github.com/freeipa/ansible-freeipa"
issues: "https://github.com/freeipa/ansible-freeipa/issues"
dependencies: {}
readme: "README.md"
license: "GPL-3.0-or-later"
license_file: "COPYING"

View File

@@ -0,0 +1,12 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Rule allhosts is absent
ipahbacrule:
ipaadmin_password: MyPassword123
name: allhosts
state: absent

View File

@@ -0,0 +1,12 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Rule allhosts is disabled
ipahbacrule:
ipaadmin_password: MyPassword123
name: allhosts
state: disabled

View File

@@ -0,0 +1,12 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Rule allhosts is enabled
ipahbacrule:
ipaadmin_password: MyPassword123
name: allhosts
state: enabled

View File

@@ -0,0 +1,12 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Rule allhosts is present
ipahbacrule:
ipaadmin_password: MyPassword123
name: allhosts
usercategory: all

View File

@@ -0,0 +1,14 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure host server is absent in HBAC Rule allhosts
ipahbacrule:
ipaadmin_password: MyPassword123
name: allhosts
host: server
action: member
state: absent

View File

@@ -0,0 +1,13 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure host server is present in HBAC Rule allhosts
ipahbacrule:
ipaadmin_password: MyPassword123
name: allhosts
host: server
action: member

View File

@@ -0,0 +1,12 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Services for http and tftp are absent
ipahbacsvc:
ipaadmin_password: MyPassword123
name: http,tftp
state: absent

View File

@@ -0,0 +1,18 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service for http is present
ipahbacsvc:
ipaadmin_password: MyPassword123
name: http
description: Web service
- name: Ensure HBAC Service for tftp is present
ipahbacsvc:
ipaadmin_password: MyPassword123
name: tftp
description: TFTP service

View File

@@ -0,0 +1,14 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service Group login is absent
ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
state: absent

View File

@@ -0,0 +1,15 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Services sshd is absent in HBAC Service Group login
ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
action: member
state: absent

View File

@@ -0,0 +1,14 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service sshd is present in HBAC Service Group login
ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
action: member

View File

@@ -0,0 +1,14 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure HBAC Service sshd is present in HBAC Service Group login
ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
action: member

1
playbooks/host/add-host.yml Symbolic link
View File

@@ -0,0 +1 @@
host-present.yml

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
- name: Ensure host host01.example.com is absent
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
state: absent

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to handle hosts
hosts: ipaserver
become: true
tasks:
- name: Disable host host01.example.com
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
state: disabled

View File

@@ -0,0 +1,18 @@
---
- name: Ensure host with random password
hosts: ipaserver
become: true
tasks:
- name: Host "{{ 'host1.' + ipaserver_domain }}" present with random password
ipahost:
ipaadmin_password: MyPassword123
name: "{{ 'host1.' + ipaserver_domain }}"
random: yes
force: yes
update_password: on_create
register: ipahost
- name: Print generated random password
debug:
var: ipahost.host.randompassword

View File

@@ -0,0 +1,24 @@
---
- name: Host member allow_create_keytab absent
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com members allow_create_keytab absent for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: MyPassword123
name: host01.exmaple.com
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- host02.exmaple.com
- host03.exmaple.com
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent

View File

@@ -0,0 +1,23 @@
---
- name: Host member allow_create_keytab present
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com members allow_create_keytab present for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: MyPassword123
name: host01.exmaple.com
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- host02.exmaple.com
- host03.exmaple.com
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member

View File

@@ -0,0 +1,24 @@
---
- name: Host member allow_retrieve_keytab absent
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com members allow_retrieve_keytab absent for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: MyPassword123
name: host01.exmaple.com
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- host02.exmaple.com
- host03.exmaple.com
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member
state: absent

View File

@@ -0,0 +1,23 @@
---
- name: Host member allow_retrieve_keytab present
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com members allow_retrieve_keytab present for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: MyPassword123
name: host01.exmaple.com
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- host02.exmaple.com
- host03.exmaple.com
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
action: member

View File

@@ -0,0 +1,13 @@
- name: Host member certificate absent
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com member certificate absent
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
certificate:
- MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
action: member
state: absent

View File

@@ -0,0 +1,12 @@
- name: Host member certificate present
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com member certificate present
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
certificate:
- MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
action: member

View File

@@ -0,0 +1,12 @@
---
- name: Host member managedby_host absent
hosts: ipaserver
become: true
tasks:
ipahost:
ipaadmin_password: MyPassword123
name: host01.exmaple.com
managedby_host: server.exmaple.com
action: member
state: absent

View File

@@ -0,0 +1,11 @@
---
- name: Host member managedby_host present
hosts: ipaserver
become: true
tasks:
ipahost:
ipaadmin_password: MyPassword123
name: host01.exmaple.com
managedby_host: server.exmaple.com
action: member

View File

@@ -0,0 +1,15 @@
---
- name: Host member principal absent
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com principals host/testhost01.example.com and host/myhost01.example.com absent
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
principal:
- host/testhost01.example.com
- host/myhost01.example.com
action: member
state: absent

View File

@@ -0,0 +1,14 @@
---
- name: Host member principal present
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com principals host/testhost01.example.com and host/myhost01.example.com present
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
principal:
- host/testhost01.example.com
- host/myhost01.example.com
action: member

View File

@@ -0,0 +1,23 @@
---
- name: Host present with allow_create_keytab
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com present with allow_create_keytab for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: MyPassword123
name: host01.exmaple.com
allow_create_keytab_user:
- user01
- user02
allow_create_keytab_group:
- group01
- group02
allow_create_keytab_host:
- host02.exmaple.com
- host03.exmaple.com
allow_create_keytab_hostgroup:
- hostgroup01
- hostgroup02
ip_address: 192.168.0.123

View File

@@ -0,0 +1,23 @@
---
- name: Host present with allow_retrieve_keytab
hosts: ipaserver
become: true
tasks:
- name: Host host1.example.com present with allow_retrieve_keytab for users, groups, hosts and hostgroups
ipahost:
ipaadmin_password: MyPassword123
name: host01.exmaple.com
allow_retrieve_keytab_user:
- user01
- user02
allow_retrieve_keytab_group:
- group01
- group02
allow_retrieve_keytab_host:
- host02.exmaple.com
- host03.exmaple.com
allow_retrieve_keytab_hostgroup:
- hostgroup01
- hostgroup02
ip_address: 192.168.0.123

View File

@@ -0,0 +1,12 @@
- name: Host present with certificate
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with certificate
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
certificate:
- MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
force: yes

View File

@@ -0,0 +1,11 @@
---
- name: Host present with managedby_host
hosts: ipaserver
become: true
tasks:
ipahost:
ipaadmin_password: MyPassword123
name: host01.exmaple.com
managedby_host: server.exmaple.com
force: yes

View File

@@ -0,0 +1,14 @@
---
- name: Host present with principal
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with principals host/testhost01.example.com and host/myhost01.example.com
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
principal:
- host/testhost01.example.com
- host/myhost01.example.com
force: yes

View File

@@ -0,0 +1,17 @@
---
- name: Host present with random password
hosts: ipaserver
become: true
tasks:
- name: Host host01.example.com present with random password
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
random: yes
force: yes
register: ipahost
- name: Print generated random password
debug:
var: ipahost.host.randompassword

View File

@@ -0,0 +1,20 @@
---
- name: Host present
hosts: ipaserver
become: true
tasks:
- name: Ensure host is present
ipahost:
ipaadmin_password: MyPassword123
name: host01.example.com
description: Example host
ip_address: 192.168.0.123
locality: Lab
ns_host_location: Lab
ns_os_version: CentOS 7
ns_hardware_platform: Lenovo T61
mac_address:
- "08:00:27:E3:B1:2D"
- "52:54:00:BD:97:1E"
state: present

View File

@@ -0,0 +1,18 @@
---
- name: Hosts member certificate absent
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.exmaple.com member certificate absent
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.example.com
certificate:
- MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
- name: host02.example.com
certificate:
- MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NDVaFw0yMDEwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhFonx99AKi44iaZkrlMKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJijJ7S/4o7h7eeqcJVXJkEhWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClplysL8OyyEG7pbX/aB9iAfFb/+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1wNw1rqWKF1ZzagWRlG4QgzRGwQ4quc7yO98TKikj2OPiIt7Zd46hbqQxmgGBtCkVOZIhxu77OmNrFsXmM4rZZpmqh0UdqcpwkRojVnGXmNqeMCd6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5R1mG4RJ2XAgMBAAGjUzBRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFKOnpTAfBgNVHSMEGDAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBBg97T2Uc1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdotIWlG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKhdhu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMngCfGUe1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcmDKfNT3YZM8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi8mW+V6bAqn9pir/J14r4YFnqMGgjmdt81tscJV
action: member
state: absent

View File

@@ -0,0 +1,17 @@
---
- name: Hosts member certificate present
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.exmaple.com member certificate present
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.example.com
certificate:
- MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
- name: host02.example.com
certificate:
- MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NDVaFw0yMDEwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhFonx99AKi44iaZkrlMKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJijJ7S/4o7h7eeqcJVXJkEhWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClplysL8OyyEG7pbX/aB9iAfFb/+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1wNw1rqWKF1ZzagWRlG4QgzRGwQ4quc7yO98TKikj2OPiIt7Zd46hbqQxmgGBtCkVOZIhxu77OmNrFsXmM4rZZpmqh0UdqcpwkRojVnGXmNqeMCd6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5R1mG4RJ2XAgMBAAGjUzBRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFKOnpTAfBgNVHSMEGDAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBBg97T2Uc1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdotIWlG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKhdhu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMngCfGUe1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcmDKfNT3YZM8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi8mW+V6bAqn9pir/J14r4YFnqMGgjmdt81tscJV
action: member

View File

@@ -0,0 +1,15 @@
---
- name: Hosts member managedby_host absent
hosts: ipaserver
become: true
tasks:
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.exmaple.com
managedby_host: server.exmaple.com
- name: host02.exmaple.com
managedby_host: server.exmaple.com
action: member
state: absent

View File

@@ -0,0 +1,14 @@
---
- name: Hosts member managedby_host present
hosts: ipaserver
become: true
tasks:
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.exmaple.com
managedby_host: server.exmaple.com
- name: host02.exmaple.com
managedby_host: server.exmaple.com
action: member

View File

@@ -0,0 +1,18 @@
---
- name: Host member principal absent
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.exmaple.com and host02.exmaple.com member principals host/testhost0X.exmaple.com absent
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.exmaple.com
principal:
- host/testhost01.exmaple.com
- name: host02.exmaple.com
principal:
- host/testhost02.exmaple.com
action: member
state: absent

View File

@@ -0,0 +1,17 @@
---
- name: Hosts member principal present
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.exmaple.com and host02.exmaple.com member principals host/testhost0X.exmaple.com present
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.exmaple.com
principal:
- host/testhost01.exmaple.com
- name: host02.exmaple.com
principal:
- host/testhost02.exmaple.com
action: member

View File

@@ -0,0 +1,17 @@
---
- name: Hosts present with certificate
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.exmaple.com present with certificate
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.example.com
certificate:
- MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMDEwMTMxNjI4MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJmOVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQbCYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmspsir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzYZ2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdxpOXMZo3Nhy+ldnf13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8DB4Kk+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsGLv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31ykBshOsOblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0fdAMmSA+jMAvTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9mBDWFQLszd/tF+ePKiNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyji8r3
- name: host02.example.com
certificate:
- MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NDVaFw0yMDEwMTMxNjI4NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWzJibKtN8Zf7LgandINhFonx99AKi44iaZkrlMKEObE6Faf8NTUbUgK3VfJNYmCbA1baLVJ0YZJijJ7S/4o7h7eeqcJVXJkEhWNTimWXNW/YCzTHe3SSapnSYOKmdHHRClplysL8OyyEG7pbX/aB9iAfFb/+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv1wNw1rqWKF1ZzagWRlG4QgzRGwQ4quc7yO98TKikj2OPiIt7Zd46hbqQxmgGBtCkVOZIhxu77OmNrFsXmM4rZZpmqh0UdqcpwkRojVnGXmNqeMCd6dNTnLhr9wukUYw0KgE57zCDVr9Ix+p/dA5R1mG4RJ2XAgMBAAGjUzBRMB0GA1UdDgQWBBSbuiH2lNVrID3yt1SsFwtOFKOnpTAfBgNVHSMEGDAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFMHRBBg97T2Uc1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdotIWlG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKhdhu1xBe4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMngCfGUe1bnYeWnLbpFbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcmDKfNT3YZM8kiGQwmFrnQdq8bN0uHR8Nz+24cbmdbHcD65wlDW6GmYxi8mW+V6bAqn9pir/J14r4YFnqMGgjmdt81tscJV
force: yes

View File

@@ -0,0 +1,15 @@
---
- name: Host present with managedby_host
hosts: ipaserver
become: true
tasks:
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.exmaple.com
managedby_host: server.exmaple.com
force: yes
- name: host02.exmaple.com
managedby_host: server.exmaple.com
force: yes

View File

@@ -0,0 +1,26 @@
---
- name: Hosts present with random passwords
hosts: ipaserver
become: true
tasks:
- name: Hosts host01.example.com and host01.example.com present with random passwords
ipahost:
ipaadmin_password: MyPassword123
hosts:
- name: host01.example.com
random: yes
force: yes
- name: host02.example.com
random: yes
force: yes
register: ipahost
- name: Print generated random password for host01.example.com
debug:
var: ipahost.host["host01.example.com"].randompassword
- name: Print generated random password for host02.example.com
debug:
var: ipahost.host["host02.example.com"].randompassword

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure host-group databases is present
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
state: absent

View File

@@ -0,0 +1,15 @@
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure host-group databases is present
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server

View File

@@ -0,0 +1,17 @@
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure hosts and hostgroups are present in existing databases hostgroup
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
state: absent

View File

@@ -0,0 +1,16 @@
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure hosts and hostgroups are present in existing databases hostgroup
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member

View File

@@ -0,0 +1,12 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure absence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
name: ops
state: absent

View File

@@ -0,0 +1,20 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Ensure presence of pwpolicies for group ops
ipapwpolicy:
ipaadmin_password: SomeADMINpassword
name: ops
minlife: 7
maxlife: 49
history: 5
priority: 1
lockouttime: 300
minlength: 8
minclasses: 5
maxfail: 3
failinterval: 5

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to manage sudo command
hosts: ipaserver
become: true
tasks:
# Ensure sudo command is absent
- ipasudocmd:
ipaadmin_password: MyPassword123
name: /usr/bin/su
state: absent

View File

@@ -0,0 +1,11 @@
---
- name: Playbook to manage sudo command
hosts: ipaserver
become: true
tasks:
# Ensure sudo command is present
- ipasudocmd:
ipaadmin_password: MyPassword123
name: /usr/bin/su
state: present

View File

@@ -0,0 +1,15 @@
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudocmds are absent in sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
state: absent

View File

@@ -0,0 +1,22 @@
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudo commands are present
- ipasudocmd:
ipaadmin_password: MyPassword123
name:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: present
# Ensure sudo commands are present in existing sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member

View File

@@ -0,0 +1,12 @@
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudocmdgroup is absent
- ipasudocmdgroup:
ipaadmin_password: pass1234
name: network
state: absent
action: sudocmdgroup

View File

@@ -0,0 +1,15 @@
---
- name: Playbook to handle sudocmdgroups
hosts: ipaserver
become: true
tasks:
# Ensure sudocmdgroup sudocmds are present
- ipasudocmdgroup:
ipaadmin_password: pass1234
name: network
description: Group of important commands.
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
state: present

View File

@@ -0,0 +1,14 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure host server is absent in Sudo Rule
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
host: server
action: member
state: absent

View File

@@ -0,0 +1,13 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure host server is present in Sudo Rule
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
host: server
action: member

View File

@@ -0,0 +1,14 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure hostgroup cluster is absent in Sudo Rule
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
hostgroup: cluster
action: member
state: absent

View File

@@ -0,0 +1,13 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure hostgrep cluster is present in Sudo Rule
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
hostgroup: cluster
action: member

View File

@@ -0,0 +1,11 @@
---
- name: Tests
hosts: ipaserver
become: true
tasks:
# Ensure sudorule command is absent
- ipasudorule:
ipaadmin_password: pass1234
name: testrule1
state: absent

View File

@@ -0,0 +1,11 @@
---
- name: Tests
hosts: ipaserver
become: true
tasks:
# Ensure sudorule command is disabled
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
state: disabled

View File

@@ -0,0 +1,11 @@
---
- name: Tests
hosts: ipaserver
become: true
tasks:
# Ensure sudorule command is enabled
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
state: enabled

View File

@@ -0,0 +1,12 @@
---
- name: Tests
hosts: ipaserver
become: true
tasks:
# Ensure sudorule command is present
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
description: A test sudo rule.
state: present

View File

@@ -0,0 +1,15 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
cmd:
- /sbin/ifconfig
- /usr/bin/vim
action: member
state: absent

View File

@@ -0,0 +1,14 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
cmd:
- /sbin/ifconfig
- /usr/bin/vim
action: member

View File

@@ -0,0 +1,19 @@
---
- name: Ensure user with random password
hosts: ipaserver
become: true
tasks:
- name: User user1 present with random password
ipauser:
ipaadmin_password: MyPassword123
name: user1
first: first1
last: last1
random: yes
update_password: on_create
register: ipauser
- name: Print generated random password
debug:
var: ipauser.user.randompassword

View File

@@ -0,0 +1,28 @@
---
- name: Tests
hosts: ipaserver
become: true
tasks:
- name: Users user1 and user1 present with random password
ipauser:
ipaadmin_password: MyPassword123
users:
- name: user1
first: first1
last: last1
random: yes
- name: user2
first: first2
last: last2
random: yes
update_password: on_create
register: ipauser
- name: Print generated random password for user1
debug:
var: ipauser.user.user1.randompassword
- name: Print generated random password for user2
debug:
var: ipauser.user.user2.randompassword

View File

@@ -0,0 +1,16 @@
---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User test cert absent
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certificate:
- 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
state: absent

View File

@@ -0,0 +1,15 @@
---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User test cert present
ipauser:
ipaadmin_password: SomeADMINpassword
name: test
certificate:
- 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

View File

@@ -0,0 +1,40 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User pinky present
ipauser:
ipaadmin_password: SomeADMINpassword
name: pinky
uid: 10001
gid: 100
phone: "+555123457"
email: pinky@acme.com
principalexpiration: "20220119235959"
passwordexpiration: "2022-01-19 23:59:59"
first: pinky
last: Acme
initials: pa
principal: pa
random: yes
city: PinkyCity
userstate: PinkyState
postalcode: 321
mobile: "+555123458,+555123459"
pager: "+555123450,+555123451"
fax: "+555123452,+555123453"
orgunit: PinkyOrgUnit
manager: manager1,manager2
update_password: on_create
carlicense: PinkyCarLicense1,PinkyCarLicense2
userauthtype: password,radius,otp
userclass: PinkyUserClass
departmentnumber: "1234"
employeenumber: "0815"
employeetype: "PinkyExmployeeType"
preferredlanguage: "en"
noprivate: yes
nomembers: false

View File

@@ -0,0 +1,42 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Users user1..10 absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
givenname: user1
last: Last
- name: user2
first: user2
last: Last
- name: user3
first: user3
last: Last
- name: user4
first: user4
last: Last
- name: user5
first: user5
last: Last
- name: user6
first: user6
last: Last
- name: user7
first: user7
last: Last
- name: user8
first: user8
last: Last
- name: user9
first: user9
last: Last
- name: user10
first: user10
last: Last
state: absent

View File

@@ -0,0 +1,17 @@
---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User test cert absent
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- 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
state: absent

View File

@@ -0,0 +1,16 @@
---
- name: Test user certificates
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: User test cert present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: test
certificate:
- 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

View File

@@ -0,0 +1,41 @@
---
- name: Tests
hosts: ipaserver
become: true
gather_facts: false
tasks:
- name: Users user1..10 present
ipauser:
ipaadmin_password: SomeADMINpassword
users:
- name: user1
first: user1
last: Last
- name: user2
first: user2
last: Last
- name: user3
first: user3
last: Last
- name: user4
first: user4
last: Last
- name: user5
first: user5
last: Last
- name: user6
first: user6
last: Last
- name: user7
first: user7
last: Last
- name: user8
first: user8
last: Last
- name: user9
first: user9
last: Last
- name: user10
first: user10
last: Last

View File

@@ -22,25 +22,66 @@
import os
import uuid
import tempfile
import shutil
import gssapi
from datetime import datetime
from ipalib import api
from ipalib.config import Env
from ipalib.constants import DEFAULT_CONFIG, LDAP_GENERALIZED_TIME_FORMAT
try:
from ipalib.install.kinit import kinit_password
from ipalib.install.kinit import kinit_password, kinit_keytab
except ImportError:
from ipapython.ipautil import kinit_password
from ipapython.ipautil import kinit_password, kinit_keytab
from ipapython.ipautil import run
from ipaplatform.paths import paths
from ipalib.krb_utils import get_credentials_if_valid
from ansible.module_utils._text import to_text
try:
from ipalib.x509 import Encoding
except ImportError:
from cryptography.hazmat.primitives.serialization import Encoding
import base64
import six
def valid_creds(principal):
if six.PY3:
unicode = str
def valid_creds(module, principal):
"""
Get valid credintials matching the princial
Get valid credintials matching the princial, try GSSAPI first
"""
if "KRB5CCNAME" in os.environ:
ccache = os.environ["KRB5CCNAME"]
module.debug('KRB5CCNAME set to %s' % ccache)
try:
cred = gssapi.Credentials(usage='initiate',
store={'ccache': ccache})
except gssapi.raw.misc.GSSError as e:
module.fail_json(msg='Failed to find default ccache: %s' % e)
else:
module.debug("Using principal %s" % str(cred.name))
return True
elif "KRB5_CLIENT_KTNAME" in os.environ:
keytab = os.environ.get('KRB5_CLIENT_KTNAME', None)
module.debug('KRB5_CLIENT_KTNAME set to %s' % keytab)
ccache_name = "MEMORY:%s" % str(uuid.uuid4())
os.environ["KRB5CCNAME"] = ccache_name
try:
cred = kinit_keytab(principal, keytab, ccache_name)
except gssapi.raw.misc.GSSError as e:
module.fail_json(msg='Kerberos authentication failed : %s' % e)
else:
module.debug("Using principal %s" % str(cred.name))
return True
creds = get_credentials_if_valid()
if creds and \
creds.lifetime > 0 and \
@@ -79,7 +120,7 @@ def temp_kdestroy(ccache_dir, ccache_name):
shutil.rmtree(ccache_dir, ignore_errors=True)
def api_connect():
def api_connect(context=None):
"""
Create environment, initialize api and connect to ldap2
"""
@@ -87,19 +128,34 @@ def api_connect():
env._bootstrap()
env._finalize_core(**dict(DEFAULT_CONFIG))
api.bootstrap(context='server', debug=env.debug, log=None)
# available contexts are 'server', 'ansible-freeipa' and 'cli_installer'
if context is None:
context = 'server'
api.bootstrap(context=context, debug=env.debug, log=None)
api.finalize()
api.Backend.ldap2.connect()
if api.env.in_server:
backend = api.Backend.ldap2
else:
backend = api.Backend.rpcclient
if not backend.isconnected():
backend.connect()
def api_command(module, command, name, args):
"""
Call ipa.Command, use AnsibleModule.fail_json for error handling
Call ipa.Command
"""
try:
return api.Command[command](name, **args)
except Exception as e:
module.fail_json(msg="%s: %s" % (command, e))
return api.Command[command](name, **args)
def api_check_param(command, name):
"""
Return if param exists in command param list
"""
return name in api.Command[command].params
def execute_api_command(module, principal, password, command, name, args):
@@ -110,7 +166,7 @@ def execute_api_command(module, principal, password, command, name, args):
ccache_dir = None
ccache_name = None
try:
if not valid_creds(principal):
if not valid_creds(module, principal):
ccache_dir, ccache_name = temp_kinit(principal, password)
api_connect()
@@ -150,10 +206,65 @@ def compare_args_ipa(module, args, ipa):
# 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]
if isinstance(ipa_arg, tuple):
ipa_arg = list(ipa_arg)
if isinstance(ipa_arg, list):
if not isinstance(arg, list):
arg = [arg]
if isinstance(ipa_arg[0], str) and isinstance(arg[0], int):
arg = [to_text(_arg) for _arg in arg]
if isinstance(ipa_arg[0], unicode) and isinstance(arg[0], int):
arg = [to_text(_arg) for _arg in arg]
# module.warn("%s <=> %s" % (arg, ipa_arg))
if arg != ipa_arg:
if set(arg) != set(ipa_arg):
# module.warn("DIFFERENT")
return False
return True
def _afm_convert(value):
if value is not None:
if isinstance(value, list):
return [_afm_convert(x) for x in value]
elif isinstance(value, dict):
return {_afm_convert(k): _afm_convert(v) for k, v in value.items()}
elif isinstance(value, str):
return to_text(value)
else:
return value
else:
return value
def module_params_get(module, name):
return _afm_convert(module.params.get(name))
def api_get_realm():
return api.env.realm
def gen_add_del_lists(user_list, res_list):
"""
Generate the lists for the addition and removal of members using the
provided user and ipa settings
"""
add_list = list(set(user_list or []) - set(res_list or []))
del_list = list(set(res_list or []) - set(user_list or []))
return add_list, del_list
def encode_certificate(cert):
"""
Encode a certificate using base64 with also taking FreeIPA and Python
versions into account
"""
if isinstance(cert, str) or isinstance(cert, unicode):
encoded = base64.b64encode(cert)
else:
encoded = base64.b64encode(cert.public_bytes(Encoding.DER))
if not six.PY2:
encoded = encoded.decode('ascii')
return encoded

View File

@@ -70,7 +70,9 @@ options:
required: false
type: list
service:
description: List of service names assigned to this group.
description:
- List of service names assigned to this group.
- Only usable with IPA versions 4.7 and up.
required: false
type: list
action:
@@ -137,18 +139,18 @@ 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
temp_kdestroy, valid_creds, api_connect, api_command, compare_args_ipa, \
api_check_param, module_params_get
def find_group(module, name):
_args = {
"all": True,
"cn": to_text(name),
"cn": name,
}
_result = api_command(module, "group_find", to_text(name), _args)
_result = api_command(module, "group_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
@@ -164,7 +166,7 @@ def gen_args(description, gid, nonposix, external, nomembers):
if description is not None:
_args["description"] = description
if gid is not None:
_args["gidnumber"] = str(gid)
_args["gidnumber"] = gid
if nonposix is not None:
_args["nonposix"] = nonposix
if external is not None:
@@ -209,8 +211,7 @@ def main():
choices=["member", "group"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent",
"member_present", "member_absent"]),
choices=["present", "absent"]),
),
supports_check_mode=True,
)
@@ -220,29 +221,29 @@ def main():
# 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")
ipaadmin_principal = module_params_get(ansible_module, "ipaadmin_principal")
ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
names = module_params_get(ansible_module, "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")
description = module_params_get(ansible_module, "description")
gid = module_params_get(ansible_module, "gid")
nonposix = module_params_get(ansible_module, "nonposix")
external = module_params_get(ansible_module, "external")
nomembers = module_params_get(ansible_module, "nomembers")
user = module_params_get(ansible_module, "user")
group = module_params_get(ansible_module, "group")
service = module_params_get(ansible_module, "service")
action = module_params_get(ansible_module, "action")
# state
state = ansible_module.params.get("state")
state = module_params_get(ansible_module, "state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Onle one group can be added at a time.")
msg="Only one group can be added at a time.")
if action == "member":
invalid = ["description", "gid", "nonposix", "external",
"nomembers"]
@@ -272,11 +273,17 @@ def main():
ccache_dir = None
ccache_name = None
try:
if not valid_creds(ipaadmin_principal):
if not valid_creds(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
has_add_member_service = api_check_param("group_add_member", "service")
if service is not None and not has_add_member_service:
ansible_module.fail_json(
msg="Managing a service as part of a group is not supported "
"by your IPA version")
commands = []
for name in names:
@@ -326,47 +333,56 @@ def main():
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,
}])
if has_add_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_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,
}])
else:
# Add members
if len(user_add) > 0 or len(group_add) > 0:
commands.append([name, "group_add_member",
{
"user": user_add,
"group": group_add,
}])
# Remove members
if len(user_del) > 0 or len(group_del) > 0:
commands.append([name, "group_remove_member",
{
"user": user_del,
"group": group_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:
if has_add_member_service:
commands.append([name, "group_add_member",
{
"user": user,
"group": group,
"service": service,
}])
else:
commands.append([name, "group_add_member",
{
"user": user,
"group": group,
}])
elif state == "absent":
if action == "group":
@@ -377,26 +393,12 @@ def main():
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,
}])
commands.append([name, "group_remove_member",
{
"user": user,
"group": group,
"service": service,
}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
@@ -404,11 +406,32 @@ def main():
for name, command, args in commands:
try:
api_command(ansible_module, command, to_text(name), args)
changed = True
result = api_command(ansible_module, command, name,
args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
errors = []
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
except Exception as e:
ansible_module.fail_json(msg=str(e))

View File

@@ -0,0 +1,556 @@
#!/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: ipahbacrule
short description: Manage FreeIPA HBAC rules
description: Manage FreeIPA HBAC rules
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: false
name:
description: The hbacrule name
required: true
aliases: ["cn"]
description:
description: The hbacrule description
required: false
usercategory:
description: User category the rule applies to
required: false
aliases: ["usercat"]
choices: ["all"]
hostcategory:
description: Host category the rule applies to
required: false
aliases: ["hostcat"]
choices: ["all"]
servicecategory:
description: Service category the rule applies to
required: false
aliases: ["servicecat"]
choices: ["all"]
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
host:
description: List of host names assigned to this hbacrule.
required: false
type: list
hostgroup:
description: List of host groups assigned to this hbacrule.
required: false
type: list
hbacsvc:
description: List of HBAC service names assigned to this hbacrule.
required: false
type: list
hbacsvcgroup:
description: List of HBAC service names assigned to this hbacrule.
required: false
type: list
user:
description: List of user names assigned to this hbacrule.
required: false
type: list
group:
description: List of user groups assigned to this hbacrule.
required: false
type: list
action:
description: Work on hbacrule or member level
default: hbacrule
choices: ["member", "hbacrule"]
state:
description: State to ensure
default: present
choices: ["present", "absent", "enabled", "disabled"]
author:
- Thomas Woerner
"""
EXAMPLES = """
# Ensure HBAC Rule allhosts is present
- ipahbacrule:
ipaadmin_password: MyPassword123
name: allhosts
usercategory: all
# Ensure host server is present in HBAC Rule allhosts
- ipahbacrule:
ipaadmin_password: MyPassword123
name: allhosts
host: server
action: member
# Ensure HBAC Rule sshd-pinky is present
- ipahbacrule:
ipaadmin_password: MyPassword123
name: sshd-pinky
hostcategory: all
# Ensure user pinky is present in HBAC Rule sshd-pinky
- ipahbacrule:
ipaadmin_password: MyPassword123
name: sshd-pinky
user: pinky
action: member
# Ensure HBAC service sshd is present in HBAC Rule sshd-pinky
- ipahbacrule:
ipaadmin_password: MyPassword123
name: sshd-pinky
hbacsvc: sshd
action: member
# Ensure HBAC Rule sshd-pinky is disabled
- ipahbacrule:
ipaadmin_password: MyPassword123
name: sshd-pinky
state: disabled
# Ensure HBAC Rule sshd-pinky is enabled
- ipahbacrule:
ipaadmin_password: MyPassword123
name: sshd-pinky
state: enabled
# Ensure HBAC Rule sshd-pinky is absent
- ipahbacrule:
ipaadmin_password: MyPassword123
name: sshd-pinky
state: absent
"""
RETURN = """
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
temp_kdestroy, valid_creds, api_connect, api_command, compare_args_ipa, \
module_params_get
def find_hbacrule(module, name):
_args = {
"all": True,
"cn": name,
}
_result = api_command(module, "hbacrule_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one hbacrule '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(description, usercategory, hostcategory, servicecategory,
nomembers):
_args = {}
if description is not None:
_args["description"] = description
if usercategory is not None:
_args["usercategory"] = usercategory
if hostcategory is not None:
_args["hostcategory"] = hostcategory
if servicecategory is not None:
_args["servicecategory"] = servicecategory
if nomembers is not None:
_args["nomembers"] = nomembers
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),
usercategory=dict(type="str", default=None,
aliases=["usercat"], choices=["all"]),
hostcategory=dict(type="str", default=None,
aliases=["hostcat"], choices=["all"]),
servicecategory=dict(type="str", default=None,
aliases=["servicecat"], choices=["all"]),
nomembers=dict(required=False, type='bool', default=None),
host=dict(required=False, type='list', default=None),
hostgroup=dict(required=False, type='list', default=None),
hbacsvc=dict(required=False, type='list', default=None),
hbacsvcgroup=dict(required=False, type='list', default=None),
user=dict(required=False, type='list', default=None),
group=dict(required=False, type='list', default=None),
action=dict(type="str", default="hbacrule",
choices=["member", "hbacrule"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent",
"enabled", "disabled"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
ipaadmin_principal = module_params_get(ansible_module,
"ipaadmin_principal")
ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
names = module_params_get(ansible_module, "name")
# present
description = module_params_get(ansible_module, "description")
usercategory = module_params_get(ansible_module, "usercategory")
hostcategory = module_params_get(ansible_module, "hostcategory")
servicecategory = module_params_get(ansible_module, "servicecategory")
nomembers = module_params_get(ansible_module, "nomembers")
host = module_params_get(ansible_module, "host")
hostgroup = module_params_get(ansible_module, "hostgroup")
hbacsvc = module_params_get(ansible_module, "hbacsvc")
hbacsvcgroup = module_params_get(ansible_module, "hbacsvcgroup")
user = module_params_get(ansible_module, "user")
group = module_params_get(ansible_module, "group")
action = module_params_get(ansible_module, "action")
# state
state = module_params_get(ansible_module, "state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one hbacrule can be added at a time.")
if action == "member":
invalid = ["description", "usercategory", "hostcategory",
"servicecategory", "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))
elif state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "usercategory", "hostcategory",
"servicecategory", "nomembers"]
if action == "hbacrule":
invalid.extend(["host", "hostgroup", "hbacsvc", "hbacsvcgroup",
"user", "group"])
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))
elif state in ["enabled", "disabled"]:
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
if action == "member":
ansible_module.fail_json(
msg="Action member can not be used with states enabled and "
"disabled")
invalid = ["description", "usercategory", "hostcategory",
"servicecategory", "nomembers", "host", "hostgroup",
"hbacsvc", "hbacsvcgroup", "user", "group"]
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))
else:
ansible_module.fail_json(msg="Invalid state '%s'" % state)
# Init
changed = False
exit_args = {}
ccache_dir = None
ccache_name = None
try:
if not valid_creds(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Make sure hbacrule exists
res_find = find_hbacrule(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description, usercategory, hostcategory,
servicecategory, nomembers)
if action == "hbacrule":
# Found the hbacrule
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, "hbacrule_mod", args])
else:
commands.append([name, "hbacrule_add", args])
# Set res_find to empty dict for next step
res_find = {}
# Generate addition and removal lists
host_add = list(
set(host or []) -
set(res_find.get("member_host", [])))
host_del = list(
set(res_find.get("member_host", [])) -
set(host or []))
hostgroup_add = list(
set(hostgroup or []) -
set(res_find.get("member_hostgroup", [])))
hostgroup_del = list(
set(res_find.get("member_hostgroup", [])) -
set(hostgroup or []))
hbacsvc_add = list(
set(hbacsvc or []) -
set(res_find.get("member_hbacsvc", [])))
hbacsvc_del = list(
set(res_find.get("member_hbacsvc", [])) -
set(hbacsvc or []))
hbacsvcgroup_add = list(
set(hbacsvcgroup or []) -
set(res_find.get("member_hbacsvcgroup", [])))
hbacsvcgroup_del = list(
set(res_find.get("member_hbacsvcgroup", [])) -
set(hbacsvcgroup or []))
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 []))
# Add hosts and hostgroups
if len(host_add) > 0 or len(hostgroup_add) > 0:
commands.append([name, "hbacrule_add_host",
{
"host": host_add,
"hostgroup": hostgroup_add,
}])
# Remove hosts and hostgroups
if len(host_del) > 0 or len(hostgroup_del) > 0:
commands.append([name, "hbacrule_remove_host",
{
"host": host_del,
"hostgroup": hostgroup_del,
}])
# Add hbacsvcs and hbacsvcgroups
if len(hbacsvc_add) > 0 or len(hbacsvcgroup_add) > 0:
commands.append([name, "hbacrule_add_service",
{
"hbacsvc": hbacsvc_add,
"hbacsvcgroup": hbacsvcgroup_add,
}])
# Remove hbacsvcs and hbacsvcgroups
if len(hbacsvc_del) > 0 or len(hbacsvcgroup_del) > 0:
commands.append([name, "hbacrule_remove_service",
{
"hbacsvc": hbacsvc_del,
"hbacsvcgroup": hbacsvcgroup_del,
}])
# Add users and groups
if len(user_add) > 0 or len(group_add) > 0:
commands.append([name, "hbacrule_add_user",
{
"user": user_add,
"group": group_add,
}])
# Remove users and groups
if len(user_del) > 0 or len(group_del) > 0:
commands.append([name, "hbacrule_remove_user",
{
"user": user_del,
"group": group_del,
}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No hbacrule '%s'" % name)
# Add hosts and hostgroups
if host is not None or hostgroup is not None:
commands.append([name, "hbacrule_add_host",
{
"host": host,
"hostgroup": hostgroup,
}])
# Add hbacsvcs and hbacsvcgroups
if hbacsvc is not None or hbacsvcgroup is not None:
commands.append([name, "hbacrule_add_service",
{
"hbacsvc": hbacsvc,
"hbacsvcgroup": hbacsvcgroup,
}])
# Add users and groups
if user is not None or group is not None:
commands.append([name, "hbacrule_add_user",
{
"user": user,
"group": group,
}])
elif state == "absent":
if action == "hbacrule":
if res_find is not None:
commands.append([name, "hbacrule_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No hbacrule '%s'" % name)
# Remove hosts and hostgroups
if host is not None or hostgroup is not None:
commands.append([name, "hbacrule_remove_host",
{
"host": host,
"hostgroup": hostgroup,
}])
# Remove hbacsvcs and hbacsvcgroups
if hbacsvc is not None or hbacsvcgroup is not None:
commands.append([name, "hbacrule_remove_service",
{
"hbacsvc": hbacsvc,
"hbacsvcgroup": hbacsvcgroup,
}])
# Remove users and groups
if user is not None or group is not None:
commands.append([name, "hbacrule_remove_user",
{
"user": user,
"group": group,
}])
elif state == "enabled":
if res_find is None:
ansible_module.fail_json(msg="No hbacrule '%s'" % name)
# hbacrule_enable is not failing on an enabled hbacrule
# Therefore it is needed to have a look at the ipaenabledflag
# in res_find.
if "ipaenabledflag" not in res_find or \
res_find["ipaenabledflag"][0] != "TRUE":
commands.append([name, "hbacrule_enable", {}])
elif state == "disabled":
if res_find is None:
ansible_module.fail_json(msg="No hbacrule '%s'" % name)
# hbacrule_disable is not failing on an disabled hbacrule
# Therefore it is needed to have a look at the ipaenabledflag
# in res_find.
if "ipaenabledflag" not in res_find or \
res_find["ipaenabledflag"][0] != "FALSE":
commands.append([name, "hbacrule_disable", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
errors = []
for name, command, args in commands:
try:
result = api_command(ansible_module, command, name,
args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
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

@@ -0,0 +1,220 @@
#!/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: ipahbacsvc
short description: Manage FreeIPA HBAC Services
description: Manage FreeIPA HBAC Services
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", "service"]
description:
description: The HBAC Service description
required: false
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Thomas Woerner
"""
EXAMPLES = """
# Ensure HBAC Service for http is present
- ipahbacsvc:
ipaadmin_password: MyPassword123
name: http
description: Web service
# Ensure HBAC Service for tftp is absent
- ipahbacsvc:
ipaadmin_password: MyPassword123
name: tftp
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_hbacsvc(module, name):
_args = {
"all": True,
"cn": to_text(name),
}
_result = api_command(module, "hbacsvc_find", to_text(name), _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one hbacsvc '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(description):
_args = {}
if description is not None:
_args["description"] = to_text(description)
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", "service"], default=None,
required=True),
# present
description=dict(type="str", default=None),
# state
state=dict(type="str", default="present",
choices=["present", "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")
# state
state = ansible_module.params.get("state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one hbacsvc can be set at a time.")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(
msg="No name given.")
invalid = ["description"]
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(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Try to find hbacsvc
res_find = find_hbacsvc(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description)
# Found the hbacsvc
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, "hbacsvc_mod", args])
else:
commands.append([name, "hbacsvc_add", args])
elif state == "absent":
if res_find is not None:
commands.append([name, "hbacsvc_del", {}])
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

@@ -0,0 +1,346 @@
#!/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: ipahbacsvcgroup
short description: Manage FreeIPA hbacsvcgroups
description: Manage FreeIPA hbacsvcgroups
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: false
name:
description: The hbacsvcgroup name
required: false
aliases: ["cn"]
description:
description: The hbacsvcgroup description
required: false
hbacsvc:
description: List of hbacsvc names assigned to this hbacsvcgroup.
required: false
type: list
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
action:
description: Work on hbacsvcgroup or member level
default: hbacsvcgroup
choices: ["member", "hbacsvcgroup"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Thomas Woerner
"""
EXAMPLES = """
# Ensure hbacsvcgroup login is present
- ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
hbacsvc:
- sshd
# Ensure hbacsvc sshd is present in existing login hbacsvcgroup
- ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: databases
hbacsvc:
- sshd
action: member
# Ensure hbacsvc sshd is abdsent in existing login hbacsvcgroup
- ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: databases
hbacsvc:
- sshd
action: member
state: absent
# Ensure hbacsvcgroup login is absent
- ipahbacsvcgroup:
ipaadmin_password: MyPassword123
name: login
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_hbacsvcgroup(module, name):
_args = {
"all": True,
"cn": to_text(name),
}
_result = api_command(module, "hbacsvcgroup_find", to_text(name), _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one hbacsvcgroup '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(description, nomembers):
_args = {}
if description is not None:
_args["description"] = to_text(description)
if nomembers is not None:
_args["nomembers"] = nomembers
return _args
def gen_member_args(hbacsvc):
_args = {}
if hbacsvc is not None:
_args["member_hbacsvc"] = [to_text(svc) for svc in hbacsvc]
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),
nomembers=dict(required=False, type='bool', default=None),
hbacsvc=dict(required=False, type='list', default=None),
action=dict(type="str", default="hbacsvcgroup",
choices=["member", "hbacsvcgroup"]),
# state
state=dict(type="str", default="present",
choices=["present", "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")
nomembers = ansible_module.params.get("nomembers")
hbacsvc = ansible_module.params.get("hbacsvc")
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="Only one hbacsvcgroup can be added at a time.")
if action == "member":
invalid = ["description", "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", "nomembers"]
if action == "hbacsvcgroup":
invalid.extend(["hbacsvc"])
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(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Make sure hbacsvcgroup exists
res_find = find_hbacsvcgroup(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description, nomembers)
if action == "hbacsvcgroup":
# Found the hbacsvcgroup
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, "hbacsvcgroup_mod", args])
else:
commands.append([name, "hbacsvcgroup_add", args])
# Set res_find to empty dict for next step
res_find = {}
member_args = gen_member_args(hbacsvc)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
hbacsvc_add = list(
set(hbacsvc or []) -
set(res_find.get("member_hbacsvc", [])))
hbacsvc_del = list(
set(res_find.get("member_hbacsvc", [])) -
set(hbacsvc or []))
# Add members
if len(hbacsvc_add) > 0:
commands.append([name, "hbacsvcgroup_add_member",
{
"hbacsvc":
[to_text(svc)
for svc in hbacsvc_add],
}])
# Remove members
if len(hbacsvc_del) > 0:
commands.append([name,
"hbacsvcgroup_remove_member",
{
"hbacsvc":
[to_text(svc)
for svc in hbacsvc_del],
}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No hbacsvcgroup '%s'" % name)
# Ensure members are present
commands.append([name, "hbacsvcgroup_add_member",
{
"hbacsvc": [to_text(svc)
for svc in hbacsvc],
}])
elif state == "absent":
if action == "hbacsvcgroup":
if res_find is not None:
commands.append([name, "hbacsvcgroup_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No hbacsvcgroup '%s'" % name)
# Ensure members are absent
commands.append([name, "hbacsvcgroup_remove_member",
{
"hbacsvc": [to_text(svc)
for svc in hbacsvc],
}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
errors = []
for name, command, args in commands:
try:
result = api_command(ansible_module, command, to_text(name),
args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and "member" in result["failed"]:
failed = result["failed"]["member"]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" not in failure \
and "not a member" not in failure:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
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()

1279
plugins/modules/ipahost.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,367 @@
#!/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: ipahostgroup
short description: Manage FreeIPA hostgroups
description: Manage FreeIPA hostgroups
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: false
name:
description: The hostgroup name
required: false
aliases: ["cn"]
description:
description: The hostgroup description
required: false
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
host:
description: List of host names assigned to this hostgroup.
required: false
type: list
hostgroup:
description: List of hostgroup names assigned to this hostgroup.
required: false
type: list
action:
description: Work on hostgroup or member level
default: hostgroup
choices: ["member", "hostgroup"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Thomas Woerner
"""
EXAMPLES = """
# Ensure host-group databases is present
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
# Ensure hosts and hostgroups are present in existing databases hostgroup
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
# Ensure hosts and hostgroups are absent in databases hostgroup
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
host:
- db.example.com
hostgroup:
- mysql-server
- oracle-server
action: member
state: absent
# Ensure host-group databases is absent
- ipahostgroup:
ipaadmin_password: MyPassword123
name: databases
state: absent
"""
RETURN = """
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
temp_kdestroy, valid_creds, api_connect, api_command, compare_args_ipa, \
module_params_get
def find_hostgroup(module, name):
_args = {
"all": True,
"cn": name,
}
_result = api_command(module, "hostgroup_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one hostgroup '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(description, nomembers):
_args = {}
if description is not None:
_args["description"] = description
if nomembers is not None:
_args["nomembers"] = nomembers
return _args
def gen_member_args(host, hostgroup):
_args = {}
if host is not None:
_args["member_host"] = host
if hostgroup is not None:
_args["member_hostgroup"] = hostgroup
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),
nomembers=dict(required=False, type='bool', default=None),
host=dict(required=False, type='list', default=None),
hostgroup=dict(required=False, type='list', default=None),
action=dict(type="str", default="hostgroup",
choices=["member", "hostgroup"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
ipaadmin_principal = module_params_get(ansible_module,
"ipaadmin_principal")
ipaadmin_password = module_params_get(ansible_module,
"ipaadmin_password")
names = module_params_get(ansible_module, "name")
# present
description = module_params_get(ansible_module, "description")
nomembers = module_params_get(ansible_module, "nomembers")
host = module_params_get(ansible_module, "host")
hostgroup = module_params_get(ansible_module, "hostgroup")
action = module_params_get(ansible_module, "action")
# state
state = module_params_get(ansible_module, "state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one hostgroup can be added at a time.")
if action == "member":
invalid = ["description", "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", "nomembers"]
if action == "hostgroup":
invalid.extend(["host", "hostgroup"])
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(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Make sure hostgroup exists
res_find = find_hostgroup(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description, nomembers)
if action == "hostgroup":
# Found the hostgroup
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, "hostgroup_mod", args])
else:
commands.append([name, "hostgroup_add", args])
# Set res_find to empty dict for next step
res_find = {}
member_args = gen_member_args(host, hostgroup)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
host_add = list(
set(host or []) -
set(res_find.get("member_host", [])))
host_del = list(
set(res_find.get("member_host", [])) -
set(host or []))
hostgroup_add = list(
set(hostgroup or []) -
set(res_find.get("member_hostgroup", [])))
hostgroup_del = list(
set(res_find.get("member_hostgroup", [])) -
set(hostgroup or []))
# Add members
if len(host_add) > 0 or len(hostgroup_add) > 0:
commands.append([name, "hostgroup_add_member",
{
"host": host_add,
"hostgroup": hostgroup_add,
}])
# Remove members
if len(host_del) > 0 or len(hostgroup_del) > 0:
commands.append([name, "hostgroup_remove_member",
{
"host": host_del,
"hostgroup": hostgroup_del,
}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No hostgroup '%s'" % name)
# Ensure members are present
commands.append([name, "hostgroup_add_member",
{
"host": host,
"hostgroup": hostgroup,
}])
elif state == "absent":
if action == "hostgroup":
if res_find is not None:
commands.append([name, "hostgroup_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No hostgroup '%s'" % name)
# Ensure members are absent
commands.append([name, "hostgroup_remove_member",
{
"host": host,
"hostgroup": hostgroup,
}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
for name, command, args in commands:
try:
result = api_command(ansible_module, command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
errors = []
if "failed" in result and "member" in result["failed"]:
failed = result["failed"]["member"]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" not in failure \
and "not a member" not in failure:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
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

@@ -0,0 +1,304 @@
#!/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: ipapwpolicy
short description: Manage FreeIPA pwpolicies
description: Manage FreeIPA pwpolicies
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"]
maxlife:
description: Maximum password lifetime (in days)
type: int
required: false
aliases: ["krbmaxpwdlife"]
minlife:
description: Minimum password lifetime (in hours)
type: int
required: false
aliases: ["krbminpwdlife"]
history:
description: Password history size
type: int
required: false
aliases: ["krbpwdhistorylength"]
minclasses:
description: Minimum number of character classes
type: int
required: false
aliases: ["krbpwdmindiffchars"]
minlength:
description: Minimum length of password
type: int
required: false
aliases: ["krbpwdminlength"]
priority:
description: Priority of the policy (higher number means lower priority)
type: int
required: false
aliases: ["cospriority"]
maxfail:
description: Consecutive failures before lockout
type: int
required: false
aliases: ["krbpwdmaxfailure"]
failinterval:
description: Period after which failure count will be reset (seconds)
type: int
required: false
aliases: ["krbpwdfailurecountinterval"]
lockouttime:
description: Period for which lockout is enforced (seconds)
type: int
required: false
aliases: ["krbpwdlockoutduration"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Thomas Woerner
"""
EXAMPLES = """
# Ensure pwpolicy is set for ops
- ipapwpolicy:
ipaadmin_password: MyPassword123
name: ops
minlife: 7
maxlife: 49
history: 5
priority: 1
lockouttime: 300
minlength: 8
"""
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_pwpolicy(module, name):
_args = {
"all": True,
"cn": to_text(name),
}
_result = api_command(module, "pwpolicy_find", to_text(name), _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one pwpolicy '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(maxlife, minlife, history, minclasses, minlength, priority,
maxfail, failinterval, lockouttime):
_args = {}
if maxlife is not None:
_args["krbmaxpwdlife"] = maxlife
if minlife is not None:
_args["krbminpwdlife"] = minlife
if history is not None:
_args["krbpwdhistorylength"] = history
if minclasses is not None:
_args["krbpwdmindiffchars"] = minclasses
if minlength is not None:
_args["krbpwdminlength"] = minlength
if priority is not None:
_args["cospriority"] = priority
if maxfail is not None:
_args["krbpwdmaxfailure"] = maxfail
if failinterval is not None:
_args["krbpwdfailurecountinterval"] = failinterval
if lockouttime is not None:
_args["krbpwdlockoutduration"] = lockouttime
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
maxlife=dict(type="int", aliases=["krbmaxpwdlife"], default=None),
minlife=dict(type="int", aliases=["krbminpwdlife"], default=None),
history=dict(type="int", aliases=["krbpwdhistorylength"],
default=None),
minclasses=dict(type="int", aliases=["krbpwdmindiffchars"],
default=None),
minlength=dict(type="int", aliases=["krbpwdminlength"],
default=None),
priority=dict(type="int", aliases=["cospriority"], default=None),
maxfail=dict(type="int", aliases=["krbpwdmaxfailure"],
default=None),
failinterval=dict(type="int",
aliases=["krbpwdfailurecountinterval"],
default=None),
lockouttime=dict(type="int", aliases=["krbpwdlockoutduration"],
default=None),
# state
state=dict(type="str", default="present",
choices=["present", "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
maxlife = ansible_module.params.get("maxlife")
minlife = ansible_module.params.get("minlife")
history = ansible_module.params.get("history")
minclasses = ansible_module.params.get("minclasses")
minlength = ansible_module.params.get("minlength")
priority = ansible_module.params.get("priority")
maxfail = ansible_module.params.get("maxfail")
failinterval = ansible_module.params.get("failinterval")
lockouttime = ansible_module.params.get("lockouttime")
# state
state = ansible_module.params.get("state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one pwpolicy can be set at a time.")
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(
msg="No name given.")
invalid = ["maxlife", "minlife", "history", "minclasses",
"minlength", "priority", "maxfail", "failinterval",
"lockouttime"]
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(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Try to find pwpolicy
res_find = find_pwpolicy(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(maxlife, minlife, history, minclasses,
minlength, priority, maxfail, failinterval,
lockouttime)
# Found the pwpolicy
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, "pwpolicy_mod", args])
else:
commands.append([name, "pwpolicy_add", args])
elif state == "absent":
if res_find is not None:
commands.append([name, "pwpolicy_del", {}])
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

@@ -0,0 +1,211 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman <rjeffman@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: ipasudocmd
short description: Manage FreeIPA sudo command
description: Manage FreeIPA sudo command
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: false
name:
description: The sudo command
required: true
aliases: ["sudocmd"]
description:
description: The command description
required: false
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Rafael Jeffman
"""
EXAMPLES = """
# Ensure sudocmd is present
- ipacommand:
ipaadmin_password: MyPassword123
name: su
state: present
# Ensure sudocmd is absent
- ipacommand:
ipaadmin_password: MyPassword123
name: su
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_sudocmd(module, name):
_args = {
"all": True,
"sudocmd": to_text(name),
}
_result = api_command(module, "sudocmd_find", to_text(name), _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one sudocmd '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(description):
_args = {}
if description is not None:
_args["description"] = description
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=["sudocmd"], default=None,
required=True),
# present
description=dict(type="str", default=None),
# state
state=dict(type="str", default="present",
choices=["present", "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")
# state
state = ansible_module.params.get("state")
# Check parameters
if state == "absent":
invalid = ["description"]
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(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Make sure hostgroup exists
res_find = find_sudocmd(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description)
if res_find is not None:
# For all settings in 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, "sudocmd_mod", args])
else:
commands.append([name, "sudocmd_add", args])
# Set res_find to empty dict for next step
res_find = {}
elif state == "absent":
if res_find is not None:
commands.append([name, "sudocmd_del", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
for name, command, args in commands:
try:
result = api_command(ansible_module, command, to_text(name),
args)
# Check if any changes were made by any command
if command == 'sudocmd_del':
changed |= "Deleted" in result['summary']
elif command == 'sudocmd_add':
changed |= "Added" in result['summary']
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

@@ -0,0 +1,355 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman <rjeffman@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: ipasudocmdgroup
short description: Manage FreeIPA sudocmd groups
description: Manage FreeIPA sudocmd groups
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: false
name:
description: The sudocmodgroup name
required: false
aliases: ["cn"]
description:
description: The sudocmdgroup description
required: false
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
sudocmdgroup:
description: List of sudocmdgroup names assigned to this sudocmdgroup.
required: false
type: list
sudocmd:
description: List of sudocmds assigned to this sudocmdgroup.
required: false
type: list
action:
description: Work on sudocmdgroup or member level
default: hostgroup
choices: ["member", "sudocmdgroup"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
author:
- Rafael Guterres Jeffman
"""
EXAMPLES = """
# Ensure sudocmd-group 'network' is present
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: network
state: present
# Ensure sudocmdgroup and sudocmd are present in 'network' sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
# Ensure sudocmdgroup and sudocmd are absent in 'network' sudocmdgroup
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: network
sudocmd:
- /usr/sbin/ifconfig
- /usr/sbin/iwlist
action: member
state: absent
# Ensure sudocmd-group 'network' is absent
- ipasudocmdgroup:
ipaadmin_password: MyPassword123
name: network
action: member
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_sudocmdgroup(module, name):
_args = {
"all": True,
"cn": to_text(name),
}
_result = api_command(module, "sudocmdgroup_find", to_text(name), _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one sudocmdgroup '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(description, nomembers):
_args = {}
if description is not None:
_args["description"] = to_text(description)
if nomembers is not None:
_args["nomembers"] = nomembers
return _args
def gen_member_args(sudocmdgroup):
_args = {}
if sudocmdgroup is not None:
_args["member_sudocmdgroup"] = sudocmdgroup
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),
nomembers=dict(required=False, type='bool', default=None),
sudocmdgroup=dict(required=False, type='list', default=None),
sudocmd=dict(required=False, type='list', default=None),
action=dict(type="str", default="sudocmdgroup",
choices=["member", "sudocmdgroup"]),
# state
state=dict(type="str", default="present",
choices=["present", "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")
nomembers = ansible_module.params.get("nomembers")
sudocmdgroup = ansible_module.params.get("sudocmdgroup")
sudocmd = ansible_module.params.get("sudocmd")
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="Only one sudocmdgroup can be added at a time.")
if action == "member":
invalid = ["description", "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", "nomembers"]
if action == "sudocmdgroup":
invalid.extend(["sudocmd"])
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(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Make sure hostgroup exists
res_find = find_sudocmdgroup(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description, nomembers)
if action == "sudocmdgroup":
# Found the hostgroup
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, "sudocmdgroup_mod", args])
else:
commands.append([name, "sudocmdgroup_add", args])
# Set res_find to empty dict for next step
res_find = {}
member_args = gen_member_args(sudocmd)
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
sudocmdgroup_add = list(
set(sudocmdgroup or []) -
set(res_find.get("member_sudocmdgroup", [])))
sudocmdgroup_del = list(
set(res_find.get("member_sudocmdgroup", [])) -
set(sudocmdgroup or []))
# Add members
if len(sudocmdgroup_add) > 0:
commands.append([name, "sudocmdgroup_add_member",
{
"sudocmd": [to_text(c)
for c in
sudocmdgroup_add]
}
])
# Remove members
if len(sudocmdgroup_del) > 0:
commands.append([name,
"sudocmdgroup_remove_member",
{
"sudocmd": [to_text(c)
for c in
sudocmdgroup_del]
}
])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No sudocmdgroup '%s'" % name)
# Ensure members are present
commands.append([name, "sudocmdgroup_add_member",
{"sudocmd": [to_text(c) for c in sudocmd]}
])
elif state == "absent":
if action == "sudocmdgroup":
if res_find is not None:
commands.append([name, "sudocmdgroup_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No sudocmdgroup '%s'" % name)
# Ensure members are absent
commands.append([name, "sudocmdgroup_remove_member",
{"sudocmd": [to_text(c) for c in sudocmd]}
])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
for name, command, args in commands:
try:
result = api_command(ansible_module, command, to_text(name),
args)
if action == "member":
if "completed" in result and result["completed"] > 0:
changed = True
else:
if command == "sudocmdgroup_del":
changed |= "Deleted" in result['summary']
elif command == "sudocmdgroup_add":
changed |= "Added" in result['summary']
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
errors = []
if "failed" in result and "member" in result["failed"]:
failed = result["failed"]["member"]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" not in failure \
and "not a member" not in failure:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
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

@@ -0,0 +1,564 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman <rjeffman@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: ipasudorule
short description: Manage FreeIPA sudo rules
description: Manage FreeIPA sudo rules
options:
ipaadmin_principal:
description: The admin principal
default: admin
ipaadmin_password:
description: The admin password
required: false
name:
description: The sudorule name
required: true
aliases: ["cn"]
description:
description: The sudorule description
required: false
user:
description: List of users assigned to the sudo rule.
required: false
usercategory:
description: User category the sudo rule applies to
required: false
choices: ["all"]
usergroup:
description: List of user groups assigned to the sudo rule.
required: false
runasgroupcategory:
description: RunAs Group category applied to the sudo rule.
required: false
choices: ["all"]
runasusercategory:
description: RunAs User category applied to the sudorule.
required: false
choices: ["all"]
nomembers:
description: Suppress processing of membership attributes
required: false
type: bool
host:
description: List of host names assigned to this sudorule.
required: false
type: list
hostgroup:
description: List of host groups assigned to this sudorule.
required: false
type: list
hostcategory:
description: Host category the sudo rule applies to.
required: false
choices: ["all"]
cmd:
description: List of sudocmds assigned to this sudorule.
required: false
type: list
cmdgroup:
description: List of sudocmd groups assigned to this sudorule.
required: false
type: list
cmdcategory:
description: Cammand category the sudo rule applies to
required: false
choices: ["all"]
action:
description: Work on sudorule or member level
default: sudorule
choices: ["member", "sudorule"]
state:
description: State to ensure
default: present
choices: ["present", "absent", "enabled", "disabled"]
author:
- Rafael Jeffman
"""
EXAMPLES = """
# Ensure Sudo Rule tesrule1 is present
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
# Ensure sudocmd is present in Sudo Rule
- ipasudorule:
ipaadmin_password: pass1234
name: testrule1
cmd:
- /sbin/ifconfig
- /usr/bin/vim
action: member
state: absent
# Ensure host server is present in Sudo Rule
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
host: server
action: member
# Ensure hostgroup cluster is present in Sudo Rule
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
hostgroup: cluster
action: member
# Ensure sudo rule for usercategory "all"
- ipasudorule:
ipaadmin_password: MyPassword123
name: allusers
usercategory: all
action: enabled
# Ensure sudo rule for hostcategory "all"
- ipasudorule:
ipaadmin_password: MyPassword123
name: allhosts
hostcategory: all
action: enabled
# Ensure Sudo Rule tesrule1 is absent
- ipasudorule:
ipaadmin_password: MyPassword123
name: testrule1
state: absent
"""
RETURN = """
"""
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
temp_kdestroy, valid_creds, api_connect, api_command, compare_args_ipa, \
module_params_get
def find_sudorule(module, name):
_args = {
"all": True,
"cn": name,
}
_result = api_command(module, "sudorule_find", name, _args)
if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one sudorule '%s'" % (name))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def gen_args(ansible_module):
arglist = ['description', 'usercategory', 'hostcategory', 'cmdcategory',
'runasusercategory', 'runasgroupcategory', 'nomembers']
_args = {}
for arg in arglist:
value = module_params_get(ansible_module, arg)
if value is not None:
_args[arg] = value
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(required=False, type="str", default=None),
usercategory=dict(required=False, type="str", default=None,
choices=["all"]),
hostcategory=dict(required=False, type="str", default=None,
choices=["all"]),
nomembers=dict(required=False, type='bool', default=None),
host=dict(required=False, type='list', default=None),
hostgroup=dict(required=False, type='list', default=None),
user=dict(required=False, type='list', default=None),
group=dict(required=False, type='list', default=None),
cmd=dict(required=False, type="list", default=None),
cmdcategory=dict(required=False, type="str", default=None,
choices=["all"]),
runasusercategory=dict(required=False, type="str", default=None,
choices=["all"]),
runasgroupcategory=dict(required=False, type="str", default=None,
choices=["all"]),
action=dict(type="str", default="sudorule",
choices=["member", "sudorule"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent",
"enabled", "disabled"]),
),
supports_check_mode=True,
)
ansible_module._ansible_debug = True
# Get parameters
# general
ipaadmin_principal = module_params_get(ansible_module,
"ipaadmin_principal")
ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
names = module_params_get(ansible_module, "name")
# present
# The 'noqa' variables are not used here, but required for vars().
# The use of 'noqa' ensures flake8 does not complain about them.
description = module_params_get(ansible_module, "description") # noqa
cmdcategory = module_params_get(ansible_module, 'cmdcategory') # noqa
usercategory = module_params_get(ansible_module, "usercategory") # noqa
hostcategory = module_params_get(ansible_module, "hostcategory") # noqa
runasusercategory = module_params_get(ansible_module, # noqa
"runasusercategory")
runasgroupcategory = module_params_get(ansible_module, # noqa
"runasgroupcategory")
hostcategory = module_params_get(ansible_module, "hostcategory") # noqa
nomembers = module_params_get(ansible_module, "nomembers") # noqa
host = module_params_get(ansible_module, "host")
hostgroup = module_params_get(ansible_module, "hostgroup")
user = module_params_get(ansible_module, "user")
group = module_params_get(ansible_module, "group")
cmd = module_params_get(ansible_module, 'cmd')
cmdgroup = module_params_get(ansible_module, 'cmdgroup')
action = module_params_get(ansible_module, "action")
# state
state = module_params_get(ansible_module, "state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one sudorule can be added at a time.")
if action == "member":
invalid = ["description", "usercategory", "hostcategory",
"cmdcategory", "runasusercategory",
"runasgroupcategory", "nomembers"]
for x in invalid:
if x in vars() and vars()[x] is not None:
ansible_module.fail_json(
msg="Argument '%s' can not be used with action "
"'%s'" % (x, action))
elif state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "usercategory", "hostcategory",
"cmdcategory", "runasusercategory",
"runasgroupcategory", "nomembers"]
if action == "sudorule":
invalid.extend(["host", "hostgroup", "user", "group",
"cmd", "cmdgroup"])
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))
elif state in ["enabled", "disabled"]:
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
if action == "member":
ansible_module.fail_json(
msg="Action member can not be used with states enabled and "
"disabled")
invalid = ["description", "usercategory", "hostcategory",
"cmdcategory", "runasusercategory", "runasgroupcategory",
"nomembers", "nomembers", "host", "hostgroup",
"user", "group", "cmd", "cmdgroup"]
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))
else:
ansible_module.fail_json(msg="Invalid state '%s'" % state)
# Init
changed = False
exit_args = {}
ccache_dir = None
ccache_name = None
try:
if not valid_creds(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
commands = []
for name in names:
# Make sure sudorule exists
res_find = find_sudorule(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(ansible_module)
if action == "sudorule":
# Found the sudorule
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, "sudorule_mod", args])
else:
commands.append([name, "sudorule_add", args])
# Set res_find to empty dict for next step
res_find = {}
# Generate addition and removal lists
host_add = list(
set(host or []) -
set(res_find.get("member_host", [])))
host_del = list(
set(res_find.get("member_host", [])) -
set(host or []))
hostgroup_add = list(
set(hostgroup or []) -
set(res_find.get("member_hostgroup", [])))
hostgroup_del = list(
set(res_find.get("member_hostgroup", [])) -
set(hostgroup or []))
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 []))
cmd_add = list(
set(cmd or []) -
set(res_find.get("member_cmd", [])))
cmd_del = list(
set(res_find.get("member_cmd", [])) -
set(cmd or []))
cmdgroup_add = list(
set(cmdgroup or []) -
set(res_find.get("member_cmdgroup", [])))
cmdgroup_del = list(
set(res_find.get("member_cmdgroup", [])) -
set(cmdgroup or []))
# Add hosts and hostgroups
if len(host_add) > 0 or len(hostgroup_add) > 0:
commands.append([name, "sudorule_add_host",
{
"host": host_add,
"hostgroup": hostgroup_add,
}])
# Remove hosts and hostgroups
if len(host_del) > 0 or len(hostgroup_del) > 0:
commands.append([name, "sudorule_remove_host",
{
"host": host_del,
"hostgroup": hostgroup_del,
}])
# Add users and groups
if len(user_add) > 0 or len(group_add) > 0:
commands.append([name, "sudorule_add_user",
{
"user": user_add,
"group": group_add,
}])
# Remove users and groups
if len(user_del) > 0 or len(group_del) > 0:
commands.append([name, "sudorule_remove_user",
{
"user": user_del,
"group": group_del,
}])
# Add commands
if len(cmd_add) > 0 or len(cmdgroup_add) > 0:
commands.append([name, "sudorule_add_allow_command",
{
"sudocmd": cmd_add,
"sudocmdgroup": cmdgroup_add,
}])
if len(cmd_del) > 0 or len(cmdgroup_del) > 0:
commands.append([name, "sudorule_add_deny_command",
{
"sudocmd": cmd_del,
"sudocmdgroup": cmdgroup_del
}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No sudorule '%s'" % name)
# Add hosts and hostgroups
if host is not None or hostgroup is not None:
commands.append([name, "sudorule_add_host",
{
"host": host,
"hostgroup": hostgroup,
}])
# Add users and groups
if user is not None or group is not None:
commands.append([name, "sudorule_add_user",
{
"user": user,
"group": group,
}])
# Add commands
if cmd is not None:
commands.append([name, "sudorule_add_allow_command",
{
"sudocmd": cmd,
}])
elif state == "absent":
if action == "sudorule":
if res_find is not None:
commands.append([name, "sudorule_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(msg="No sudorule '%s'" % name)
# Remove hosts and hostgroups
if host is not None or hostgroup is not None:
commands.append([name, "sudorule_remove_host",
{
"host": host,
"hostgroup": hostgroup,
}])
# Remove users and groups
if user is not None or group is not None:
commands.append([name, "sudorule_remove_user",
{
"user": user,
"group": group,
}])
# Remove commands
if cmd is not None:
commands.append([name, "sudorule_add_deny_command",
{
"sudocmd": cmd,
}])
elif state == "enabled":
if res_find is None:
ansible_module.fail_json(msg="No sudorule '%s'" % name)
# sudorule_enable is not failing on an enabled sudorule
# Therefore it is needed to have a look at the ipaenabledflag
# in res_find.
if "ipaenabledflag" not in res_find or \
res_find["ipaenabledflag"][0] != "TRUE":
commands.append([name, "sudorule_enable", {}])
elif state == "disabled":
if res_find is None:
ansible_module.fail_json(msg="No sudorule '%s'" % name)
# sudorule_disable is not failing on an disabled sudorule
# Therefore it is needed to have a look at the ipaenabledflag
# in res_find.
if "ipaenabledflag" not in res_find or \
res_find["ipaenabledflag"][0] != "FALSE":
commands.append([name, "sudorule_disable", {}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute commands
errors = []
for name, command, args in commands:
try:
result = api_command(ansible_module, command, name,
args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
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

@@ -217,7 +217,7 @@ def main():
ccache_dir = None
ccache_name = None
try:
if not valid_creds(ipaadmin_principal):
if not valid_creds(ansible_module, ipaadmin_principal):
ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
ipaadmin_password)
api_connect()
@@ -256,12 +256,12 @@ def main():
del args[key]
if len(args) > 1:
# cn needs to be in args always
commands.append(["topologysegment_mod", args])
commands.append(["topologysegment_mod", args, suffix])
# else: Nothing to change
else:
if name is None:
args["cn"] = to_text("%s-to-%s" % (left, right))
commands.append(["topologysegment_add", args])
commands.append(["topologysegment_add", args, suffix])
elif state in ["absent", "disabled"]:
# Make sure topology segment does not exist
@@ -274,7 +274,7 @@ def main():
args = {
"cn": res_find["cn"][0]
}
commands.append(["topologysegment_del", args])
commands.append(["topologysegment_del", args, suffix])
elif state == "checked":
# Check if topology segment does exists
@@ -309,14 +309,27 @@ def main():
elif direction == "right-to-left":
args["right"] = True
commands.append(["topologysegment_reinitialize", args])
commands.append(["topologysegment_reinitialize", args,
suffix])
else:
params = []
if name is not None:
params.append("name=%s" % name)
if left is not None:
params.append("left=%s" % left)
if right is not None:
params.append("right=%s" % right)
ansible_module.fail_json(
msg="No entry '%s' for suffix '%s'" %
(",".join(params), suffix))
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Execute command
for command, args in commands:
api_command(ansible_module, command, to_text(suffix), args)
for command, args, _suffix in commands:
api_command(ansible_module, command, to_text(_suffix), args)
changed = True
except Exception as e:

File diff suppressed because it is too large Load Diff

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