From 94b1f25b377800ce89f1b14d4e71dc16a825a9e0 Mon Sep 17 00:00:00 2001 From: Thomas Woerner Date: Mon, 2 Dec 2019 14:02:59 +0100 Subject: [PATCH] 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 --- README-host.md | 140 ++- playbooks/host/add-host.yml | 21 +- ...host-member-allow_create_keytab-absent.yml | 24 + ...ost-member-allow_create_keytab-present.yml | 23 + ...st-member-allow_retrieve_keytab-absent.yml | 24 + ...t-member-allow_retrieve_keytab-present.yml | 23 + .../host/host-member-certificate-absent.yml | 13 + .../host/host-member-certificate-present.yml | 12 + .../host-member-managedby_host-absent.yml | 12 + .../host-member-managedby_host-present.yml | 11 + .../host/host-member-principal-absent.yml | 15 + .../host/host-member-principal-present.yml | 14 + .../host-present-with-allow_create_keytab.yml | 23 + ...ost-present-with-allow_retrieve_keytab.yml | 23 + .../host/host-present-with-certificate.yml | 12 + .../host/host-present-with-managedby_host.yml | 11 + .../host/host-present-with-principal.yml | 14 + .../host/host-present-with-randompassword.yml | 17 + playbooks/host/host-present.yml | 20 + .../host/hosts-member-certificate-absent.yml | 18 + .../host/hosts-member-certificate-present.yml | 17 + .../hosts-member-managedby_host-absent.yml | 15 + .../hosts-member-managedby_host-present.yml | 14 + .../host/hosts-member-principal-absent.yml | 18 + .../host/hosts-member-principal-present.yml | 17 + .../host/hosts-present-with-certificate.yml | 17 + .../hosts-present-with-managedby_host.yml | 15 + .../hosts-present-with-randompasswords.yml | 26 + .../module_utils/ansible_freeipa_module.py | 30 + plugins/modules/ipahost.py | 1064 +++++++++++++++-- tests/host/certificate/cert1.der | Bin 0 -> 771 bytes tests/host/certificate/cert1.pem | 19 + tests/host/certificate/cert2.der | Bin 0 -> 771 bytes tests/host/certificate/cert2.pem | 19 + tests/host/certificate/cert3.der | Bin 0 -> 771 bytes tests/host/certificate/cert3.pem | 19 + tests/host/certificate/private1.key | 28 + tests/host/certificate/private2.key | 28 + tests/host/certificate/private3.key | 28 + .../certificate/test_host_certificate.yml | 110 ++ .../certificate/test_hosts_certificate.yml | 109 ++ tests/host/test_host.yml | 218 ++++ tests/host/test_host_allow_create_keytab.yml | 278 +++++ .../host/test_host_allow_retrieve_keytab.yml | 278 +++++ tests/host/test_host_managedby_host.yml | 125 ++ tests/host/test_host_principal.yml | 130 ++ tests/host/test_host_random.yml | 61 +- tests/host/test_hosts.yml | 98 ++ tests/host/test_hosts_managedby_host.yml | 151 +++ tests/host/test_hosts_principal.yml | 179 +++ 50 files changed, 3435 insertions(+), 146 deletions(-) mode change 100644 => 120000 playbooks/host/add-host.yml create mode 100644 playbooks/host/host-member-allow_create_keytab-absent.yml create mode 100644 playbooks/host/host-member-allow_create_keytab-present.yml create mode 100644 playbooks/host/host-member-allow_retrieve_keytab-absent.yml create mode 100644 playbooks/host/host-member-allow_retrieve_keytab-present.yml create mode 100644 playbooks/host/host-member-certificate-absent.yml create mode 100644 playbooks/host/host-member-certificate-present.yml create mode 100644 playbooks/host/host-member-managedby_host-absent.yml create mode 100644 playbooks/host/host-member-managedby_host-present.yml create mode 100644 playbooks/host/host-member-principal-absent.yml create mode 100644 playbooks/host/host-member-principal-present.yml create mode 100644 playbooks/host/host-present-with-allow_create_keytab.yml create mode 100644 playbooks/host/host-present-with-allow_retrieve_keytab.yml create mode 100644 playbooks/host/host-present-with-certificate.yml create mode 100644 playbooks/host/host-present-with-managedby_host.yml create mode 100644 playbooks/host/host-present-with-principal.yml create mode 100644 playbooks/host/host-present-with-randompassword.yml create mode 100644 playbooks/host/host-present.yml create mode 100644 playbooks/host/hosts-member-certificate-absent.yml create mode 100644 playbooks/host/hosts-member-certificate-present.yml create mode 100644 playbooks/host/hosts-member-managedby_host-absent.yml create mode 100644 playbooks/host/hosts-member-managedby_host-present.yml create mode 100644 playbooks/host/hosts-member-principal-absent.yml create mode 100644 playbooks/host/hosts-member-principal-present.yml create mode 100644 playbooks/host/hosts-present-with-certificate.yml create mode 100644 playbooks/host/hosts-present-with-managedby_host.yml create mode 100644 playbooks/host/hosts-present-with-randompasswords.yml create mode 100644 tests/host/certificate/cert1.der create mode 100644 tests/host/certificate/cert1.pem create mode 100644 tests/host/certificate/cert2.der create mode 100644 tests/host/certificate/cert2.pem create mode 100644 tests/host/certificate/cert3.der create mode 100644 tests/host/certificate/cert3.pem create mode 100644 tests/host/certificate/private1.key create mode 100644 tests/host/certificate/private2.key create mode 100644 tests/host/certificate/private3.key create mode 100644 tests/host/certificate/test_host_certificate.yml create mode 100644 tests/host/certificate/test_hosts_certificate.yml create mode 100644 tests/host/test_host.yml create mode 100644 tests/host/test_host_allow_create_keytab.yml create mode 100644 tests/host/test_host_allow_retrieve_keytab.yml create mode 100644 tests/host/test_host_managedby_host.yml create mode 100644 tests/host/test_host_principal.yml create mode 100644 tests/host/test_hosts.yml create mode 100644 tests/host/test_hosts_managedby_host.yml create mode 100644 tests/host/test_hosts_principal.yml diff --git a/README-host.md b/README-host.md index 7ff7afa7..77ca098d 100644 --- a/README-host.md +++ b/README-host.md @@ -41,7 +41,7 @@ ipaserver.test.local ``` -Example playbook to add hosts: +Example playbook to ensure host presence: ```yaml --- @@ -67,7 +67,7 @@ Example playbook to add hosts: ``` -Example playbook to create host without DNS: +Example playbook to ensure host presence without DNS: ```yaml --- @@ -85,28 +85,118 @@ Example playbook to create host without DNS: ``` -Example playbook to initiate the generation of a random password to be used in bulk enrollment: +Example playbook to ensure host presence with a random password: ```yaml --- -- name: Playbook to handle hosts +- name: Ensure host with random password hosts: ipaserver become: true tasks: - # Generate a random password for bulk enrollment - - ipahost: + - name: Host host01.example.com present with random password + ipahost: ipaadmin_password: MyPassword123 name: host01.example.com - description: Example host - ip_address: 192.168.0.123 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: @@ -155,7 +245,20 @@ 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. | yes +`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**.
There is one required option in the `hosts` dict:| no +  | `name` \| `fqdn` - The user name string of the entry. | yes +  | **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 @@ -163,13 +266,28 @@ Variable | Description | Required `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.
Options: | no +`allow_create_keytab_group` \| `ipaallowedtoperform_write_keys_group` | Groups allowed to create a keytab of this host.
Options: | no +`allow_create_keytab_host` \| `ipaallowedtoperform_write_keys_host` | Hosts allowed to create a keytab of this host.
Options: | no +`allow_create_keytab_hostgroup` \| `ipaallowedtoperform_write_keys_hostgroup` | Host groups allowed to create a keytab of this host.
Options: | no +`allow_retrieve_keytab_user` \| `ipaallowedtoperform_read_keys_user` | Users allowed to retieve a keytab of this host.
Options: | no +`allow_retrieve_keytab_group` \| `ipaallowedtoperform_read_keys_group` | Groups allowed to retieve a keytab of this host.
Options: | no +`allow_retrieve_keytab_host` \| `ipaallowedtoperform_read_keys_host` | Hosts allowed to retieve a keytab of this host.
Options: | no +`allow_retrieve_keytab_hostgroup` \| `ipaallowedtoperform_read_keys_hostgroup` | Host groups allowed to retieve a keytab of this host.
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 -`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 -`state` | The state to ensure. It can be one of `present`, `absent` or `disabled`, default: `present`. | yes Return Values diff --git a/playbooks/host/add-host.yml b/playbooks/host/add-host.yml deleted file mode 100644 index 61b8a958..00000000 --- a/playbooks/host/add-host.yml +++ /dev/null @@ -1,20 +0,0 @@ ---- -- name: Playbook to handle hosts - 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 diff --git a/playbooks/host/add-host.yml b/playbooks/host/add-host.yml new file mode 120000 index 00000000..6d5bc9a9 --- /dev/null +++ b/playbooks/host/add-host.yml @@ -0,0 +1 @@ +host-present.yml \ No newline at end of file diff --git a/playbooks/host/host-member-allow_create_keytab-absent.yml b/playbooks/host/host-member-allow_create_keytab-absent.yml new file mode 100644 index 00000000..55e3110d --- /dev/null +++ b/playbooks/host/host-member-allow_create_keytab-absent.yml @@ -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 diff --git a/playbooks/host/host-member-allow_create_keytab-present.yml b/playbooks/host/host-member-allow_create_keytab-present.yml new file mode 100644 index 00000000..f5865497 --- /dev/null +++ b/playbooks/host/host-member-allow_create_keytab-present.yml @@ -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 diff --git a/playbooks/host/host-member-allow_retrieve_keytab-absent.yml b/playbooks/host/host-member-allow_retrieve_keytab-absent.yml new file mode 100644 index 00000000..b8830f60 --- /dev/null +++ b/playbooks/host/host-member-allow_retrieve_keytab-absent.yml @@ -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 diff --git a/playbooks/host/host-member-allow_retrieve_keytab-present.yml b/playbooks/host/host-member-allow_retrieve_keytab-present.yml new file mode 100644 index 00000000..fde116cc --- /dev/null +++ b/playbooks/host/host-member-allow_retrieve_keytab-present.yml @@ -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 diff --git a/playbooks/host/host-member-certificate-absent.yml b/playbooks/host/host-member-certificate-absent.yml new file mode 100644 index 00000000..918951f8 --- /dev/null +++ b/playbooks/host/host-member-certificate-absent.yml @@ -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 diff --git a/playbooks/host/host-member-certificate-present.yml b/playbooks/host/host-member-certificate-present.yml new file mode 100644 index 00000000..066ae0a9 --- /dev/null +++ b/playbooks/host/host-member-certificate-present.yml @@ -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 diff --git a/playbooks/host/host-member-managedby_host-absent.yml b/playbooks/host/host-member-managedby_host-absent.yml new file mode 100644 index 00000000..f899a52f --- /dev/null +++ b/playbooks/host/host-member-managedby_host-absent.yml @@ -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 diff --git a/playbooks/host/host-member-managedby_host-present.yml b/playbooks/host/host-member-managedby_host-present.yml new file mode 100644 index 00000000..073d81ad --- /dev/null +++ b/playbooks/host/host-member-managedby_host-present.yml @@ -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 diff --git a/playbooks/host/host-member-principal-absent.yml b/playbooks/host/host-member-principal-absent.yml new file mode 100644 index 00000000..b2c3a8d8 --- /dev/null +++ b/playbooks/host/host-member-principal-absent.yml @@ -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 diff --git a/playbooks/host/host-member-principal-present.yml b/playbooks/host/host-member-principal-present.yml new file mode 100644 index 00000000..b56fd591 --- /dev/null +++ b/playbooks/host/host-member-principal-present.yml @@ -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 diff --git a/playbooks/host/host-present-with-allow_create_keytab.yml b/playbooks/host/host-present-with-allow_create_keytab.yml new file mode 100644 index 00000000..f7b9c6f4 --- /dev/null +++ b/playbooks/host/host-present-with-allow_create_keytab.yml @@ -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 diff --git a/playbooks/host/host-present-with-allow_retrieve_keytab.yml b/playbooks/host/host-present-with-allow_retrieve_keytab.yml new file mode 100644 index 00000000..5a9f3af5 --- /dev/null +++ b/playbooks/host/host-present-with-allow_retrieve_keytab.yml @@ -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 diff --git a/playbooks/host/host-present-with-certificate.yml b/playbooks/host/host-present-with-certificate.yml new file mode 100644 index 00000000..f5da46d7 --- /dev/null +++ b/playbooks/host/host-present-with-certificate.yml @@ -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 diff --git a/playbooks/host/host-present-with-managedby_host.yml b/playbooks/host/host-present-with-managedby_host.yml new file mode 100644 index 00000000..b85f5e60 --- /dev/null +++ b/playbooks/host/host-present-with-managedby_host.yml @@ -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 diff --git a/playbooks/host/host-present-with-principal.yml b/playbooks/host/host-present-with-principal.yml new file mode 100644 index 00000000..5b8ad4ee --- /dev/null +++ b/playbooks/host/host-present-with-principal.yml @@ -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 diff --git a/playbooks/host/host-present-with-randompassword.yml b/playbooks/host/host-present-with-randompassword.yml new file mode 100644 index 00000000..9063c480 --- /dev/null +++ b/playbooks/host/host-present-with-randompassword.yml @@ -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 diff --git a/playbooks/host/host-present.yml b/playbooks/host/host-present.yml new file mode 100644 index 00000000..d40c1ecf --- /dev/null +++ b/playbooks/host/host-present.yml @@ -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 diff --git a/playbooks/host/hosts-member-certificate-absent.yml b/playbooks/host/hosts-member-certificate-absent.yml new file mode 100644 index 00000000..bb2d5b03 --- /dev/null +++ b/playbooks/host/hosts-member-certificate-absent.yml @@ -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 diff --git a/playbooks/host/hosts-member-certificate-present.yml b/playbooks/host/hosts-member-certificate-present.yml new file mode 100644 index 00000000..c402ef4a --- /dev/null +++ b/playbooks/host/hosts-member-certificate-present.yml @@ -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 diff --git a/playbooks/host/hosts-member-managedby_host-absent.yml b/playbooks/host/hosts-member-managedby_host-absent.yml new file mode 100644 index 00000000..9b584e51 --- /dev/null +++ b/playbooks/host/hosts-member-managedby_host-absent.yml @@ -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 diff --git a/playbooks/host/hosts-member-managedby_host-present.yml b/playbooks/host/hosts-member-managedby_host-present.yml new file mode 100644 index 00000000..f8d4e2b7 --- /dev/null +++ b/playbooks/host/hosts-member-managedby_host-present.yml @@ -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 diff --git a/playbooks/host/hosts-member-principal-absent.yml b/playbooks/host/hosts-member-principal-absent.yml new file mode 100644 index 00000000..edd33521 --- /dev/null +++ b/playbooks/host/hosts-member-principal-absent.yml @@ -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 diff --git a/playbooks/host/hosts-member-principal-present.yml b/playbooks/host/hosts-member-principal-present.yml new file mode 100644 index 00000000..54c9a8f6 --- /dev/null +++ b/playbooks/host/hosts-member-principal-present.yml @@ -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 diff --git a/playbooks/host/hosts-present-with-certificate.yml b/playbooks/host/hosts-present-with-certificate.yml new file mode 100644 index 00000000..34e402f7 --- /dev/null +++ b/playbooks/host/hosts-present-with-certificate.yml @@ -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 diff --git a/playbooks/host/hosts-present-with-managedby_host.yml b/playbooks/host/hosts-present-with-managedby_host.yml new file mode 100644 index 00000000..5f3546b6 --- /dev/null +++ b/playbooks/host/hosts-present-with-managedby_host.yml @@ -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 diff --git a/playbooks/host/hosts-present-with-randompasswords.yml b/playbooks/host/hosts-present-with-randompasswords.yml new file mode 100644 index 00000000..f747ca31 --- /dev/null +++ b/playbooks/host/hosts-present-with-randompasswords.yml @@ -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 + diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py index 7977a8ea..6a3e771e 100644 --- a/plugins/module_utils/ansible_freeipa_module.py +++ b/plugins/module_utils/ansible_freeipa_module.py @@ -38,6 +38,11 @@ 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 @@ -236,3 +241,28 @@ def module_params_get(module, 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 diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py index 4a240bdb..ec5e1963 100644 --- a/plugins/modules/ipahost.py +++ b/plugins/modules/ipahost.py @@ -42,6 +42,145 @@ options: description: The full qualified domain name. aliases: ["fqdn"] required: true + + hosts: + description: The list of user host dicts + required: false + options: + name: + description: The host (internally uid). + aliases: ["fqdn"] + required: true + description: + description: The host description + required: false + locality: + description: Host locality (e.g. "Baltimore, MD") + required: false + location: + description: Host location (e.g. "Lab 2") + aliases: ["ns_host_location"] + required: false + platform: + description: Host hardware platform (e.g. "Lenovo T61") + aliases: ["ns_hardware_platform"] + required: false + os: + description: Host operating system and version (e.g. "Fedora 9") + aliases: ["ns_os_version"] + required: false + password: + description: Password used in bulk enrollment + aliases: ["user_password", "userpassword"] + required: false + random: + description: + Initiate the generation of a random password to be used in bulk + enrollment + aliases: ["random_password"] + required: false + certificate: + description: List of base-64 encoded host certificates + type: list + aliases: ["usercertificate"] + required: false + managedby_host: + description: List of hosts that can manage this host + type: list + aliases: ["principalname", "krbprincipalname"] + required: false + principal: + description: List of principal aliases for this host + type: list + aliases: ["principalname", "krbprincipalname"] + required: false + allow_create_keytab_user: + description: Users allowed to create a keytab of this host + aliases: ["ipaallowedtoperform_write_keys_user"] + required: false + allow_create_keytab_group: + description: Groups allowed to create a keytab of this host + aliases: ["ipaallowedtoperform_write_keys_group"] + required: false + allow_create_keytab_host: + description: Hosts allowed to create a keytab of this host + aliases: ["ipaallowedtoperform_write_keys_host"] + required: false + allow_create_keytab_hostgroup: + description: Hostgroups allowed to create a keytab of this host + aliases: ["ipaallowedtoperform_write_keys_hostgroup"] + required: false + allow_retrieve_keytab_user: + description: Users allowed to retrieve a keytab of this host + aliases: ["ipaallowedtoperform_read_keys_user"] + required: false + allow_retrieve_keytab_group: + description: Groups allowed to retrieve a keytab of this host + aliases: ["ipaallowedtoperform_read_keys_group"] + required: false + allow_retrieve_keytab_host: + description: Hosts allowed to retrieve a keytab of this host + aliases: ["ipaallowedtoperform_read_keys_host"] + required: false + allow_retrieve_keytab_hostgroup: + description: Hostgroups allowed to retrieve a keytab of this host + aliases: ["ipaallowedtoperform_read_keys_hostgroup"] + required: false + mac_address: + description: List of hardware MAC addresses. + type: list + aliases: ["macaddress"] + required: false + sshpubkey: + description: List of SSH public keys + type: list + aliases: ["ipasshpubkey"] + required: false + userclass: + description: + Host category (semantics placed on this attribute are for local + interpretation) + aliases: ["class"] + required: false + auth_ind: + description: + 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. + type: list + aliases: ["krbprincipalauthind"] + choices: ["radius", "otp", "pkinit", "hardened"] + required: false + requires_pre_auth: + description: Pre-authentication is required for the service + type: bool + aliases: ["ipakrbrequirespreauth"] + required: false + ok_as_delegate: + description: Client credentials may be delegated to the service + type: bool + aliases: ["ipakrbokasdelegate"] + required: false + ok_to_auth_as_delegate: + description: + The service is allowed to authenticate on behalf of a client + type: bool + aliases: ["ipakrboktoauthasdelegate"] + required: false + force: + description: Force host name even if not in DNS + required: false + reverse: + description: Reverse DNS detection + default: true + required: false + ip_address: + description: The host IP address + aliases: ["ipaddress"] + required: false + update_dns: + description: Update DNS entries + required: false description: description: The host description required: false @@ -70,11 +209,93 @@ options: enrollment aliases: ["random_password"] required: false + certificate: + description: List of base-64 encoded host certificates + type: list + aliases: ["usercertificate"] + required: false + managedby_host: + description: List of hosts that can manage this host + type: list + aliases: ["principalname", "krbprincipalname"] + required: false + principal: + description: List of principal aliases for this host + type: list + aliases: ["principalname", "krbprincipalname"] + required: false + allow_create_keytab_user: + description: Users allowed to create a keytab of this host + aliases: ["ipaallowedtoperform_write_keys_user"] + required: false + allow_create_keytab_group: + description: Groups allowed to create a keytab of this host + aliases: ["ipaallowedtoperform_write_keys_group"] + required: false + allow_create_keytab_host: + description: Hosts allowed to create a keytab of this host + aliases: ["ipaallowedtoperform_write_keys_host"] + required: false + allow_create_keytab_hostgroup: + description: Hostgroups allowed to create a keytab of this host + aliases: ["ipaallowedtoperform_write_keys_hostgroup"] + required: false + allow_retrieve_keytab_user: + description: Users allowed to retrieve a keytab of this host + aliases: ["ipaallowedtoperform_read_keys_user"] + required: false + allow_retrieve_keytab_group: + description: Groups allowed to retrieve a keytab of this host + aliases: ["ipaallowedtoperform_read_keys_group"] + required: false + allow_retrieve_keytab_host: + description: Hosts allowed to retrieve a keytab of this host + aliases: ["ipaallowedtoperform_read_keys_host"] + required: false + allow_retrieve_keytab_hostgroup: + description: Hostgroups allowed to retrieve a keytab of this host + aliases: ["ipaallowedtoperform_read_keys_hostgroup"] + required: false mac_address: description: List of hardware MAC addresses. type: list aliases: ["macaddress"] required: false + sshpubkey: + description: List of SSH public keys + type: list + aliases: ["ipasshpubkey"] + required: false + userclass: + description: + Host category (semantics placed on this attribute are for local + interpretation) + aliases: ["class"] + required: false + auth_ind: + description: + 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. + type: list + aliases: ["krbprincipalauthind"] + choices: ["radius", "otp", "pkinit", "hardened"] + required: false + requires_pre_auth: + description: Pre-authentication is required for the service + type: bool + aliases: ["ipakrbrequirespreauth"] + required: false + ok_as_delegate: + description: Client credentials may be delegated to the service + type: bool + aliases: ["ipakrbokasdelegate"] + required: false + ok_to_auth_as_delegate: + description: The service is allowed to authenticate on behalf of a client + type: bool + aliases: ["ipakrboktoauthasdelegate"] + required: false force: description: Force host name even if not in DNS required: false @@ -94,6 +315,10 @@ options: Set password for a host in present state only on creation or always default: 'always' choices: ["always", "on_create"] + action: + description: Work on host or member level + default: "host" + choices: ["member", "host"] state: description: State to ensure default: present @@ -170,7 +395,13 @@ host: 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, \ + module_params_get, gen_add_del_lists, encode_certificate, api_get_realm +import six + + +if six.PY3: + unicode = str def find_host(module, name): @@ -185,7 +416,12 @@ def find_host(module, name): module.fail_json( msg="There is more than one host '%s'" % (name)) elif len(_result["result"]) == 1: - return _result["result"][0] + _res = _result["result"][0] + certs = _res.get("usercertificate") + if certs is not None: + _res["usercertificate"] = [encode_certificate(cert) for + cert in certs] + return _res else: return None @@ -195,13 +431,15 @@ def show_host(module, name): return _result["result"] -def gen_args(description, force, locality, location, platform, os, password, - random, mac_address, ip_address, update_dns, reverse): +def gen_args(description, locality, location, platform, os, password, random, + mac_address, sshpubkey, userclass, auth_ind, requires_pre_auth, + ok_as_delegate, ok_to_auth_as_delegate, force, reverse, + ip_address, update_dns): + # certificate, managedby_host, principal, create_keytab_* and + # allow_retrieve_keytab_* are not handled here _args = {} if description is not None: _args["description"] = description - if force is not None: - _args["force"] = force if locality is not None: _args["l"] = locality if location is not None: @@ -216,17 +454,162 @@ def gen_args(description, force, locality, location, platform, os, password, _args["random"] = random if mac_address is not None: _args["macaddress"] = mac_address + if sshpubkey is not None: + _args["ipasshpubkey"] = sshpubkey + if userclass is not None: + _args["userclass"] = userclass + if auth_ind is not None: + _args["krbprincipalauthind"] = auth_ind + if requires_pre_auth is not None: + _args["ipakrbrequirespreauth"] = requires_pre_auth + if ok_as_delegate is not None: + _args["ipakrbokasdelegate"] = ok_as_delegate + if ok_to_auth_as_delegate is not None: + _args["ipakrboktoauthasdelegate"] = ok_to_auth_as_delegate + if force is not None: + _args["force"] = force + if reverse is not None: + _args["no_reverse"] = not reverse if ip_address is not None: _args["ip_address"] = ip_address if update_dns is not None: _args["updatedns"] = update_dns - if reverse is not None: - _args["no_reverse"] = not reverse return _args +def check_parameters( + module, state, action, + description, locality, location, platform, os, password, random, + certificate, managedby_host, principal, allow_create_keytab_user, + allow_create_keytab_group, allow_create_keytab_host, + allow_create_keytab_hostgroup, allow_retrieve_keytab_user, + allow_retrieve_keytab_group, allow_retrieve_keytab_host, + allow_retrieve_keytab_hostgroup, mac_address, sshpubkey, + userclass, auth_ind, requires_pre_auth, ok_as_delegate, + ok_to_auth_as_delegate, force, reverse, ip_address, update_dns, + update_password): + if state == "present": + if action == "member": + # certificate, managedby_host, principal, + # allow_create_keytab_*, allow_retrieve_keytab_*, + invalid = ["description", "locality", "location", "platform", + "os", "password", "random", "mac_address", "sshpubkey", + "userclass", "auth_ind", "requires_pre_auth", + "ok_as_delegate", "ok_to_auth_as_delegate", "force", + "reverse", "ip_address", "update_dns", + "update_password"] + for x in invalid: + if vars()[x] is not None: + module.fail_json( + msg="Argument '%s' can not be used with action " + "'%s'" % (x, action)) + + if state == "absent": + invalid = ["description", "locality", "location", "platform", "os", + "password", "random", "mac_address", "sshpubkey", + "userclass", "auth_ind", "requires_pre_auth", + "ok_as_delegate", "ok_to_auth_as_delegate", "force", + "reverse", "ip_address", "update_password"] + if action == "host": + invalid.extend([ + "certificate", "managedby_host", "principal", + "allow_create_keytab_user", "allow_create_keytab_group", + "allow_create_keytab_host", "allow_create_keytab_hostgroup", + "allow_retrieve_keytab_user", "allow_retrieve_keytab_group", + "allow_retrieve_keytab_host", + "allow_retrieve_keytab_hostgroup"]) + for x in invalid: + if vars()[x] is not None: + module.fail_json( + msg="Argument '%s' can not be used with state '%s'" % + (x, state)) + + def main(): + host_spec = dict( + # present + description=dict(type="str", default=None), + locality=dict(type="str", default=None), + location=dict(type="str", aliases=["ns_host_location"], + default=None), + platform=dict(type="str", aliases=["ns_hardware_platform"], + default=None), + os=dict(type="str", aliases=["ns_os_version"], default=None), + password=dict(type="str", + aliases=["user_password", "userpassword"], + default=None, no_log=True), + random=dict(type="bool", aliases=["random_password"], + default=None), + + + + certificate=dict(type="list", aliases=["usercertificate"], + default=None), + managedby_host=dict(type="list", + default=None), + principal=dict(type="list", aliases=["krbprincipalname"], + default=None), + allow_create_keytab_user=dict( + type="list", + aliases=["ipaallowedtoperform_write_keys_user"], + default=None), + allow_create_keytab_group=dict( + type="list", + aliases=["ipaallowedtoperform_write_keys_group"], + default=None), + allow_create_keytab_host=dict( + type="list", + aliases=["ipaallowedtoperform_write_keys_host"], + default=None), + allow_create_keytab_hostgroup=dict( + type="list", + aliases=["ipaallowedtoperform_write_keys_hostgroup"], + default=None), + allow_retrieve_keytab_user=dict( + type="list", + aliases=["ipaallowedtoperform_write_keys_user"], + default=None), + allow_retrieve_keytab_group=dict( + type="list", + aliases=["ipaallowedtoperform_write_keys_group"], + default=None), + allow_retrieve_keytab_host=dict( + type="list", + aliases=["ipaallowedtoperform_write_keys_host"], + default=None), + allow_retrieve_keytab_hostgroup=dict( + type="list", + aliases=["ipaallowedtoperform_write_keys_hostgroup"], + default=None), + mac_address=dict(type="list", aliases=["macaddress"], + default=None), + sshpubkey=dict(type="str", aliases=["ipasshpubkey"], + default=None), + userclass=dict(type="list", aliases=["class"], + default=None), + auth_ind=dict(type='list', aliases=["krbprincipalauthind"], + default=None, + choices=['password', 'radius', 'otp']), + requires_pre_auth=dict(type="bool", aliases=["ipakrbrequirespreauth"], + default=None), + ok_as_delegate=dict(type="bool", aliases=["ipakrbokasdelegate"], + default=None), + ok_to_auth_as_delegate=dict(type="bool", + aliases=["ipakrboktoauthasdelegate"], + default=None), + force=dict(type='bool', default=None), + reverse=dict(type='bool', default=None), + ip_address=dict(type="str", aliases=["ipaddress"], + default=None), + update_dns=dict(type="bool", aliases=["updatedns"], + default=None), + # no_members + + # for update: + # krbprincipalname + ) + ansible_module = AnsibleModule( argument_spec=dict( # general @@ -234,51 +617,33 @@ def main(): ipaadmin_password=dict(type="str", no_log=True), name=dict(type="list", aliases=["fqdn"], default=None, - required=True), - # present - description=dict(type="str", default=None), - locality=dict(type="str", default=None), - location=dict(type="str", aliases=["ns_host_location"], - default=None), - platform=dict(type="str", aliases=["ns_hardware_platform"], - default=None), - os=dict(type="str", aliases=["ns_os_version"], default=None), - password=dict(type="str", - aliases=["user_password", "userpassword"], - default=None, no_log=True), - random=dict(type="bool", aliases=["random_password"], - default=None), - # certificate (usercertificate) - mac_address=dict(type="list", aliases=["macaddress"], - default=None), - # sshpubkey=dict(type="str", aliases=["ipasshpubkey"], - # default=None), - # class - # auth_ind - # requires_pre_auth - # ok_as_delegate - # ok_to_auth_as_delegate - force=dict(type='bool', default=None), - reverse=dict(type='bool', default=True), - ip_address=dict(type="str", aliases=["ipaddress"], - default=None), - # no_members + required=False), - # for update: - # krbprincipalname - update_dns=dict(type="bool", aliases=["updatedns"], - default=None), + hosts=dict(type="list", default=None, + options=dict( + # Here name is a simple string + name=dict(type="str", aliases=["fqdn"], + required=True), + # Add host specific parameters + **host_spec + ), + elements='dict', required=False), + + # mod update_password=dict(type='str', default=None, choices=['always', 'on_create']), - # absent - # continue - # disabled - - # state + # general + action=dict(type="str", default="host", + choices=["member", "host"]), state=dict(type="str", default="present", choices=["present", "absent", "disabled"]), + + # Add host specific parameters for simple use case + **host_spec ), + mutually_exclusive=[["name", "hosts"]], + required_one_of=[["name", "hosts"]], supports_check_mode=True, ) @@ -287,49 +652,82 @@ 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") + hosts = module_params_get(ansible_module, "hosts") # present - description = ansible_module.params.get("description") - locality = ansible_module.params.get("locality") - location = ansible_module.params.get("location") - platform = ansible_module.params.get("platform") - os = ansible_module.params.get("os") - password = ansible_module.params.get("password") - random = ansible_module.params.get("random") - mac_address = ansible_module.params.get("mac_address") - force = ansible_module.params.get("force") - reverse = ansible_module.params.get("reverse") - ip_address = ansible_module.params.get("ip_address") - update_dns = ansible_module.params.get("update_dns") - update_password = ansible_module.params.get("update_password") - # absent - # disabled - # state - state = ansible_module.params.get("state") + description = module_params_get(ansible_module, "description") + locality = module_params_get(ansible_module, "locality") + location = module_params_get(ansible_module, "location") + platform = module_params_get(ansible_module, "platform") + os = module_params_get(ansible_module, "os") + password = module_params_get(ansible_module, "password") + random = module_params_get(ansible_module, "random") + certificate = module_params_get(ansible_module, "certificate") + managedby_host = module_params_get(ansible_module, "managedby_host") + principal = module_params_get(ansible_module, "principal") + allow_create_keytab_user = module_params_get( + ansible_module, "allow_create_keytab_user") + allow_create_keytab_group = module_params_get( + ansible_module, "allow_create_keytab_group") + allow_create_keytab_host = module_params_get( + ansible_module, "allow_create_keytab_host") + allow_create_keytab_hostgroup = module_params_get( + ansible_module, "allow_create_keytab_hostgroup") + allow_retrieve_keytab_user = module_params_get( + ansible_module, "allow_retrieve_keytab_user") + allow_retrieve_keytab_group = module_params_get( + ansible_module, "allow_retrieve_keytab_group") + allow_retrieve_keytab_host = module_params_get( + ansible_module, "allow_retrieve_keytab_host") + allow_retrieve_keytab_hostgroup = module_params_get( + ansible_module, "allow_retrieve_keytab_hostgroup") + mac_address = module_params_get(ansible_module, "mac_address") + sshpubkey = module_params_get(ansible_module, "sshpubkey") + userclass = module_params_get(ansible_module, "userclass") + auth_ind = module_params_get(ansible_module, "auth_ind") + requires_pre_auth = module_params_get(ansible_module, "requires_pre_auth") + ok_as_delegate = module_params_get(ansible_module, "ok_as_delegate") + ok_to_auth_as_delegate = module_params_get(ansible_module, + "ok_to_auth_as_delegate") + force = module_params_get(ansible_module, "force") + reverse = module_params_get(ansible_module, "reverse") + ip_address = module_params_get(ansible_module, "ip_address") + update_dns = module_params_get(ansible_module, "update_dns") + update_password = module_params_get(ansible_module, "update_password") + # general + action = module_params_get(ansible_module, "action") + state = module_params_get(ansible_module, "state") # Check parameters + if (names is None or len(names) < 1) and \ + (hosts is None or len(hosts) < 1): + ansible_module.fail_json(msg="One of name and hosts is required") + if state == "present": - if len(names) != 1: + if names is not None and len(names) != 1: ansible_module.fail_json( msg="Only one host can be added at a time.") - if state == "absent": - if len(names) < 1: - ansible_module.fail_json( - msg="No name given.") - for x in ["description", "password", "random", "mac_address", - "force", "ip_address", "update_password"]: - if vars()[x] is not None: - ansible_module.fail_json( - msg="Argument '%s' can not be used with state '%s'" % - (x, state)) + check_parameters( + ansible_module, state, action, + description, locality, location, platform, os, password, random, + certificate, managedby_host, principal, allow_create_keytab_user, + allow_create_keytab_group, allow_create_keytab_host, + allow_create_keytab_hostgroup, allow_retrieve_keytab_user, + allow_retrieve_keytab_group, allow_retrieve_keytab_host, + allow_retrieve_keytab_hostgroup, mac_address, sshpubkey, userclass, + auth_ind, requires_pre_auth, ok_as_delegate, ok_to_auth_as_delegate, + force, reverse, ip_address, update_dns, update_password) - if update_password is None: - update_password = "always" + # Use hosts if names is None + if hosts is not None: + names = hosts # Init @@ -343,9 +741,75 @@ def main(): ipaadmin_password) api_connect() + # Check version specific settings + + server_realm = api_get_realm() + commands = [] - for name in names: + for host in names: + if isinstance(host, dict): + name = host.get("name") + description = host.get("description") + locality = host.get("locality") + location = host.get("location") + platform = host.get("platform") + os = host.get("os") + password = host.get("password") + random = host.get("random") + certificate = host.get("certificate") + managedby_host = host.get("managedby_host") + principal = host.get("principal") + allow_create_keytab_user = host.get( + "allow_create_keytab_user") + allow_create_keytab_group = host.get( + "allow_create_keytab_group") + allow_create_keytab_host = host.get( + "allow_create_keytab_host") + allow_create_keytab_hostgroup = host.get( + "allow_create_keytab_hostgroup") + allow_retrieve_keytab_user = host.get( + "allow_retrieve_keytab_user") + allow_retrieve_keytab_group = host.get( + "allow_retrieve_keytab_group") + allow_retrieve_keytab_host = host.get( + "allow_retrieve_keytab_host") + allow_retrieve_keytab_hostgroup = host.get( + "allow_retrieve_keytab_hostgroup") + mac_address = host.get("mac_address") + sshpubkey = host.get("sshpubkey") + userclass = host.get("userclass") + auth_ind = host.get("auth_ind") + requires_pre_auth = host.get("requires_pre_auth") + ok_as_delegate = host.get("ok_as_delegate") + ok_to_auth_as_delegate = host.get("ok_to_auth_as_delegate") + force = host.get("force") + reverse = host.get("reverse") + ip_address = host.get("ip_address") + update_dns = host.get("update_dns") + # update_password is not part of hosts structure + # action is not part of hosts structure + # state is not part of hosts structure + + check_parameters( + ansible_module, state, action, + description, locality, location, platform, os, password, + random, certificate, managedby_host, principal, + allow_create_keytab_user, allow_create_keytab_group, + allow_create_keytab_host, allow_create_keytab_hostgroup, + allow_retrieve_keytab_user, allow_retrieve_keytab_group, + allow_retrieve_keytab_host, + allow_retrieve_keytab_hostgroup, mac_address, sshpubkey, + userclass, auth_ind, requires_pre_auth, ok_as_delegate, + ok_to_auth_as_delegate, force, reverse, ip_address, + update_dns, update_password) + + elif isinstance(host, str) or isinstance(host, unicode): + name = host + else: + ansible_module.fail_json(msg="Host '%s' is not valid" % + repr(host)) + # Make sure host exists res_find = find_host(ansible_module, name) @@ -353,41 +817,392 @@ def main(): if state == "present": # Generate args args = gen_args( - description, force, locality, location, platform, os, - password, random, mac_address, ip_address, update_dns, - reverse) + description, locality, location, platform, os, password, + random, mac_address, sshpubkey, userclass, auth_ind, + requires_pre_auth, ok_as_delegate, ok_to_auth_as_delegate, + force, reverse, ip_address, update_dns) - # Found the host - if res_find is not None: - # Ignore password with update_password == on_create - if update_password == "on_create": - if "userpassword" in args: + if action == "host": + # Found the host + if res_find is not None: + # Ignore password with update_password == on_create + if update_password == "on_create" and \ + "userpassword" in args: del args["userpassword"] - if "random" in args: - del args["random"] - # Ignore force, ip_address and no_reverse for mod - for x in ["force", "ip_address", "no_reverse"]: - if x in args: - del args[x] + # Ignore force, ip_address and no_reverse for mod + for x in ["force", "ip_address", "no_reverse"]: + if x in args: + del args[x] + + # 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, "host_mod", args]) + elif random and "userpassword" in res_find: + # Host exists and random is set, return + # userpassword + if len(names) == 1: + exit_args["userpassword"] = \ + res_find["userpassword"] + else: + exit_args.setdefault("hosts", {})[name] = { + "userpassword": res_find["userpassword"] + } + + else: + # Remove update_dns as it is not supported by host_add + if "updatedns" in args: + del args["updatedns"] + commands.append([name, "host_add", args]) + + # Handle members: certificate, managedby_host, principal, + # allow_create_keytab and allow_retrieve_keytab + if res_find is not None: + certificate_add, certificate_del = gen_add_del_lists( + certificate, res_find.get("usercertificate")) + managedby_host_add, managedby_host_del = \ + gen_add_del_lists(managedby_host, + res_find.get("managedby_host")) + principal_add, principal_del = gen_add_del_lists( + principal, res_find.get("principal")) + # Principals are not returned as utf8 for IPA using + # python2 using host_find, therefore we need to + # convert the principals that we should remove. + principal_del = [to_text(x) for x in principal_del] + + (allow_create_keytab_user_add, + allow_create_keytab_user_del) = \ + gen_add_del_lists( + allow_create_keytab_user, + res_find.get( + "ipaallowedtoperform_write_keys_user")) + (allow_create_keytab_group_add, + allow_create_keytab_group_del) = \ + gen_add_del_lists( + allow_create_keytab_group, + res_find.get( + "ipaallowedtoperform_write_keys_group")) + (allow_create_keytab_host_add, + allow_create_keytab_host_del) = \ + gen_add_del_lists( + allow_create_keytab_host, + res_find.get( + "ipaallowedtoperform_write_keys_host")) + (allow_create_keytab_hostgroup_add, + allow_create_keytab_hostgroup_del) = \ + gen_add_del_lists( + allow_create_keytab_hostgroup, + res_find.get( + "ipaallowedtoperform_write_keys_" + "hostgroup")) + (allow_retrieve_keytab_user_add, + allow_retrieve_keytab_user_del) = \ + gen_add_del_lists( + allow_retrieve_keytab_user, + res_find.get( + "ipaallowedtoperform_read_keys_user")) + (allow_retrieve_keytab_group_add, + allow_retrieve_keytab_group_del) = \ + gen_add_del_lists( + allow_retrieve_keytab_group, + res_find.get( + "ipaallowedtoperform_read_keys_group")) + (allow_retrieve_keytab_host_add, + allow_retrieve_keytab_host_del) = \ + gen_add_del_lists( + allow_retrieve_keytab_host, + res_find.get( + "ipaallowedtoperform_read_keys_host")) + (allow_retrieve_keytab_hostgroup_add, + allow_retrieve_keytab_hostgroup_del) = \ + gen_add_del_lists( + allow_retrieve_keytab_hostgroup, + res_find.get( + "ipaallowedtoperform_read_keys_hostgroup")) + + else: + certificate_add = certificate or [] + certificate_del = [] + managedby_host_add = managedby_host or [] + managedby_host_del = [] + principal_add = principal or [] + principal_del = [] + allow_create_keytab_user_add = \ + allow_create_keytab_user or [] + allow_create_keytab_user_del = [] + allow_create_keytab_group_add = \ + allow_create_keytab_group or [] + allow_create_keytab_group_del = [] + allow_create_keytab_host_add = \ + allow_create_keytab_host or [] + allow_create_keytab_host_del = [] + allow_create_keytab_hostgroup_add = \ + allow_create_keytab_hostgroup or [] + allow_create_keytab_hostgroup_del = [] + allow_retrieve_keytab_user_add = \ + allow_retrieve_keytab_user or [] + allow_retrieve_keytab_user_del = [] + allow_retrieve_keytab_group_add = \ + allow_retrieve_keytab_group or [] + allow_retrieve_keytab_group_del = [] + allow_retrieve_keytab_host_add = \ + allow_retrieve_keytab_host or [] + allow_retrieve_keytab_host_del = [] + allow_retrieve_keytab_hostgroup_add = \ + allow_retrieve_keytab_hostgroup or [] + allow_retrieve_keytab_hostgroup_del = [] - # 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, "host_mod", args]) else: - commands.append([name, "host_add", args]) + certificate_add = certificate or [] + certificate_del = [] + managedby_host_add = managedby_host or [] + managedby_host_del = [] + principal_add = principal or [] + principal_del = [] + allow_create_keytab_user_add = \ + allow_create_keytab_user or [] + allow_create_keytab_user_del = [] + allow_create_keytab_group_add = \ + allow_create_keytab_group or [] + allow_create_keytab_group_del = [] + allow_create_keytab_host_add = \ + allow_create_keytab_host or [] + allow_create_keytab_host_del = [] + allow_create_keytab_hostgroup_add = \ + allow_create_keytab_hostgroup or [] + allow_create_keytab_hostgroup_del = [] + allow_retrieve_keytab_user_add = \ + allow_retrieve_keytab_user or [] + allow_retrieve_keytab_user_del = [] + allow_retrieve_keytab_group_add = \ + allow_retrieve_keytab_group or [] + allow_retrieve_keytab_group_del = [] + allow_retrieve_keytab_host_add = \ + allow_retrieve_keytab_host or [] + allow_retrieve_keytab_host_del = [] + allow_retrieve_keytab_hostgroup_add = \ + allow_retrieve_keytab_hostgroup or [] + allow_retrieve_keytab_hostgroup_del = [] + + # Remove canonical principal from principal_del + canonical_principal = "host/" + name + "@" + server_realm + if canonical_principal in principal_del and \ + action == "host" and (principal is not None or + canonical_principal not in principal): + principal_del.remove(canonical_principal) + + # Remove canonical managedby managedby_host_del for + # action host if managedby_host is set and the canonical + # managedby host is not in the managedby_host list. + canonical_managedby_host = name + if canonical_managedby_host in managedby_host_del and \ + action == "host" and (managedby_host is None or + canonical_managedby_host not in + managedby_host): + managedby_host_del.remove(canonical_managedby_host) + + # Certificates need to be added and removed one by one, + # because if entry already exists, the processing of + # the remaining enries is stopped. The same applies to + # the removal of non-existing entries. + + # Add certificates + for _certificate in certificate_add: + commands.append([name, "host_add_cert", + { + "usercertificate": + _certificate, + }]) + # Remove certificates + for _certificate in certificate_del: + commands.append([name, "host_remove_cert", + { + "usercertificate": + _certificate, + }]) + + # Managedby_Hosts need to be added and removed one by one, + # because if entry already exists, the processing of + # the remaining enries is stopped. The same applies to + # the removal of non-existing entries. + + # Add managedby_hosts + for _managedby_host in managedby_host_add: + commands.append([name, "host_add_managedby", + { + "host": + _managedby_host, + }]) + # Remove managedby_hosts + for _managedby_host in managedby_host_del: + commands.append([name, "host_remove_managedby", + { + "host": + _managedby_host, + }]) + + # Principals need to be added and removed one by one, + # because if entry already exists, the processing of + # the remaining enries is stopped. The same applies to + # the removal of non-existing entries. + + # Add principals + for _principal in principal_add: + commands.append([name, "host_add_principal", + { + "krbprincipalname": + _principal, + }]) + # Remove principals + for _principal in principal_del: + commands.append([name, "host_remove_principal", + { + "krbprincipalname": + _principal, + }]) + + # Allow create keytab + if len(allow_create_keytab_user_add) > 0 or \ + len(allow_create_keytab_group_add) > 0 or \ + len(allow_create_keytab_host_add) > 0 or \ + len(allow_create_keytab_hostgroup_add) > 0: + commands.append( + [name, "host_allow_create_keytab", + { + "user": allow_create_keytab_user_add, + "group": allow_create_keytab_group_add, + "host": allow_create_keytab_host_add, + "hostgroup": allow_create_keytab_hostgroup_add, + }]) + + # Disallow create keytab + if len(allow_create_keytab_user_del) > 0 or \ + len(allow_create_keytab_group_del) > 0 or \ + len(allow_create_keytab_host_del) > 0 or \ + len(allow_create_keytab_hostgroup_del) > 0: + commands.append( + [name, "host_disallow_create_keytab", + { + "user": allow_create_keytab_user_del, + "group": allow_create_keytab_group_del, + "host": allow_create_keytab_host_del, + "hostgroup": allow_create_keytab_hostgroup_del, + }]) + + # Allow retrieve keytab + if len(allow_retrieve_keytab_user_add) > 0 or \ + len(allow_retrieve_keytab_group_add) > 0 or \ + len(allow_retrieve_keytab_host_add) > 0 or \ + len(allow_retrieve_keytab_hostgroup_add) > 0: + commands.append( + [name, "host_allow_retrieve_keytab", + { + "user": allow_retrieve_keytab_user_add, + "group": allow_retrieve_keytab_group_add, + "host": allow_retrieve_keytab_host_add, + "hostgroup": allow_retrieve_keytab_hostgroup_add, + }]) + + # Disallow retrieve keytab + if len(allow_retrieve_keytab_user_del) > 0 or \ + len(allow_retrieve_keytab_group_del) > 0 or \ + len(allow_retrieve_keytab_host_del) > 0 or \ + len(allow_retrieve_keytab_hostgroup_del) > 0: + commands.append( + [name, "host_disallow_retrieve_keytab", + { + "user": allow_retrieve_keytab_user_del, + "group": allow_retrieve_keytab_group_del, + "host": allow_retrieve_keytab_host_del, + "hostgroup": allow_retrieve_keytab_hostgroup_del, + }]) elif state == "absent": - if res_find is not None: - commands.append([name, "host_del", {}]) + if action == "host": + + if res_find is not None: + args = {} + if update_dns is not None: + args["updatedns"] = update_dns + commands.append([name, "host_del", args]) + else: + + # Certificates need to be added and removed one by one, + # because if entry already exists, the processing of + # the remaining enries is stopped. The same applies to + # the removal of non-existing entries. + + # Remove certificates + if certificate is not None: + for _certificate in certificate: + commands.append([name, "host_remove_cert", + { + "usercertificate": + _certificate, + }]) + + # Managedby_Hosts need to be added and removed one by one, + # because if entry already exists, the processing of + # the remaining enries is stopped. The same applies to + # the removal of non-existing entries. + + # Remove managedby_hosts + if managedby_host is not None: + for _managedby_host in managedby_host: + commands.append([name, "host_remove_managedby", + { + "host": + _managedby_host, + }]) + + # Principals need to be added and removed one by one, + # because if entry already exists, the processing of + # the remaining enries is stopped. The same applies to + # the removal of non-existing entries. + + # Remove principals + if principal is not None: + for _principal in principal: + commands.append([name, "host_remove_principal", + { + "krbprincipalname": + _principal, + }]) + + # Disallow create keytab + if allow_create_keytab_user is not None or \ + allow_create_keytab_group is not None or \ + allow_create_keytab_host is not None or \ + allow_create_keytab_hostgroup is not None: + commands.append( + [name, "host_disallow_create_keytab", + { + "user": allow_create_keytab_user, + "group": allow_create_keytab_group, + "host": allow_create_keytab_host, + "hostgroup": allow_create_keytab_hostgroup, + }]) + + # Disallow retrieve keytab + if allow_retrieve_keytab_user is not None or \ + allow_retrieve_keytab_group is not None or \ + allow_retrieve_keytab_host is not None or \ + allow_retrieve_keytab_hostgroup is not None: + commands.append( + [name, "host_disallow_retrieve_keytab", + { + "user": allow_retrieve_keytab_user, + "group": allow_retrieve_keytab_group, + "host": allow_retrieve_keytab_host, + "hostgroup": allow_retrieve_keytab_hostgroup, + }]) elif state == "disabled": if res_find is not None: - res_show = show_host(ansible_module, name) - if res_show["has_keytab"]: - commands.append([name, "host_disable", {}]) + commands.append([name, "host_disable", {}]) else: raise ValueError("No host '%s'" % name) @@ -395,11 +1210,17 @@ def main(): 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) - changed = True + if "completed" in result: + if result["completed"] > 0: + changed = True + else: + changed = True if "random" in args and command in ["host_add", "host_mod"] \ and "randompassword" in result["result"]: @@ -411,8 +1232,37 @@ def main(): result["result"]["randompassword"] except Exception as e: + msg = str(e) + if "already contains" in msg \ + or "does not contain" in msg: + continue + + # The canonical principal name may not be removed + if "equal to the canonical principal name must" in msg: + continue + + # Host is already disabled, ignore error + if "This entry is already disabled" in msg: + continue ansible_module.fail_json(msg="%s: %s: %s" % (command, name, - str(e))) + msg)) + + # 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)) diff --git a/tests/host/certificate/cert1.der b/tests/host/certificate/cert1.der new file mode 100644 index 0000000000000000000000000000000000000000..334511ff52b76c7611d9782e454275b06e93c93b GIT binary patch literal 771 zcmXqLV)}2;#Q1yxGZP~dlSoS9=}a|+YdI@lI9Y_GPU6mcZ?)TimyJ`a&7QA+G^98*?ZNGY?BiYH^8yoH(zcrJ;eLiJ_U1g|TUrIIocbkZTO(Vrpn&R6;hC zk(GhDiIJZH=ngKXCPqevBkn&PKeIB-_;Tr>y1mKMv(wEpZJscDb3N3ko4#q8>w{GR z3)SrBB`jtVO0$ge3+m&#`Eg>pPlNpRCsO}5sr;Msrh&C*`@G_f{jxE<54UC82VAc; zP^(LQSSTXR*(v&)bJd66n-Blr$b6A=-7eWVlh1GPYxz)lDP&_+()qfA$((PhH(2y< zNV@xAQnuzMt*={;tJU|E+Wg-nGj(oZ&Ae@afkkOGO{bDqJSpqlZ+lclr~QP?3DaF` zKBs!x+(=JMGrMubds!maG4A`}7jj}JG)2svvT-F-^zlHKeMdAFMDM+`Pte~m^-j&Z zQlq_PoT8mR!3p!(787$2IwhuUkfrywAS%|Evv5gAEP~FHnC``#9px^c8LIw@qn1W6OSd zZ>cn|B`-rZo8G_ft&AeIDlV%yO)L9u`(JRaoA`BS>`XC%zHbH&Km4TY=Xo99_8{Qm z_UoFAn}pX`?(|bRo9g{n>!E2ov(%g5(9rhI&MUAau&UItkHY9{D#8K{;3?3;teKWUAlSZSC$r?ALkj&*ZDHu{{73^re`S^ L*PF%Nr@jLKG7deK literal 0 HcmV?d00001 diff --git a/tests/host/certificate/cert1.pem b/tests/host/certificate/cert1.pem new file mode 100644 index 00000000..6fb9d2e9 --- /dev/null +++ b/tests/host/certificate/cert1.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/zCCAeegAwIBAgIUZGHLaSYg1myp6EI4VGWSC27vOrswDQYJKoZIhvcNAQEL +BQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4MzVaFw0yMDEwMTMxNjI4 +MzVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDER/lB8wUAmPTSwSc/NOXNlzdpPOQDSwrhKH6XsqZF4KpQoSY/nmCjAhJm +OVpOUo4K2fGRZ0yAH9fkGv6yJP6c7IAFjLeec7GPHVwN4bZrP1DXfTAmfmXhcRQb +CYkV+wmq8Puzw/+xA9EJrrodnJPPsE6E8HnSVLF6Ys9+cJMJ7HuwOI+wYt3gkmsp +sir1tccmf4x1PP+yHJWdcXyetlFRcmZ8gspjqOR2jb89xSQsh8gcyDW6rPNlSTzY +Z2FmNtjES6ZhCsYL31fQbF2QglidlLGpAlvHUUS+xCigW73cvhFPMWXcfO51Mr15 +RcgYTckY+7QZ2nYqplRBoDlQl6DnAgMBAAGjUzBRMB0GA1UdDgQWBBTPG99XVRdx +pOXMZo3Nhy+ldnf13TAfBgNVHSMEGDAWgBTPG99XVRdxpOXMZo3Nhy+ldnf13TAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAjWTcnIl2mpNbfHAN8 +DB4Kk+RNRmhsH0y+r/47MXVTMMMToCfofeNY3Jeohu+2lIXMPQfTvXUbDTkNAGsG +Lv6LtQEUfSREqgk1eY7bT9BFfpH1uV2ZFhCO9jBA+E4bf55Kx7bgUNG31ykBshOs +OblOJM1lS/0q4TWHAxrsU2PNwPi8X0ten+eGeB8aRshxS17Ij2cH0fdAMmSA+jMA +vTIZl853Bxe0HuozauKwOFWL4qHm61c4O/j1mQCLqJKYfJ9mBDWFQLszd/tF+ePK +iNhZCQly60F8Lumn2CDZj5UIkl8wk9Wls5n1BIQs+M8AN65NAdv7+js8jKUKCuyj +i8r3 +-----END CERTIFICATE----- diff --git a/tests/host/certificate/cert2.der b/tests/host/certificate/cert2.der new file mode 100644 index 0000000000000000000000000000000000000000..a3ba5a575677e12a26c96ab8844724e733878ff7 GIT binary patch literal 771 zcmXqLV)}2;#Q1yxGZP~dlL%v?>D~o)GpCo&XUjU6`0Ih&@x8JJylk9WZ60mkc^MhG zSs4uY4S5Z?*_cCFn0Z)AQj1FrA zjI0dIO^o~uKzDF4H8CvpAK?bVve5i`^dT;0|kGFKvH#$xp?`ycf^eEWP=!PIayN5zOMk7lNxjsC`T z*6`k4m08P5W>~D8D^ub$ZD!Gi{d}ht+1^dN{&zub2m8_d|LX$+rawDuAQE-s$ctqf z^ZkoI2Z~+Kzs_86ZPzr7*vPXh#M}aRIPqMRX0cfH-1@}(8lM$Q`jh)Rx~o&~S+(w( za4dt3?ZT3fXCCd+yWhO*T@x)nzIh7?;3cXJl{+ zO)vXiBX+98b;Us+Spmo9dzWvzo1T2~rR3lbw%L6dS`(Ic?W~%=PWR{$<@MWV_^5rF zwm)DC6aSfR-CMefnQr%A)IZ$Cy7WfB=mF#a8qCtdg2 zAhqLE>y5nY0&x$2MLZ3dw>8w%V$V9iqeeTA=!or(RCby8xuPyF?9+l{)k?zZ4eG}N z-$u`EpEhUPOVJ$*G(W!!Fcui1A6});|vXiZf3(Ykm&C+vfAhqs^JK zbzO<<>SJdwJ-qng&cEC3(lf6eFRalxfSc%Sm!Nf OYqFfX{cP^WL!kie2uig8 literal 0 HcmV?d00001 diff --git a/tests/host/certificate/cert2.pem b/tests/host/certificate/cert2.pem new file mode 100644 index 00000000..4a243b25 --- /dev/null +++ b/tests/host/certificate/cert2.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/zCCAeegAwIBAgIUAWE1vaA+mZd3nwZqwWH64EbHvR0wDQYJKoZIhvcNAQEL +BQAwDzENMAsGA1UEAwwEdGVzdDAeFw0xOTEwMTQxNjI4NDVaFw0yMDEwMTMxNjI4 +NDVaMA8xDTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCWzJibKtN8Zf7LgandINhFonx99AKi44iaZkrlMKEObE6Faf8NTUbUgK3V +fJNYmCbA1baLVJ0YZJijJ7S/4o7h7eeqcJVXJkEhWNTimWXNW/YCzTHe3SSapnSY +OKmdHHRClplysL8OyyEG7pbX/aB9iAfFb/+vUFCX5sMwFFrYxOimKJ9Pc/NRFtdv +1wNw1rqWKF1ZzagWRlG4QgzRGwQ4quc7yO98TKikj2OPiIt7Zd46hbqQxmgGBtCk +VOZIhxu77OmNrFsXmM4rZZpmqh0UdqcpwkRojVnGXmNqeMCd6dNTnLhr9wukUYw0 +KgE57zCDVr9Ix+p/dA5R1mG4RJ2XAgMBAAGjUzBRMB0GA1UdDgQWBBSbuiH2lNVr +ID3yt1SsFwtOFKOnpTAfBgNVHSMEGDAWgBSbuiH2lNVrID3yt1SsFwtOFKOnpTAP +BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBCVWd293wWyohFqMFM +HRBBg97T2Uc1yeT0dMH4BpuOaCqQp4q5ep+uLcXEI6+3mEwm8pa/ULQCD8yLLdot +IWlG3+h/4boFpdiPFcBDgT8kGe+0KOzB8Nt7E13QYOu12MNi10qwGrjKhdhu1xBe +4fpY5VCetVU1OLyuTsUyucQsFrtZI0SR83h+blbyoMZ7IhMngCfGUe1bnYeWnLbp +FbigKfPuVDWsMH2kgj05EAd5EgHkWbX8QA8hmcmDKfNT3YZM8kiGQwmFrnQdq8bN +0uHR8Nz+24cbmdbHcD65wlDW6GmYxi8mW+V6bAqn9pir/J14r4YFnqMGgjmdt81t +scJV +-----END CERTIFICATE----- diff --git a/tests/host/certificate/cert3.der b/tests/host/certificate/cert3.der new file mode 100644 index 0000000000000000000000000000000000000000..783830ee5d9fb52cc41010a3b60047bd68667cd0 GIT binary patch literal 771 zcmXqLV)}2;#Q1yxGZP~dlZcP*_ed`Zi71YcWP>KNJ5T0qQZGm5>c( zWMyD(V&rE4x`T_UiII`v5c9kKn=j_YlucFBejBC!+p9Xc&nfMa^+Zh(w~e+Rw!b-) zwu-s>%%`aazL&D){(PPmdtu+%5+Cl=|HZAPmpruhrad>k7#k3NFla_ntd`bXH}>=; zw|?#u@i*AE#bHu_=Ou3Y^lRjEX?+l|$W5AX z`W{!)w|@%%e*fy;Q76f$)9VvI^GW2|bEn=38=L&!wt`=Huj1r00%u*#vUE7#bgRux zv`RW@UEFZPU<&L1xzXJTMX8B`W;Tt5>=)UXXYQ13$&uLiszfMJo{5=}fpKxLL7;&wFq~!iSj1RFIyw0j7dyYK z_EZd$P%>JrKaIzu-#{KDt;`}}Al86g0Y6BAFeBrC7FGjhAcY+4z_dvIob+g0*Z{4-$n5Y%C