Compare commits

..

1 Commits

Author SHA1 Message Date
Thomas Woerner
dd6dd1fd84 Update README-role.md
Change title of README-role to "Role module"
2020-07-29 10:18:15 +02:00
207 changed files with 9602 additions and 8100 deletions

View File

@@ -1,23 +0,0 @@
exclude_paths:
- roles
- .tox
- .venv
parseable: true
quiet: false
skip_list:
- '201' # Trailing whitespace
- '204' # Lines should be no longer than 160 chars
- '206' # Variables should have spaces before and after: {{ var_name }}'
- '208' # File permissions not mentioned
- '301' # Commands should not change things if nothing needs doing'
- '305' # Use shell only when shell functionality is required'
- '306' # Shells that use pipes should set the pipefail option'
- '502' # All tasks should be named
- '505' # Referenced missing file
use_default_rules: true
verbosity: 1

View File

@@ -1,9 +0,0 @@
srpm:
# Setup development environment
echo "Installing base development environment"
dnf install -y dnf-plugins-core git-all
echo "Call SRPM build Script"
./utils/build-srpm.sh
if [[ "${outdir}" != "" ]]; then \
mv /builddir/build/SRPMS/* ${outdir}; \
fi

View File

@@ -1,33 +0,0 @@
---
name: Run Linters
on:
- push
- pull_request
jobs:
linters:
name: Run Linters
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: "3.6"
- name: Run ansible-lint
uses: ansible/ansible-lint-action@master
with:
targets: |
tests/*.yml
tests/*/*.yml
tests/*/*/*.yml
playbooks/*.yml
playbooks/*/*.yml
env:
ANSIBLE_MODULE_UTILS: plugins/module_utils
ANSIBLE_LIBRARY: plugins/modules
- name: Run yaml-lint
uses: ibiqlik/action-yamllint@v1
- name: Run Python linters
uses: rjeffman/python-lint-action@master

6
.gitignore vendored
View File

@@ -1,8 +1,2 @@
*.pyc *.pyc
*.retry *.retry
# ignore virtual environments
/.tox/
/.venv/
tests/logs/

View File

@@ -1,28 +0,0 @@
---
ignore: |
/.tox/
/.venv/
/.github/
extends: default
rules:
braces:
max-spaces-inside: 1
level: error
brackets:
max-spaces-inside: 1
level: error
truthy:
allowed-values: ["yes", "no", "true", "false", "True", "False"]
level: error
# Disabled rules
document-start: disable
indentation: disable
line-length: disable
colons: disable
empty-lines: disable
comments: disable
comments-indentation: disable
trailing-spaces: disable
new-line-at-end-of-file: disable

View File

@@ -19,7 +19,6 @@ Supported FreeIPA Versions
FreeIPA versions 4.4.0 and up are supported by the ipaconfig module. FreeIPA versions 4.4.0 and up are supported by the ipaconfig module.
Some variables are only supported on newer versions of FreeIPA. Check `Variables` section for details.
Requirements Requirements
------------ ------------
@@ -92,7 +91,7 @@ Variable | Description | Required
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no `ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no `ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`maxusername` \| `ipamaxusernamelength` | Set the maximum username length (1 to 255) | no `maxusername` \| `ipamaxusernamelength` | Set the maximum username length (1 to 255) | no
`maxhostname` \| `ipamaxhostnamelength` | Set the maximum hostname length between 64-255. Only usable with IPA versions 4.8.0 and up. | no `maxhostname` \| `ipamaxhostnamelength` | Set the maximum hostname length between 64-255 | no
`homedirectory` \| `ipahomesrootdir` | Set the default location of home directories | no `homedirectory` \| `ipahomesrootdir` | Set the default location of home directories | no
`defaultshell` \| `ipadefaultloginshell` | Set the default shell for new users | no `defaultshell` \| `ipadefaultloginshell` | Set the default shell for new users | no
`defaultgroup` \| `ipadefaultprimarygroup` | Set the default group for new users | no `defaultgroup` \| `ipadefaultprimarygroup` | Set the default group for new users | no

View File

@@ -1,157 +0,0 @@
Delegation module
=================
Description
-----------
The delegation module allows to ensure presence, absence of delegations and delegation attributes.
Features
--------
* Delegation management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipadelegation 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 delegation "basic manager attributes" is present:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
- employeetype
group: managers
membergroup: employees
```
Example playbook to make sure delegation "basic manager attributes" is absent:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
state: absent
```
Example playbook to make sure "basic manager attributes" member attributes employeetype and employeenumber are present:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
```
Example playbook to make sure "basic manager attributes" member attributes employeetype and employeenumber are absent:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
state: absent
```
Example playbook to make sure delegation "basic manager attributes" is absent:
```yaml
---
- name: Playbook to manage IPA delegation.
hosts: ipaserver
become: yes
tasks:
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
state: absent
```
Variables
---------
ipadelegation
-------
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` \| `aciname` | The list of delegation name strings. | yes
`permission` \| `permissions` | The permission to grant `read`, `read,write`, `write`]. Default is `write`. | no
`attribute` \| `attrs` | The attribute list to which the delegation applies. | no
`membergroup` \| `memberof` | The user group to apply delegation to. | no
`group` | User group ACI grants access to. | no
`action` | Work on delegation or member level. It can be on of `member` or `delegation` and defaults to `delegation`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner

View File

@@ -152,46 +152,6 @@ Example playbook to remove a zone:
``` ```
Example playbook to create a zone for reverse DNS lookup, from an IP address:
```yaml
---
- name: dnszone present
hosts: ipaserver
become: true
tasks:
- name: Ensure zone for reverse DNS lookup is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 192.168.1.2
state: present
```
Note that, on the previous example the zone created with `name_from_ip` might be "1.168.192.in-addr.arpa.", "168.192.in-addr.arpa.", or "192.in-addr.arpa.", depending on the DNS response the system get while querying for zones, and for this reason, when creating a zone using `name_from_ip`, the inferred zone name is returned to the controller, in the attribute `dnszone.name`. Since the zone inferred might not be what a user expects, `name_from_ip` can only be used with `state: present`. To have more control over the zone name, the prefix length for the IP address can be provided.
Example playbook to create a zone for reverse DNS lookup, from an IP address, given the prefix length and displaying the resulting zone name:
```yaml
---
- name: dnszone present
hosts: ipaserver
become: true
tasks:
- name: Ensure zone for reverse DNS lookup is present.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 192.168.1.2/24
state: present
register: result
- name: Display inferred zone name.
debug:
msg: "Zone name: {{ result.dnszone.name }}"
```
Variables Variables
========= =========
@@ -203,8 +163,7 @@ Variable | Description | Required
-------- | ----------- | -------- -------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no `ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no `ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`name` \| `zone_name` | The zone name string or list of strings. | no `name` \| `zone_name` | The zone name string. | yes
`name_from_ip` | Derive zone name from reverse of IP (PTR). Can only be used with `state: present`. | no
`forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no `forwarders` | The list of forwarders dicts. Each `forwarders` dict entry has:| no
  | `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes   | `ip_address` - The IPv4 or IPv6 address of the DNS server. | yes
  | `port` - The custom port that should be used on this server. | no   | `port` - The custom port that should be used on this server. | no
@@ -230,17 +189,6 @@ Variable | Description | Required
`skip_nameserver_check` | Force DNS zone creation even if nameserver is not resolvable | no `skip_nameserver_check` | Force DNS zone creation even if nameserver is not resolvable | no
Return Values
=============
ipadnszone
----------
Variable | Description | Returned When
-------- | ----------- | -------------
`dnszone` | DNS Zone dict with zone name infered from `name_from_ip`. <br>Options: | If `state` is `present`, `name_from_ip` is used, and a zone was created.
&nbsp; | `name` - The name of the zone created, inferred from `name_from_ip`. | Always
Authors Authors
======= =======

View File

@@ -19,8 +19,6 @@ Supported FreeIPA Versions
FreeIPA versions 4.4.0 and up are supported by the ipagroup module. FreeIPA versions 4.4.0 and up are supported by the ipagroup module.
Some variables are only supported on newer versions of FreeIPA. Check `Variables` section for details.
Requirements Requirements
------------ ------------

View File

@@ -19,8 +19,6 @@ Supported FreeIPA Versions
FreeIPA versions 4.4.0 and up are supported by the ipahostgroup module. FreeIPA versions 4.4.0 and up are supported by the ipahostgroup module.
Some variables are only supported on newer versions of FreeIPA. Check `Variables` section for details.
Requirements Requirements
------------ ------------
@@ -107,23 +105,6 @@ Example playbook to make sure hosts and hostgroups are absent in databases hostg
state: absent state: absent
``` ```
Example playbook to rename an existing playbook:
```yaml
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: true
tasks:
# Ensure host-group databases is absent
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
rename: datalake
state: renamed
```
Example playbook to make sure host-group databases is absent: Example playbook to make sure host-group databases is absent:
```yaml ```yaml
@@ -140,6 +121,7 @@ Example playbook to make sure host-group databases is absent:
state: absent state: absent
``` ```
Variables Variables
========= =========
@@ -157,9 +139,8 @@ Variable | Description | Required
`hostgroup` | List of hostgroup name strings assigned to this hostgroup. | no `hostgroup` | List of hostgroup name strings assigned to this hostgroup. | no
`membermanager_user` | List of member manager users assigned to this hostgroup. Only usable with IPA versions 4.8.4 and up. | no `membermanager_user` | List of member manager users assigned to this hostgroup. Only usable with IPA versions 4.8.4 and up. | no
`membermanager_group` | List of member manager groups assigned to this hostgroup. Only usable with IPA versions 4.8.4 and up. | no `membermanager_group` | List of member manager groups assigned to this hostgroup. Only usable with IPA versions 4.8.4 and up. | no
`rename` \| `new_name` | Rename hostgroup to the provided name. Only usable with IPA versions 4.8.7 and up. | no
`action` | Work on hostgroup or member level. It can be on of `member` or `hostgroup` and defaults to `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`, `absent` or `renamed`, default: `present`. | no `state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
Authors Authors

View File

@@ -1,92 +0,0 @@
Location module
===============
Description
-----------
The location module allows to ensure presence and absence of locations.
Features
--------
* Location management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipalocation 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 location "my_location1" is present:
```yaml
---
- name: Playbook to manage IPA location.
hosts: ipaserver
become: yes
tasks:
- ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
description: My Location 1
```
Example playbook to make sure location "my_location1" is absent:
```yaml
---
- name: Playbook to manage IPA location.
hosts: ipaserver
become: yes
tasks:
- ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
state: absent
```
Variables
---------
ipalocation
-------
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` \| `idnsname` | The list of location name strings. | yes
`description` | The IPA location string | false
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner

View File

@@ -1,147 +0,0 @@
Privilege module
================
Description
-----------
The privilege module allows to ensure presence and absence of privileges and privilege members.
Features
--------
* Privilege management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaprivilege 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 privilege "Broad Privilege" is present:
```yaml
---
- name: Playbook to manage IPA privilege.
hosts: ipaserver
become: yes
tasks:
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
description: Broad Privilege
```
Example playbook to make sure privilege "Broad Privilege" member permission has multiple values:
```yaml
---
- name: Playbook to manage IPA privilege permission member.
hosts: ipaserver
become: yes
tasks:
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member
```
Example playbook to make sure privilege "Broad Privilege" member permission 'Write IPA Configuration' is absent:
```yaml
---
- name: Playbook to manage IPA privilege permission member.
hosts: ipaserver
become: yes
tasks:
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "Write IPA Configuration"
action: member
state: absent
```
Example playbook to rename privilege "Broad Privilege" to "DNS Special Privilege":
```yaml
---
- name: Playbook to manage IPA privilege.
hosts: ipaserver
become: yes
tasks:
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
rename: DNS Special Privilege
state: renamed
```
Example playbook to make sure privilege "DNS Special Privilege" is absent:
```yaml
---
- name: Playbook to manage IPA privilege.
hosts: ipaserver
become: yes
- name: Ensure privilege Broad Privilege is absent
ipaadmin_password: SomeADMINpassword
name: DNS Special Privilege
state: absent
```
Variables
---------
ipaprivilege
------------
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 privilege name strings. | yes
`description` | Privilege description. | no
`rename` \| `new_name` | Rename the privilege object. | no
`permission` | Permissions to be added to the privilege. | no
`action` | Work on privilege or member level. It can be one of `member` or `privilege` and defaults to `privilege`. | no
`state` | The state to ensure. It can be one of `present`, `absent` or `renamed`, default: `present`. | no
Authors
=======
Rafael Guterres Jeffman

View File

@@ -1,151 +0,0 @@
Selfservice module
=================
Description
-----------
The selfservice module allows to ensure presence, absence of selfservices and selfservice attributes.
Features
--------
* Selfservice management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaselfservice 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 selfservice "Users can manage their own name details" is present:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
permission: read
attribute:
- title
- initials
```
Example playbook to make sure selfservice "Users can manage their own name details" is absent:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
state: absent
```
Example playbook to make sure "Users can manage their own name details" member attribute initials is present:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
attribute:
- initials
action: member
```
Example playbook to make sure "Users can manage their own name details" member attribute initials is absent:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
attribute:
- initials
action: member
state: absent
```
Example playbook to make sure selfservice "Users can manage their own name details" is absent:
```yaml
---
- name: Playbook to manage IPA selfservice.
hosts: ipaserver
become: yes
tasks:
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
state: absent
```
Variables
---------
ipaselfservice
-------
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` \| `aciname` | The list of selfservice name strings. | yes
`permission` \| `permissions` | The permission to grant `read`, `read,write`, `write`]. Default is `write`. | no
`attribute` \| `attrs` | The attribute list to which the selfservice applies. | no
`action` | Work on selfservice or member level. It can be on of `member` or `selfservice` and defaults to `selfservice`. | no
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
Authors
=======
Thomas Woerner

View File

@@ -18,7 +18,7 @@ Supported FreeIPA Versions
FreeIPA versions 4.4.0 and up are supported by the ipaservice module. FreeIPA versions 4.4.0 and up are supported by the ipaservice module.
Some variables are only supported on newer versions of FreeIPA. Check `Variables` section for details. Option `skip_host_check` requires FreeIPA version 4.7.0 or later.
Requirements Requirements
@@ -56,7 +56,7 @@ Example playbook to make sure service is present:
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com name: HTTP/www.example.com
certificate: | certificate:
- MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAw - MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAw
DzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8xDT DzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8xDT
ALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVGFYpH ALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVGFYpH
@@ -77,7 +77,7 @@ Example playbook to make sure service is present:
requires_pre_auth: false requires_pre_auth: false
ok_as_delegate: false ok_as_delegate: false
ok_to_auth_as_delegate: false ok_to_auth_as_delegate: false
skip_host_check: true skip-host-check: true
force: true force: true
``` ```
@@ -167,7 +167,7 @@ Example playbook to ensure service has a certificate:
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: HTTP/www.example.com name: HTTP/www.example.com
certificate: | certificate:
- MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAw - MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAw
DzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8xDT DzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8xDT
ALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVGFYpH ALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVGFYpH
@@ -298,7 +298,7 @@ Variable | Description | Required
`requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service. Default to true. (bool) | no `requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service. Default to true. (bool) | no
`ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service. Default to false. (bool) | no `ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service. Default to false. (bool) | no
`ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client. Default to false. (bool) | no `ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client. Default to false. (bool) | no
`skip_host_check` | Force service to be created even when host object does not exist to manage it. Only usable with IPA versions 4.7.0 and up. Default to false. (bool)| no `skip_host_check` | Force service to be created even when host object does not exist to manage it. Default to false. (bool)| no
`force` | Force principal name even if host not in DNS. Default to false. (bool) | no `force` | Force principal name even if host not in DNS. Default to false. (bool) | no
`host` \| `managedby_host`| Hosts that can manage the service. | no `host` \| `managedby_host`| Hosts that can manage the service. | no
`principal` \| `krbprincipalname` | List of principal aliases for the service. | no `principal` \| `krbprincipalname` | List of principal aliases for the service. | no

View File

@@ -1,119 +0,0 @@
Trust module
============
Description
-----------
The trust module allows to ensure presence and absence of a domain trust.
Features
--------
* Trust management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipatrust module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
**Node**
* Supported FreeIPA version (see above)
* samba-4
* ipa-server-trust-ad
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure a one-way trust is present:
Omitting the two_way option implies the default of one-way
```yaml
---
- name: Playbook to ensure a one-way trust is present
hosts: ipaserver
become: true
tasks:
- name: ensure the one-way trust present
ipatrust:
realm: ad.example.test
admin: Administrator
password: secret_password
state: present
```
Example playbook to ensure a two-way trust is present using a shared-secret:
```yaml
---
- name: Playbook to ensure a two-way trust is present
hosts: ipaserver
become: true
tasks:
- name: ensure the two-way trust is present
ipatrust:
realm: ad.example.test
trust_secret: my_share_Secret
two_way: True
state: present
```
Example playbook to ensure a trust is absent:
```yaml
---
- name: Playbook to ensure a trust is absent
hosts: ipaserver
become: true
tasks:
- name: ensure the trust is absent
ipatrust:
realm: ad.example.test
state: absent
```
This will only delete the ipa-side of the trust and it does NOT delete the id-range that matches the trust,
Variables
=========
ipatrust
-------
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
`realm` | The realm name string. | yes
`admin` | Active Directory domain administrator string. | no
`password` | Active Directory domain administrator's password string. | no
`server` | Domain controller for the Active Directory domain string. | no
`trust_secret` | Shared secret for the trust string. | no
`base_id` | First posix id for the trusted domain integer. | no
`range_size` | Size of the ID range reserved for the trusted domain integer. | no
`range_type` | Type of trusted domain ID range, It can be one of `ipa-ad-trust` or `ipa-ad-trust-posix`and defaults to `ipa-ad-trust`. | no
`two_way` | Establish bi-directional trust. By default trust is inbound one-way only. (bool) | no
`external` | Establish external trust to a domain in another forest. The trust is not transitive beyond the domain. (bool) | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
Authors
=======
Rob Verduijn

View File

@@ -437,7 +437,7 @@ There are only return values if one or more random passwords have been generated
Variable | Description | Returned When Variable | Description | Returned When
-------- | ----------- | ------------- -------- | ----------- | -------------
`user` | User dict with random password. (dict) <br>Options: | If random is yes and user did not exist or update_password is yes `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; | `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 &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

View File

@@ -197,7 +197,7 @@ Example playbook to make sure vault is absent:
state: absent state: absent
register: result register: result
- debug: - debug:
msg: "{{ result.vault.data }}" msg: "{{ result.data }}"
``` ```
Variables Variables
@@ -246,8 +246,7 @@ There is only a return value if `state` is `retrieved`.
Variable | Description | Returned When Variable | Description | Returned When
-------- | ----------- | ------------- -------- | ----------- | -------------
`vault` | Vault dict with archived data. (dict) <br>Options: | If `state` is `retrieved` and `out` is not defined. `data` | The data stored in the vault. | If `state` is `retrieved`.
&nbsp; | `data` - The vault data. | Always
Notes Notes

View File

@@ -27,7 +27,6 @@ Features
* Modules for sudocmdgroup management * Modules for sudocmdgroup management
* Modules for sudorule management * Modules for sudorule management
* Modules for topology management * Modules for topology management
* Modules fot trust management
* Modules for user management * Modules for user management
* Modules for vault management * Modules for vault management
@@ -430,7 +429,6 @@ Modules in plugin/modules
* [ipasudorule](README-sudorule.md) * [ipasudorule](README-sudorule.md)
* [ipatopologysegment](README-topology.md) * [ipatopologysegment](README-topology.md)
* [ipatopologysuffix](README-topology.md) * [ipatopologysuffix](README-topology.md)
* [ipatrust](README-trust.md)
* [ipauser](README-user.md) * [ipauser](README-user.md)
* [ipavault](README-vault.md) * [ipavault](README-vault.md)

22
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,22 @@
trigger:
- master
pool:
vmImage: 'ubuntu-18.04'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.6'
- script: python -m pip install --upgrade pip setuptools wheel
displayName: Install tools
- script: pip install pydocstyle flake8
displayName: Install dependencies
- script: flake8 .
displayName: Run flake8 checks
- script: pydocstyle .
displayName: Verify docstings

View File

@@ -1,18 +0,0 @@
---
driver:
name: docker
platforms:
- name: centos-7-build
image: centos/systemd
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml

View File

@@ -1,18 +0,0 @@
---
driver:
name: docker
platforms:
- name: centos-7
image: quay.io/ansible-freeipa/upstream-tests:centos-7
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml

View File

@@ -1,18 +0,0 @@
---
driver:
name: docker
platforms:
- name: centos-8-build
image: centos:8
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml

View File

@@ -1,18 +0,0 @@
---
driver:
name: docker
platforms:
- name: centos-8
image: quay.io/ansible-freeipa/upstream-tests:centos-8
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml

View File

@@ -1 +0,0 @@
centos-8

View File

@@ -1,30 +0,0 @@
FROM fedora:latest
ENV container=docker
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
dnf makecache; \
dnf --assumeyes install \
/usr/bin/python3 \
/usr/bin/python3-config \
/usr/bin/dnf-3 \
sudo \
bash \
systemd \
procps-ng \
iproute && \
dnf clean all; \
(cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
rm -rf /var/cache/dnf/;
STOPSIGNAL RTMIN+3
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]

View File

@@ -1,18 +0,0 @@
---
driver:
name: docker
platforms:
- name: fedora-latest-build
image: fedora-latest
dockerfile: Dockerfile
hostname: ipaserver.test.local
dns_servers:
- 8.8.8.8
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare-build.yml

View File

@@ -1,18 +0,0 @@
---
driver:
name: docker
platforms:
- name: fedora-latest
image: quay.io/ansible-freeipa/upstream-tests:fedora-latest
pre_build_image: true
hostname: ipaserver.test.local
dns_servers:
- 127.0.0.1
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
command: /usr/sbin/init
privileged: true
provisioner:
name: ansible
playbooks:
prepare: ../resources/playbooks/prepare.yml

View File

@@ -1 +0,0 @@
../../../plugins/modules/

View File

@@ -1 +0,0 @@
../../../plugins/module_utils/

View File

@@ -1,27 +0,0 @@
---
- name: Converge
hosts: all
tasks:
- include_tasks: prepare-common.yml
- name: Ensure sudo package is installed
package:
name: sudo
- name: Ensure nss package is updated
package:
name: nss
state: latest # noqa 403
- include_role:
name: ipaserver
vars:
ipaserver_setup_dns: yes
ipaserver_setup_kra: yes
ipaserver_auto_forwarders: yes
ipaserver_no_dnssec_validation: yes
ipaserver_auto_reverse: yes
ipaadmin_password: SomeADMINpassword
ipadm_password: SomeDMpassword
ipaserver_domain: test.local
ipaserver_realm: TEST.LOCAL

View File

@@ -1,33 +0,0 @@
# IPA depends on IPv6 and without it dirsrv service won't start.
- name: Ensure IPv6 is ENABLED
sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_set: yes
state: present
reload: yes
with_items :
- name: net.ipv6.conf.all.disable_ipv6
value: 0
- name: net.ipv6.conf.lo.disable_ipv6
value: 0
- name: net.ipv6.conf.eth0.disable_ipv6
value: 1
# Set fs.protected_regular to 0
# This is needed in some IPA versions in order to get KRA enabled.
# See https://pagure.io/freeipa/issue/7906 for more information.
- name: stat protected_regular
stat:
path: /proc/sys/fs/protected_regular
register: result
- name: Ensure fs.protected_regular is disabled
sysctl:
name: fs.protected_regular
value: 0
sysctl_set: yes
state: present
reload: yes
when: result.stat.exists

View File

@@ -1,26 +0,0 @@
---
- name: Converge
hosts: all
tasks:
- include_tasks: prepare-common.yml
# In some distros DS won't start up after reboot
# This is due to a problem in 389-ds. See tickets:
# * https://pagure.io/389-ds-base/issue/47429
# * https://pagure.io/389-ds-base/issue/51039
#
# To avoid this problem we create the directories before starting IPA.
- name: Ensure lock dirs for DS exists
file:
state: directory
owner: dirsrv
group: dirsrv
path: "{{ item }}"
loop:
- /var/lock/dirsrv/
- /var/lock/dirsrv/slapd-TEST-LOCAL/
- name: Ensure IPA server is up an running
service:
name: ipa
state: started

View File

@@ -1 +0,0 @@
../../../roles/

View File

@@ -1,11 +0,0 @@
---
- name: Delegation absent
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" is absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
state: absent

View File

@@ -1,15 +0,0 @@
---
- name: Delegation member absent
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" member attributes employeenumber and employeetype are absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
state: absent

View File

@@ -1,13 +0,0 @@
---
- name: Delegation member present
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" member attribute departmentnumber is present
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- departmentnumber
action: member

View File

@@ -1,15 +0,0 @@
---
- name: Delegation present
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" is present
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
group: managers
membergroup: employees

View File

@@ -1,11 +0,0 @@
---
- name: Playbook to manage DNS forward zone
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure DNS zone is present
- ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
state: absent

View File

@@ -1,16 +0,0 @@
---
- name: Playbook to manage DNS forward zone
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure DNS zone is present
- ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
name: example.com
forwarders:
- ip_address: 8.8.8.8
forwardpolicy: first
skip_overlap_check: true
permission: yes

View File

@@ -1,14 +0,0 @@
---
- name: Playbook to manage DNS forward zone
hosts: ipaserver
become: true
gather_facts: false
tasks:
# Ensure DNS zone is present
- ipadnsforwardzone:
ipaadmin_password: SomeADMINpassword
name: example.com
forwarders:
- ip_address: 192.168.100.123
port: 8063

View File

@@ -1,15 +0,0 @@
---
- name: Playbook to ensure DNS zone exist
hosts: ipaserver
become: true
tasks:
- name: Ensure zone exist, finding zone name from IP address.
ipadnszone:
ipaadmin_password: SomeADMINpassword
name_from_ip: 10.1.2.3/24
register: result
- name: Zone name inferred from `name_from_ip`
debug:
msg: "Zone created: {{ result.dnszone.name }}"

View File

@@ -4,7 +4,7 @@
become: true become: true
tasks: tasks:
- ipahost: ipahost:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: host01.exmaple.com name: host01.exmaple.com
managedby_host: server.exmaple.com managedby_host: server.exmaple.com

View File

@@ -4,7 +4,7 @@
become: true become: true
tasks: tasks:
- ipahost: ipahost:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: host01.exmaple.com name: host01.exmaple.com
managedby_host: server.exmaple.com managedby_host: server.exmaple.com

View File

@@ -4,7 +4,7 @@
become: true become: true
tasks: tasks:
- ipahost: ipahost:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: host01.exmaple.com name: host01.exmaple.com
managedby_host: server.exmaple.com managedby_host: server.exmaple.com

View File

@@ -4,7 +4,6 @@
become: true become: true
tasks: tasks:
- name: Ensure hosts manadegby_host is absent.
ipahost: ipahost:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
hosts: hosts:

View File

@@ -4,7 +4,6 @@
become: true become: true
tasks: tasks:
- name: Ensure hosts manadegby_host is absent.
ipahost: ipahost:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
hosts: hosts:

View File

@@ -4,7 +4,7 @@
become: true become: true
tasks: tasks:
- ipahost: ipahost:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
hosts: hosts:
- name: host01.exmaple.com - name: host01.exmaple.com

View File

@@ -23,3 +23,4 @@
- name: Print generated random password for host02.example.com - name: Print generated random password for host02.example.com
debug: debug:
var: ipahost.host["host02.example.com"].randompassword var: ipahost.host["host02.example.com"].randompassword

View File

@@ -1,12 +0,0 @@
---
- name: Playbook to handle hostgroups
hosts: ipaserver
become: yes
tasks:
- name : Rename host-group from `databases` to `datalake`
ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
rename: datalake
state: renamed

View File

@@ -1,11 +0,0 @@
---
- name: Location absent test
hosts: ipaserver
become: true
tasks:
- name: Ensure location my_location1 is absent
ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
state: absent

View File

@@ -1,10 +0,0 @@
---
- name: Location present test
hosts: ipaserver
become: true
tasks:
- name: Ensure location my_location1 is present
ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1

View File

@@ -1,10 +0,0 @@
---
- name: Privilege absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure privilege "Broad Privilege" is absent
ipaprivilege:
name: Broad Privilege
state: absent

View File

@@ -1,14 +0,0 @@
---
- name: Privilege absent example
hosts: ipaserver
become: true
tasks:
- name: Ensure privilege "Broad Privilege" permission is absent
ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "System: Write IPA Configuration"
action: member
state: absent

View File

@@ -1,15 +0,0 @@
---
- name: Privilege member present example
hosts: ipaserver
become: true
tasks:
- name: Ensure privilege "Broad Privilege" permissions are present
ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "System: Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member

View File

@@ -1,11 +0,0 @@
---
- name: Privilege present example
hosts: ipaserver
become: true
tasks:
- name: Ensure privilege Broad Privilege is present
ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
description: Broad Privilege

View File

@@ -1,11 +0,0 @@
---
- name: Delegation absent
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" is absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
state: absent

View File

@@ -1,15 +0,0 @@
---
- name: Delegation member absent
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" member attributes employeenumber and employeetype are absent
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
state: absent

View File

@@ -1,13 +0,0 @@
---
- name: Delegation member present
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" member attribute departmentnumber is present
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- departmentnumber
action: member

View File

@@ -1,13 +0,0 @@
---
- name: Delegation present
hosts: ipaserver
become: true
tasks:
- name: Ensure delegation "basic manager attributes" is present
ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
permission: read
attribute:
- businesscategory

View File

@@ -7,7 +7,7 @@
tasks: tasks:
# Ensure management host is absent. # Ensure management host is absent.
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
host: "{{ groups.ipaserver[0] }}" host: "{{ groups.ipaserver[0] }}"
action: member action: member

View File

@@ -7,7 +7,7 @@
tasks: tasks:
# Ensure management host is present. # Ensure management host is present.
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
host: "{{ groups.ipaserver[0] }}" host: "{{ groups.ipaserver[0] }}"
action: member action: member

View File

@@ -7,6 +7,6 @@
tasks: tasks:
# Ensure service is absent # Ensure service is absent
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
state: absent state: absent

View File

@@ -7,6 +7,6 @@
tasks: tasks:
# Ensure service is disabled # Ensure service is disabled
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
state: disabled state: disabled

View File

@@ -7,7 +7,7 @@
tasks: tasks:
# Ensure service is present # Ensure service is present
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
certificate: certificate:
- MIICBjCCAW8CFHnm32VcXaUDGfEGdDL/erPSijUAMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwHhcNMjAwMTIzMDA1NjQ2WhcNMjEwMTIyMDA1NjQ2WjBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYrdVmsr7iT3f67DM5bb1osSEe5/c91UUMEIcFq5wrgBhzVfs8iIMDVC1yiUGTsDLJNJc4nb1tUxeR9K5fh25E6n/eWDBP75NStotjAXRU4Ahi3FNRhWFOKesds5xNqgDk5/dY8UekJv2yUblQuZzeF8b2XFrmHuCaYuFctzPfWwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACF+5RS8Ce0HRixGPu4Xd51i+Kzblg++lx8fDJ8GW5G16/Z1AsB72Hc7etJL2PksHlue/xCq6SA9fIfHc4TBNCiWjPSP1NhHJeYyoPiSkcYsqXuxWyoyRLbnAhBVvhoiqZbUt3u3tGB0uMMA0yJvj07mP7Nea2KdBYVH8X1pM0V+ - MIICBjCCAW8CFHnm32VcXaUDGfEGdDL/erPSijUAMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwHhcNMjAwMTIzMDA1NjQ2WhcNMjEwMTIyMDA1NjQ2WjBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYrdVmsr7iT3f67DM5bb1osSEe5/c91UUMEIcFq5wrgBhzVfs8iIMDVC1yiUGTsDLJNJc4nb1tUxeR9K5fh25E6n/eWDBP75NStotjAXRU4Ahi3FNRhWFOKesds5xNqgDk5/dY8UekJv2yUblQuZzeF8b2XFrmHuCaYuFctzPfWwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACF+5RS8Ce0HRixGPu4Xd51i+Kzblg++lx8fDJ8GW5G16/Z1AsB72Hc7etJL2PksHlue/xCq6SA9fIfHc4TBNCiWjPSP1NhHJeYyoPiSkcYsqXuxWyoyRLbnAhBVvhoiqZbUt3u3tGB0uMMA0yJvj07mP7Nea2KdBYVH8X1pM0V+

View File

@@ -7,7 +7,7 @@
tasks: tasks:
# Ensure service is present # Ensure service is present
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/ihavenodns.info name: HTTP/ihavenodns.info
force: yes force: yes
# state: absent # state: absent

View File

@@ -7,6 +7,6 @@
tasks: tasks:
# Ensure service is present # Ensure service is present
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.ansible.com name: HTTP/www.ansible.com
skip_host_check: yes skip_host_check: yes

View File

@@ -7,5 +7,5 @@
tasks: tasks:
# Ensure service is present # Ensure service is present
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com

View File

@@ -6,7 +6,7 @@
tasks: tasks:
- name: Service HTTP/www.example.com members allow_create_keytab absent for users, groups, hosts and hostgroups - name: Service HTTP/www.example.com members allow_create_keytab absent for users, groups, hosts and hostgroups
ipaservice: ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
allow_create_keytab_user: allow_create_keytab_user:
- user01 - user01

View File

@@ -6,7 +6,7 @@
tasks: tasks:
- name: Service HTTP/www.example.com members allow_create_keytab present for users, groups, hosts and hostgroups - name: Service HTTP/www.example.com members allow_create_keytab present for users, groups, hosts and hostgroups
ipaservice: ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
allow_create_keytab_user: allow_create_keytab_user:
- user01 - user01

View File

@@ -6,7 +6,7 @@
tasks: tasks:
- name: Service HTTP/www.example.com members allow_retrieve_keytab absent for users, groups, hosts and hostgroups - name: Service HTTP/www.example.com members allow_retrieve_keytab absent for users, groups, hosts and hostgroups
ipaservice: ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
allow_retrieve_keytab_user: allow_retrieve_keytab_user:
- user01 - user01

View File

@@ -6,7 +6,7 @@
tasks: tasks:
- name: Service HTTP/www.example.com members allow_retrieve_keytab present for users, groups, hosts and hostgroups - name: Service HTTP/www.example.com members allow_retrieve_keytab present for users, groups, hosts and hostgroups
ipaservice: ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
allow_retrieve_keytab_user: allow_retrieve_keytab_user:
- user01 - user01

View File

@@ -7,7 +7,7 @@
tasks: tasks:
# Ensure service certificate is absent # Ensure service certificate is absent
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
certificate: certificate:

View File

@@ -7,7 +7,7 @@
tasks: tasks:
# Ensure service certificate is present # Ensure service certificate is present
- ipaservice: - ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
certificate: certificate:
- MIICBjCCAW8CFHnm32VcXaUDGfEGdDL/erPSijUAMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwHhcNMjAwMTIzMDA1NjQ2WhcNMjEwMTIyMDA1NjQ2WjBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYrdVmsr7iT3f67DM5bb1osSEe5/c91UUMEIcFq5wrgBhzVfs8iIMDVC1yiUGTsDLJNJc4nb1tUxeR9K5fh25E6n/eWDBP75NStotjAXRU4Ahi3FNRhWFOKesds5xNqgDk5/dY8UekJv2yUblQuZzeF8b2XFrmHuCaYuFctzPfWwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACF+5RS8Ce0HRixGPu4Xd51i+Kzblg++lx8fDJ8GW5G16/Z1AsB72Hc7etJL2PksHlue/xCq6SA9fIfHc4TBNCiWjPSP1NhHJeYyoPiSkcYsqXuxWyoyRLbnAhBVvhoiqZbUt3u3tGB0uMMA0yJvj07mP7Nea2KdBYVH8X1pM0V+ - MIICBjCCAW8CFHnm32VcXaUDGfEGdDL/erPSijUAMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwHhcNMjAwMTIzMDA1NjQ2WhcNMjEwMTIyMDA1NjQ2WjBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYrdVmsr7iT3f67DM5bb1osSEe5/c91UUMEIcFq5wrgBhzVfs8iIMDVC1yiUGTsDLJNJc4nb1tUxeR9K5fh25E6n/eWDBP75NStotjAXRU4Ahi3FNRhWFOKesds5xNqgDk5/dY8UekJv2yUblQuZzeF8b2XFrmHuCaYuFctzPfWwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBACF+5RS8Ce0HRixGPu4Xd51i+Kzblg++lx8fDJ8GW5G16/Z1AsB72Hc7etJL2PksHlue/xCq6SA9fIfHc4TBNCiWjPSP1NhHJeYyoPiSkcYsqXuxWyoyRLbnAhBVvhoiqZbUt3u3tGB0uMMA0yJvj07mP7Nea2KdBYVH8X1pM0V+

View File

@@ -6,7 +6,7 @@
tasks: tasks:
- name: Service HTTP/www.exmaple.com member principals host/test.exmaple.com absent - name: Service HTTP/www.exmaple.com member principals host/test.exmaple.com absent
ipaservice: ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
principal: principal:
- host/test.exmaple.com - host/test.exmaple.com

View File

@@ -6,7 +6,7 @@
tasks: tasks:
- name: Service HTTP/www.exmaple.com member principals host/test.exmaple.com present - name: Service HTTP/www.exmaple.com member principals host/test.exmaple.com present
ipaservice: ipaservice:
ipaadmin_password: SomeADMINpassword ipaadmin_password: MyPassword123
name: HTTP/www.example.com name: HTTP/www.example.com
principal: principal:
- host/test.exmaple.com - host/test.exmaple.com

View File

@@ -1,12 +0,0 @@
---
- name: Playbook to create a trust
hosts: ipaserver
become: true
tasks:
- name: ensure the trust is present
ipatrust:
realm: windows.local
admin: Administrator
password: secret_password
state: present

View File

@@ -1,10 +0,0 @@
---
- name: Playbook to delete trust
hosts: ipaserver
become: true
tasks:
- name: ensure the trust is absent
ipatrust:
realm: windows.local
state: absent

View File

@@ -14,4 +14,4 @@
state: retrieved state: retrieved
register: result register: result
- debug: - debug:
msg: "Data: {{ result.vault.data }}" msg: "Data: {{ result.data }}"

View File

@@ -14,4 +14,4 @@
state: retrieved state: retrieved
register: result register: result
- debug: - debug:
msg: "{{ result.vault.data }}" msg: "{{ result.data | b64decode }}"

View File

@@ -506,7 +506,7 @@ class FreeIPABaseModule(AnsibleModule):
# when needed. # when needed.
self.ipa_params = AnsibleFreeIPAParams(self) self.ipa_params = AnsibleFreeIPAParams(self)
def get_ipa_command_args(self, **kwargs): def get_ipa_command_args(self):
""" """
Return a dict to be passed to an IPA command. Return a dict to be passed to an IPA command.
@@ -538,7 +538,7 @@ class FreeIPABaseModule(AnsibleModule):
elif hasattr(self, param_name): elif hasattr(self, param_name):
method = getattr(self, param_name) method = getattr(self, param_name)
if callable(method): if callable(method):
value = method(**kwargs) value = method()
# We don't have a way to guess the value so fail. # We don't have a way to guess the value so fail.
else: else:
@@ -610,16 +610,13 @@ class FreeIPABaseModule(AnsibleModule):
exit the module with proper arguments. exit the module with proper arguments.
""" """
# TODO: shouldn't we also disconnect from api backend?
temp_kdestroy(self.ccache_dir, self.ccache_name)
if exc_type == SystemExit:
raise
if exc_val: if exc_val:
self.fail_json(msg=str(exc_val)) self.fail_json(msg=str(exc_val))
self.exit_json(changed=self.changed, **self.exit_args) # TODO: shouldn't we also disconnect from api backend?
temp_kdestroy(self.ccache_dir, self.ccache_name)
self.exit_json(changed=self.changed, user=self.exit_args)
def get_command_errors(self, command, result): def get_command_errors(self, command, result):
"""Look for erros into command results.""" """Look for erros into command results."""
@@ -658,22 +655,14 @@ class FreeIPABaseModule(AnsibleModule):
except Exception as excpt: except Exception as excpt:
self.fail_json(msg="%s: %s: %s" % (command, name, str(excpt))) self.fail_json(msg="%s: %s: %s" % (command, name, str(excpt)))
else: else:
self.process_command_result(name, command, args, result)
self.get_command_errors(command, result)
def process_command_result(self, name, command, args, result):
"""
Process an API command result.
This method can be overriden in subclasses, and change self.exit_values
to return data in the result for the controller.
"""
if "completed" in result: if "completed" in result:
if result["completed"] > 0: if result["completed"] > 0:
self.changed = True self.changed = True
else: else:
self.changed = True self.changed = True
self.get_command_errors(command, result)
def require_ipa_attrs_change(self, command_args, ipa_attrs): def require_ipa_attrs_change(self, command_args, ipa_attrs):
""" """
Compare given args with current object attributes. Compare given args with current object attributes.

View File

@@ -1,340 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2020 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: ipadelegation
short description: Manage FreeIPA delegations
description: Manage FreeIPA delegations and delegation attributes
options:
ipaadmin_principal:
description: The admin principal.
default: admin
ipaadmin_password:
description: The admin password.
required: false
name:
description: The list of delegation name strings.
required: true
aliases: ["aciname"]
permission:
description: Permissions to grant (read, write). Default is write.
required: false
aliases: ["permissions"]
attribute:
description: Attribute list to which the delegation applies
required: false
aliases: ["attrs"]
membergroup
description: User group to apply delegation to
required: false
aliases: ["memberof"]
group:
description: User group ACI grants access to
required: false
action:
description: Work on delegation or member level.
choices: ["delegation", "member"]
default: delegation
required: false
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
EXAMPLES = """
# Ensure delegation "basic manager attributes" is present
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
permission: read
attribute:
- businesscategory
- employeetype
group: managers
membergroup: employees
# Ensure delegation "basic manager attributes" member attribute
# departmentnumber is present
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- departmentnumber
action: member
# Ensure delegation "basic manager attributes" member attributes
# employeetype and employeenumber are present
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
attribute:
- employeenumber
- employeetype
action: member
state: absent
# Ensure delegation "basic manager attributes" is absent
- ipadelegation:
ipaadmin_password: SomeADMINpassword
name: "basic manager attributes"
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
import six
if six.PY3:
unicode = str
def find_delegation(module, name):
"""Find if a delegation with the given name already exist."""
try:
_result = api_command(module, "delegation_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if delegation name is not found.
return None
else:
return _result["result"]
def gen_args(permission, attribute, membergroup, group):
_args = {}
if permission is not None:
_args["permissions"] = permission
if attribute is not None:
_args["attrs"] = attribute
if membergroup is not None:
_args["memberof"] = membergroup
if group is not None:
_args["group"] = group
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=["aciname"], default=None,
required=True),
# present
permission=dict(required=False, type='list',
aliases=["permissions"], default=None),
attribute=dict(required=False, type='list', aliases=["attrs"],
default=None),
membergroup=dict(type="str", aliases=["memberof"], default=None),
group=dict(type="str", default=None),
action=dict(type="str", default="delegation",
choices=["member", "delegation"]),
# 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
permission = module_params_get(ansible_module, "permission")
attribute = module_params_get(ansible_module, "attribute")
membergroup = module_params_get(ansible_module, "membergroup")
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 delegation be added at a time.")
if action == "member":
invalid = ["permission", "membergroup", "group"]
for x in invalid:
if vars()[x] is not None:
ansible_module.fail_json(
msg="Argument '%s' can not be used with action "
"'%s' and state '%s'" % (x, action, state))
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["permission", "membergroup", "group"]
if action == "delegation":
invalid.append("attribute")
for x in invalid:
if vars()[x] is not None:
ansible_module.fail_json(
msg="Argument '%s' can not be used with action "
"'%s' and state '%s'" % (x, action, state))
if permission is not None:
perm = [p for p in permission if p not in ("read", "write")]
if perm:
ansible_module.fail_json(msg="Invalid permission '%s'" % perm)
if len(set(permission)) != len(permission):
ansible_module.fail_json(
msg="Invalid permission '%s', items are not unique" %
repr(permission))
if attribute is not None:
if len(set(attribute)) != len(attribute):
ansible_module.fail_json(
msg="Invalid attribute '%s', items are not unique" %
repr(attribute))
# 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 delegation exists
res_find = find_delegation(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(permission, attribute, membergroup, group)
if action == "delegation":
# Found the delegation
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, "delegation_mod", args])
else:
commands.append([name, "delegation_add", args])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No delegation '%s'" % name)
if attribute is None:
ansible_module.fail_json(msg="No attributes given")
# New attribute list (add given ones to find result)
# Make list with unique entries
attrs = list(set(list(res_find["attrs"]) + attribute))
if len(attrs) > len(res_find["attrs"]):
commands.append([name, "delegation_mod",
{"attrs": attrs}])
elif state == "absent":
if action == "delegation":
if res_find is not None:
commands.append([name, "delegation_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No delegation '%s'" % name)
if attribute is None:
ansible_module.fail_json(msg="No attributes given")
# New attribute list (remove given ones from find result)
# Make list with unique entries
attrs = list(set(res_find["attrs"]) - set(attribute))
if len(attrs) < 1:
ansible_module.fail_json(
msg="At minimum one attribute is needed.")
# Entries New number of attributes is smaller
if len(attrs) < len(res_find["attrs"]):
commands.append([name, "delegation_mod",
{"attrs": attrs}])
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)))
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

@@ -106,7 +106,6 @@ RETURN = '''
from ansible.module_utils.basic import AnsibleModule 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, \ 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 module_params_get
@@ -151,7 +150,7 @@ def forwarder_list(forwarders):
formatter = "{ip_address} port {port}" formatter = "{ip_address} port {port}"
else: else:
formatter = "{ip_address}" formatter = "{ip_address}"
fwd_list.append(to_text(formatter.format(**forwarder))) fwd_list.append(formatter.format(**forwarder))
return fwd_list return fwd_list

View File

@@ -41,14 +41,8 @@ options:
name: name:
description: The zone name string. description: The zone name string.
required: true required: true
type: list
alises: ["zone_name"]
name_from_ip:
description: |
Derive zone name from reverse of IP (PTR).
Can only be used with `state: present`.
required: false
type: str type: str
alises: ["zone_name"]
forwarders: forwarders:
description: The list of global DNS forwarders. description: The list of global DNS forwarders.
required: false required: false
@@ -194,14 +188,6 @@ EXAMPLES = """
""" """
RETURN = """ RETURN = """
dnszone:
description: DNS Zone dict with zone name infered from `name_from_ip`.
returned:
If `state` is `present`, `name_from_ip` is used, and a zone was created.
options:
name:
description: The name of the zone created, inferred from `name_from_ip`.
returned: always
""" """
from ipapython.dnsutil import DNSName # noqa: E402 from ipapython.dnsutil import DNSName # noqa: E402
@@ -211,12 +197,6 @@ from ansible.module_utils.ansible_freeipa_module import (
is_ipv6_addr, is_ipv6_addr,
is_valid_port, is_valid_port,
) # noqa: E402 ) # noqa: E402
import netaddr
import six
if six.PY3:
unicode = str
class DNSZoneModule(FreeIPABaseModule): class DNSZoneModule(FreeIPABaseModule):
@@ -288,7 +268,7 @@ class DNSZoneModule(FreeIPABaseModule):
return True return True
def get_ipa_nsec3paramrecord(self, **kwargs): def get_ipa_nsec3paramrecord(self):
nsec3param_rec = self.ipa_params.nsec3param_rec nsec3param_rec = self.ipa_params.nsec3param_rec
if nsec3param_rec is not None: if nsec3param_rec is not None:
error_msg = ( error_msg = (
@@ -300,7 +280,7 @@ class DNSZoneModule(FreeIPABaseModule):
self.fail_json(msg=error_msg) self.fail_json(msg=error_msg)
return nsec3param_rec return nsec3param_rec
def get_ipa_idnsforwarders(self, **kwargs): def get_ipa_idnsforwarders(self):
if self.ipa_params.forwarders is not None: if self.ipa_params.forwarders is not None:
forwarders = [] forwarders = []
for forwarder in self.ipa_params.forwarders: for forwarder in self.ipa_params.forwarders:
@@ -324,14 +304,14 @@ class DNSZoneModule(FreeIPABaseModule):
return forwarders return forwarders
def get_ipa_idnsallowtransfer(self, **kwargs): def get_ipa_idnsallowtransfer(self):
if self.ipa_params.allow_transfer is not None: if self.ipa_params.allow_transfer is not None:
error_msg = "Invalid ip_address for DNS allow_transfer: %s" error_msg = "Invalid ip_address for DNS allow_transfer: %s"
self.validate_ips(self.ipa_params.allow_transfer, error_msg) self.validate_ips(self.ipa_params.allow_transfer, error_msg)
return (";".join(self.ipa_params.allow_transfer) or "none") + ";" return (";".join(self.ipa_params.allow_transfer) or "none") + ";"
def get_ipa_idnsallowquery(self, **kwargs): def get_ipa_idnsallowquery(self):
if self.ipa_params.allow_query is not None: if self.ipa_params.allow_query is not None:
error_msg = "Invalid ip_address for DNS allow_query: %s" error_msg = "Invalid ip_address for DNS allow_query: %s"
self.validate_ips(self.ipa_params.allow_query, error_msg) self.validate_ips(self.ipa_params.allow_query, error_msg)
@@ -354,122 +334,70 @@ class DNSZoneModule(FreeIPABaseModule):
return ".".join((name, domain)) return ".".join((name, domain))
def get_ipa_idnssoarname(self, **kwargs): def get_ipa_idnssoarname(self):
if self.ipa_params.admin_email is not None: if self.ipa_params.admin_email is not None:
return DNSName( return DNSName(
self._replace_at_symbol_in_rname(self.ipa_params.admin_email) self._replace_at_symbol_in_rname(self.ipa_params.admin_email)
) )
def get_ipa_idnssoamname(self, **kwargs): def get_ipa_idnssoamname(self):
if self.ipa_params.name_server is not None: if self.ipa_params.name_server is not None:
return DNSName(self.ipa_params.name_server) return DNSName(self.ipa_params.name_server)
def get_ipa_skip_overlap_check(self, **kwargs): def get_ipa_skip_overlap_check(self):
zone = kwargs.get('zone') if not self.zone and self.ipa_params.skip_overlap_check is not None:
if not zone and self.ipa_params.skip_overlap_check is not None:
return self.ipa_params.skip_overlap_check return self.ipa_params.skip_overlap_check
def get_ipa_skip_nameserver_check(self, **kwargs): def get_ipa_skip_nameserver_check(self):
zone = kwargs.get('zone') if not self.zone and self.ipa_params.skip_nameserver_check is not None:
if not zone and self.ipa_params.skip_nameserver_check is not None:
return self.ipa_params.skip_nameserver_check return self.ipa_params.skip_nameserver_check
def __reverse_zone_name(self, ipaddress):
"""
Infer reverse zone name from an ip address.
This function uses the same heuristics as FreeIPA to infer the zone
name from ip.
"""
try:
ip = netaddr.IPAddress(str(ipaddress))
except (netaddr.AddrFormatError, ValueError):
net = netaddr.IPNetwork(ipaddress)
items = net.ip.reverse_dns.split('.')
prefixlen = net.prefixlen
ip_version = net.version
else:
items = ip.reverse_dns.split('.')
prefixlen = 24 if ip.version == 4 else 64
ip_version = ip.version
if ip_version == 4:
return u'.'.join(items[4 - prefixlen // 8:])
elif ip_version == 6:
return u'.'.join(items[32 - prefixlen // 4:])
else:
self.fail_json(msg="Invalid IP version for reverse zone.")
def get_zone(self, zone_name): def get_zone(self, zone_name):
get_zone_args = {"idnsname": zone_name, "all": True} get_zone_args = {"idnsname": zone_name, "all": True}
response = self.api_command("dnszone_find", args=get_zone_args) response = self.api_command("dnszone_find", args=get_zone_args)
zone = None
is_zone_active = False
if response["count"] == 1: if response["count"] == 1:
zone = response["result"][0] self.zone = response["result"][0]
is_zone_active = zone.get("idnszoneactive") == ["TRUE"] self.is_zone_active = self.zone.get("idnszoneactive") == ["TRUE"]
return self.zone
return zone, is_zone_active # Zone doesn't exist yet
self.zone = None
self.is_zone_active = False
def get_zone_names(self): @property
zone_names = self.__get_zone_names_from_params() def zone_name(self):
if len(zone_names) > 1 and self.ipa_params.state != "absent":
self.fail_json(
msg=("Please provide a single name. Multiple values for 'name'"
"can only be supplied for state 'absent'.")
)
return zone_names
def __get_zone_names_from_params(self):
if not self.ipa_params.name:
return [self.__reverse_zone_name(self.ipa_params.name_from_ip)]
return self.ipa_params.name return self.ipa_params.name
def check_ipa_params(self):
if not self.ipa_params.name and not self.ipa_params.name_from_ip:
self.fail_json(
msg="Either `name` or `name_from_ip` must be provided."
)
if self.ipa_params.state != "present" and self.ipa_params.name_from_ip:
self.fail_json(
msg=(
"Cannot use argument `name_from_ip` with state `%s`."
% self.ipa_params.state
)
)
def define_ipa_commands(self): def define_ipa_commands(self):
for zone_name in self.get_zone_names():
# Look for existing zone in IPA # Look for existing zone in IPA
zone, is_zone_active = self.get_zone(zone_name) self.get_zone(self.zone_name)
args = self.get_ipa_command_args(zone=zone) args = self.get_ipa_command_args()
just_added = False just_added = False
if self.ipa_params.state in ["present", "enabled", "disabled"]: if self.ipa_params.state in ["present", "enabled", "disabled"]:
if not zone: if not self.zone:
# Since the zone doesn't exist we just create it # Since the zone doesn't exist we just create it
# with given args # with given args
self.add_ipa_command("dnszone_add", zone_name, args) self.add_ipa_command("dnszone_add", self.zone_name, args)
is_zone_active = True self.is_zone_active = True
just_added = True just_added = True
else: else:
# Zone already exist so we need to verify if given args # Zone already exist so we need to verify if given args
# matches the current config. If not we updated it. # matches the current config. If not we updated it.
if self.require_ipa_attrs_change(args, zone): if self.require_ipa_attrs_change(args, self.zone):
self.add_ipa_command("dnszone_mod", zone_name, args) self.add_ipa_command("dnszone_mod", self.zone_name, args)
if self.ipa_params.state == "enabled" and not is_zone_active: if self.ipa_params.state == "enabled" and not self.is_zone_active:
self.add_ipa_command("dnszone_enable", zone_name) self.add_ipa_command("dnszone_enable", self.zone_name)
if self.ipa_params.state == "disabled" and is_zone_active: if self.ipa_params.state == "disabled" and self.is_zone_active:
self.add_ipa_command("dnszone_disable", zone_name) self.add_ipa_command("dnszone_disable", self.zone_name)
if self.ipa_params.state == "absent": if self.ipa_params.state == "absent":
if zone: if self.zone:
self.add_ipa_command("dnszone_del", zone_name) self.add_ipa_command("dnszone_del", self.zone_name)
# Due to a bug in FreeIPA dnszone-add won't set # Due to a bug in FreeIPA dnszone-add won't set
# SOA Serial. The good news is that dnszone-mod does the job. # SOA Serial. The good news is that dnszone-mod does the job.
@@ -480,15 +408,7 @@ class DNSZoneModule(FreeIPABaseModule):
args = { args = {
"idnssoaserial": self.ipa_params.serial, "idnssoaserial": self.ipa_params.serial,
} }
self.add_ipa_command("dnszone_mod", zone_name, args) self.add_ipa_command("dnszone_mod", self.zone_name, args)
def process_command_result(self, name, command, args, result):
super(DNSZoneModule, self).process_command_result(
name, command, args, result
)
if command == "dnszone_add" and self.ipa_params.name_from_ip:
dnszone_exit_args = self.exit_args.setdefault('dnszone', {})
dnszone_exit_args['name'] = name
def get_argument_spec(): def get_argument_spec():
@@ -506,9 +426,8 @@ def get_argument_spec():
ipaadmin_principal=dict(type="str", default="admin"), ipaadmin_principal=dict(type="str", default="admin"),
ipaadmin_password=dict(type="str", required=False, no_log=True), ipaadmin_password=dict(type="str", required=False, no_log=True),
name=dict( name=dict(
type="list", default=None, required=False, aliases=["zone_name"] type="str", default=None, required=True, aliases=["zone_name"]
), ),
name_from_ip=dict(type="str", default=None, required=False),
forwarders=dict( forwarders=dict(
type="list", type="list",
default=None, default=None,
@@ -548,11 +467,7 @@ def get_argument_spec():
def main(): def main():
DNSZoneModule( DNSZoneModule(argument_spec=get_argument_spec()).ipa_run()
argument_spec=get_argument_spec(),
mutually_exclusive=[["name", "name_from_ip"]],
required_one_of=[["name", "name_from_ip"]],
).ipa_run()
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -70,12 +70,6 @@ options:
- Only usable with IPA versions 4.8.4 and up. - Only usable with IPA versions 4.8.4 and up.
required: false required: false
type: list type: list
rename:
description:
- Rename hostgroup to the given name.
- Only usable with IPA versions 4.8.7 and up.
required: false
aliases: ["new_name"]
action: action:
description: Work on hostgroup or member level description: Work on hostgroup or member level
default: hostgroup default: hostgroup
@@ -83,7 +77,7 @@ options:
state: state:
description: State to ensure description: State to ensure
default: present default: present
choices: ["present", "absent", "renamed"] choices: ["present", "absent"]
author: author:
- Thomas Woerner - Thomas Woerner
""" """
@@ -122,12 +116,6 @@ EXAMPLES = """
action: member action: member
state: absent state: absent
# Rename hostgroup
- ipahostgroup:
ipaadmin_password: SomeADMINpassword
name: databases
rename: datalake
# Ensure host-group databases is absent # Ensure host-group databases is absent
- ipahostgroup: - ipahostgroup:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
@@ -141,7 +129,7 @@ RETURN = """
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \ 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, api_check_command, api_check_param module_params_get, gen_add_del_lists, api_check_command
def find_hostgroup(module, name): def find_hostgroup(module, name):
@@ -161,14 +149,12 @@ def find_hostgroup(module, name):
return None return None
def gen_args(description, nomembers, rename): def gen_args(description, nomembers):
_args = {} _args = {}
if description is not None: if description is not None:
_args["description"] = description _args["description"] = description
if nomembers is not None: if nomembers is not None:
_args["nomembers"] = nomembers _args["nomembers"] = nomembers
if rename is not None:
_args["rename"] = rename
return _args return _args
@@ -200,13 +186,11 @@ def main():
membermanager_user=dict(required=False, type='list', default=None), membermanager_user=dict(required=False, type='list', default=None),
membermanager_group=dict(required=False, type='list', membermanager_group=dict(required=False, type='list',
default=None), default=None),
rename=dict(required=False, type='str', default=None,
aliases=["new_name"]),
action=dict(type="str", default="hostgroup", action=dict(type="str", default="hostgroup",
choices=["member", "hostgroup"]), choices=["member", "hostgroup"]),
# state # state
state=dict(type="str", default="present", state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]), choices=["present", "absent"]),
), ),
supports_check_mode=True, supports_check_mode=True,
) )
@@ -231,7 +215,6 @@ def main():
"membermanager_user") "membermanager_user")
membermanager_group = module_params_get(ansible_module, membermanager_group = module_params_get(ansible_module,
"membermanager_group") "membermanager_group")
rename = module_params_get(ansible_module, "rename")
action = module_params_get(ansible_module, "action") action = module_params_get(ansible_module, "action")
# state # state
state = module_params_get(ansible_module, "state") state = module_params_get(ansible_module, "state")
@@ -242,38 +225,19 @@ def main():
if len(names) != 1: if len(names) != 1:
ansible_module.fail_json( ansible_module.fail_json(
msg="Only one hostgroup can be added at a time.") msg="Only one hostgroup can be added at a time.")
invalid = ["rename"]
if action == "member": if action == "member":
invalid.extend(["description", "nomembers"]) invalid = ["description", "nomembers"]
for x in invalid: for x in invalid:
if vars()[x] is not None: if vars()[x] is not None:
ansible_module.fail_json( ansible_module.fail_json(
msg="Argument '%s' can not be used with action " msg="Argument '%s' can not be used with action "
"'%s'" % (x, action)) "'%s'" % (x, action))
if state == "renamed":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one hostgroup can be added at a time.")
if action == "member":
ansible_module.fail_json(
msg="Action '%s' can not be used with state '%s'" %
(action, state))
invalid = [
"description", "nomembers", "host", "hostgroup",
"membermanager_user", "membermanager_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))
if state == "absent": if state == "absent":
if len(names) < 1: if len(names) < 1:
ansible_module.fail_json( ansible_module.fail_json(
msg="No name given.") msg="No name given.")
invalid = ["description", "nomembers", "rename"] invalid = ["description", "nomembers"]
if action == "hostgroup": if action == "hostgroup":
invalid.extend(["host", "hostgroup"]) invalid.extend(["host", "hostgroup"])
for x in invalid: for x in invalid:
@@ -302,10 +266,6 @@ def main():
msg="Managing a membermanager user or group is not supported " msg="Managing a membermanager user or group is not supported "
"by your IPA version" "by your IPA version"
) )
has_mod_rename = api_check_param("hostgroup_mod", "rename")
if not has_mod_rename and rename is not None:
ansible_module.fail_json(
msg="Renaming hostgroups is not supported by your IPA version")
commands = [] commands = []
@@ -316,7 +276,7 @@ def main():
# Create command # Create command
if state == "present": if state == "present":
# Generate args # Generate args
args = gen_args(description, nomembers, rename) args = gen_args(description, nomembers)
if action == "hostgroup": if action == "hostgroup":
# Found the hostgroup # Found the hostgroup
@@ -415,22 +375,6 @@ def main():
}] }]
) )
elif state == "renamed":
if res_find is not None:
if rename != name:
commands.append(
[name, "hostgroup_mod", {"rename": rename}]
)
else:
# If a hostgroup with the desired name exists, do nothing.
new_find = find_hostgroup(ansible_module, rename)
if new_find is None:
# Fail only if the either hostsgroups do not exist.
ansible_module.fail_json(
msg="Attribute `rename` can not be used, unless "
"hostgroup exists."
)
elif state == "absent": elif state == "absent":
if action == "hostgroup": if action == "hostgroup":
if res_find is not None: if res_find is not None:

View File

@@ -1,220 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2020 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: ipalocation
short description: Manage FreeIPA location
description: Manage FreeIPA location
options:
ipaadmin_principal:
description: The admin principal.
default: admin
ipaadmin_password:
description: The admin password.
required: false
name:
description: The list of location name strings.
required: true
aliases: ["idnsname"]
description:
description: The IPA location string
required: false
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
EXAMPLES = """
# Ensure location my_location1 is present
- ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
description: My location 1
# Ensure location my_location1 is absent
- ipalocation:
ipaadmin_password: SomeADMINpassword
name: my_location1
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
import six
if six.PY3:
unicode = str
def find_location(module, name):
"""Find if a location with the given name already exist."""
try:
_result = api_command(module, "location_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if location name is not found.
return None
else:
return _result["result"]
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=["idnsname"],
default=None, required=True),
# present
description=dict(required=False, 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 = 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")
# state
state = module_params_get(ansible_module, "state")
# Check parameters
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one location be added 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:
# Make sure location exists
res_find = find_location(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(description)
# Found the location
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, "location_mod", args])
else:
commands.append([name, "location_add", args])
elif state == "absent":
if res_find is not None:
commands.append([name, "location_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, 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)))
except Exception as e:
ansible_module.fail_json(msg=str(e))
finally:
temp_kdestroy(ccache_dir, ccache_name)
# Done
ansible_module.exit_json(changed=changed, **exit_args)
if __name__ == "__main__":
main()

View File

@@ -1,357 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Rafael Guterres Jeffman <rjeffman@redhat.com>
#
# Copyright (C) 2020 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-freeipa module to manage FreeIPA privileges."""
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = """
---
module: ipaprivilege
short description: Manage FreeIPA privilege
description: Manage FreeIPA privilege and privilege members
options:
ipaadmin_principal:
description: The admin principal.
default: admin
ipaadmin_password:
description: The admin password.
required: false
name:
description: The list of privilege name strings.
required: true
aliases: ["cn"]
description:
description: Privilege description
required: false
rename:
description: Rename the privilege object.
required: false
aliases: ["new_name"]
permission:
description: Permissions to be added to the privilege.
required: false
action:
description: Work on privilege or member level.
choices: ["privilege", "member"]
default: privilege
required: false
state:
description: The state to ensure.
choices: ["present", "absent", "renamed"]
default: present
required: true
"""
EXAMPLES = """
# Ensure privilege "Broad Privilege" is present
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
description: Broad Privilege
# Ensure privilege "Broad Privilege" has permissions set
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "Write IPA Configuration"
- "System: Write DNS Configuration"
- "System: Update DNS Entries"
action: member
# Ensure privilege member permission 'Write IPA Configuration' is absent
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
permission:
- "Write IPA Configuration"
action: member
state: absent
# Rename privilege "Broad Privilege" to "DNS Special Privilege"
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: Broad Privilege
rename: DNS Special Privilege
state: renamed
# Ensure privilege "DNS Special Privilege" is absent
- ipaprivilege:
ipaadmin_password: SomeADMINpassword
name: DNS Special Privilege
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, gen_add_del_lists
import six
if six.PY3:
unicode = str
def find_privilege(module, name):
"""Find if a privilege with the given name already exist."""
try:
_result = api_command(module, "privilege_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if privilege name is not found.
return None
else:
return _result["result"]
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),
rename=dict(required=False, type='str', default=None,
aliases=["new_name"], ),
permission=dict(required=False, type='list', default=None),
action=dict(type="str", default="privilege",
choices=["member", "privilege"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent", "renamed"]),
),
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")
permission = module_params_get(ansible_module, "permission")
rename = module_params_get(ansible_module, "rename")
action = module_params_get(ansible_module, "action")
# state
state = module_params_get(ansible_module, "state")
# Check parameters
invalid = []
if state == "present":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one privilege be added at a time.")
if action == "member":
invalid = ["description"]
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["description", "rename"]
if action == "privilege":
invalid.append("permission")
if state == "renamed":
if len(names) != 1:
ansible_module.fail_json(
msg="Only one privilege be added at a time.")
invalid = ["description", "permission"]
if action != "privilege":
ansible_module.fail_json(
msg="Action '%s' can not be used with state '%s'"
% (action, state))
for x in invalid:
if vars()[x] is not None:
ansible_module.fail_json(
msg="Argument '%s' can not be used with action "
"'%s' and state '%s'" % (x, action, 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 privilege exists
res_find = find_privilege(ansible_module, name)
# Create command
if state == "present":
args = {}
if description:
args['description'] = description
if action == "privilege":
# Found the privilege
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, "privilege_mod", args])
else:
commands.append([name, "privilege_add", args])
member_args = {}
if permission:
member_args['permission'] = permission
if not compare_args_ipa(ansible_module, member_args,
res_find):
# Generate addition and removal lists
permission_add, permission_del = gen_add_del_lists(
permission, res_find.get("member_permission"))
# Add members
if len(permission_add) > 0:
commands.append([name, "privilege_add_permission",
{
"permission": permission_add,
}])
# Remove members
if len(permission_del) > 0:
commands.append([
name,
"privilege_remove_permission",
{"permission": permission_del}
])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No privilege '%s'" % name)
if permission is None:
ansible_module.fail_json(msg="No permission given")
commands.append([name, "privilege_add_permission",
{"permission": permission}])
elif state == "absent":
if action == "privilege":
if res_find is not None:
commands.append([name, "privilege_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No privilege '%s'" % name)
if permission is None:
ansible_module.fail_json(msg="No permission given")
commands.append([name, "privilege_remove_permission",
{
"permission": permission,
}])
elif state == "renamed":
if not rename:
ansible_module.fail_json(msg="No rename value given.")
if res_find is None:
ansible_module.fail_json(
msg="No privilege found to be renamed: '%s'" % (name))
if name != rename:
commands.append(
[name, "privilege_mod", {"rename": rename}])
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 = []
for failed_item in result.get("failed", []):
failed = result["failed"][failed_item]
for member_type in failed:
for member, failure in failed[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

@@ -30,9 +30,9 @@ ANSIBLE_METADATA = {
DOCUMENTATION = """ DOCUMENTATION = """
--- ---
module: iparole module: ipaservice
short description: Manage FreeIPA role short description: Manage FreeIPA service
description: Manage FreeIPA role description: Manage FreeIPA service
options: options:
ipaadmin_principal: ipaadmin_principal:
description: The admin principal. description: The admin principal.
@@ -66,7 +66,7 @@ options:
description: List of services. description: List of services.
required: false required: false
action: action:
description: Work on role or member level. description: Work on service or member level.
choices: ["role", "member"] choices: ["role", "member"]
default: role default: role
required: false required: false

View File

@@ -1,323 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Thomas Woerner <twoerner@redhat.com>
#
# Copyright (C) 2020 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: ipaselfservice
short description: Manage FreeIPA selfservices
description: Manage FreeIPA selfservices and selfservice attributes
options:
ipaadmin_principal:
description: The admin principal.
default: admin
ipaadmin_password:
description: The admin password.
required: false
name:
description: The list of selfservice name strings.
required: true
aliases: ["aciname"]
permission:
description: Permissions to grant (read, write). Default is write.
required: false
aliases: ["permissions"]
attribute:
description: Attribute list to which the selfservice applies
required: false
aliases: ["attrs"]
action:
description: Work on selfservice or member level.
choices: ["selfservice", "member"]
default: selfservice
required: false
state:
description: The state to ensure.
choices: ["present", "absent"]
default: present
required: true
"""
EXAMPLES = """
# Ensure selfservice "Users can manage their own name details" is present
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
permission: read
attribute:
- title
- initials
# Ensure selfservice "Users can manage their own name details" member
# attribute departmentnumber is present
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
attribute:
- initials
action: member
# Ensure selfservice "Users can manage their own name details" member
# attributes employeetype and employeenumber are present
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
attribute:
- title
- initials
action: member
state: absent
# Ensure selfservice "Users can manage their own name details" is absent
- ipaselfservice:
ipaadmin_password: SomeADMINpassword
name: "Users can manage their own name details"
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
import six
if six.PY3:
unicode = str
def find_selfservice(module, name):
"""Find if a selfservice with the given name already exist."""
try:
_result = api_command(module, "selfservice_show", name, {"all": True})
except Exception: # pylint: disable=broad-except
# An exception is raised if selfservice name is not found.
return None
else:
return _result["result"]
def gen_args(permission, attribute):
_args = {}
if permission is not None:
_args["permissions"] = permission
if attribute is not None:
_args["attrs"] = attribute
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=["aciname"], default=None,
required=True),
# present
permission=dict(required=False, type='list',
aliases=["permissions"], default=None),
attribute=dict(required=False, type='list', aliases=["attrs"],
default=None),
action=dict(type="str", default="selfservice",
choices=["member", "selfservice"]),
# 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
permission = module_params_get(ansible_module, "permission")
attribute = module_params_get(ansible_module, "attribute")
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 selfservice be added at a time.")
if action == "member":
invalid = ["permission"]
for x in invalid:
if vars()[x] is not None:
ansible_module.fail_json(
msg="Argument '%s' can not be used with action "
"'%s' and state '%s'" % (x, action, state))
if state == "absent":
if len(names) < 1:
ansible_module.fail_json(msg="No name given.")
invalid = ["permission"]
if action == "selfservice":
invalid.append("attribute")
for x in invalid:
if vars()[x] is not None:
ansible_module.fail_json(
msg="Argument '%s' can not be used with action "
"'%s' and state '%s'" % (x, action, state))
if permission is not None:
perm = [p for p in permission if p not in ("read", "write")]
if perm:
ansible_module.fail_json(msg="Invalid permission '%s'" % perm)
if len(set(permission)) != len(permission):
ansible_module.fail_json(
msg="Invalid permission '%s', items are not unique" %
repr(permission))
if attribute is not None:
if len(set(attribute)) != len(attribute):
ansible_module.fail_json(
msg="Invalid attribute '%s', items are not unique" %
repr(attribute))
# 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 selfservice exists
res_find = find_selfservice(ansible_module, name)
# Create command
if state == "present":
# Generate args
args = gen_args(permission, attribute)
if action == "selfservice":
# Found the selfservice
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, "selfservice_mod", args])
else:
commands.append([name, "selfservice_add", args])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No selfservice '%s'" % name)
if attribute is None:
ansible_module.fail_json(msg="No attributes given")
# New attribute list (add given ones to find result)
# Make list with unique entries
attrs = list(set(list(res_find["attrs"]) + attribute))
if len(attrs) > len(res_find["attrs"]):
commands.append([name, "selfservice_mod",
{"attrs": attrs}])
elif state == "absent":
if action == "selfservice":
if res_find is not None:
commands.append([name, "selfservice_del", {}])
elif action == "member":
if res_find is None:
ansible_module.fail_json(
msg="No selfservice '%s'" % name)
if attribute is None:
ansible_module.fail_json(msg="No attributes given")
# New attribute list (remove given ones from find result)
# Make list with unique entries
attrs = list(set(res_find["attrs"]) - set(attribute))
if len(attrs) < 1:
ansible_module.fail_json(
msg="At minimum one attribute is needed.")
# Entries New number of attributes is smaller
if len(attrs) < len(res_find["attrs"]):
commands.append([name, "selfservice_mod",
{"attrs": attrs}])
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)))
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

@@ -460,7 +460,7 @@ def main():
allow_retrieve_keytab_group = module_params_get( allow_retrieve_keytab_group = module_params_get(
ansible_module, "allow_retrieve_keytab_group") ansible_module, "allow_retrieve_keytab_group")
allow_retrieve_keytab_host = module_params_get( allow_retrieve_keytab_host = module_params_get(
ansible_module, "allow_retrieve_keytab_host") ansible_module, "allow_create_keytab_host")
allow_retrieve_keytab_hostgroup = module_params_get( allow_retrieve_keytab_hostgroup = module_params_get(
ansible_module, "allow_retrieve_keytab_hostgroup") ansible_module, "allow_retrieve_keytab_hostgroup")
delete_continue = module_params_get(ansible_module, "delete_continue") delete_continue = module_params_get(ansible_module, "delete_continue")
@@ -727,7 +727,7 @@ def main():
# Allow retrieve keytab # Allow retrieve keytab
if len(allow_retrieve_keytab_user_add) > 0 or \ if len(allow_retrieve_keytab_user_add) > 0 or \
len(allow_retrieve_keytab_group_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 or \
len(allow_retrieve_keytab_hostgroup_add) > 0: len(allow_retrieve_keytab_hostgroup_add) > 0:
commands.append( commands.append(
[name, "service_allow_retrieve_keytab", [name, "service_allow_retrieve_keytab",

View File

@@ -1,274 +0,0 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Rob Verduijn <rob.verduijn@gmail.com>
#
# Copyright (C) 2019 By Rob Verduijn
# 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/>.
from ansible.module_utils.ansible_freeipa_module import temp_kinit, \
temp_kdestroy, valid_creds, api_connect, api_command, module_params_get
from ansible.module_utils.basic import AnsibleModule
ANSIBLE_METADATA = {'metadata_version': '1.1',
'supported_by': 'community',
'status': ['preview'],
}
DOCUMENTATION = """
---
module: ipatrust
short_description: Manage FreeIPA Domain Trusts.
description: Manage FreeIPA Domain Trusts.
options:
realm:
description:
- Realm name
required: true
trust_type:
description:
- Trust type (ad for Active Directory, default)
default: ad
required: true
admin:
description:
- Active Directory domain administrator
required: false
password:
description:
- Active Directory domain administrator's password
required: false
server:
description:
- Domain controller for the Active Directory domain (optional)
required: false
trust_secret:
description:
- Shared secret for the trust
required: false
base_id:
description:
- First Posix ID of the range reserved for the trusted domain
required: false
range_size:
description:
- Size of the ID range reserved for the trusted domain
range_type:
description:
- Type of trusted domain ID range, one of ipa-ad-trust, ipa-ad-trust-posix
default: ipa-ad-trust
required: false
two_way:
description:
- Establish bi-directional trust. By default trust is inbound one-way only.
default: false
required: false
choices: ["true", "false"]
external:
description:
- Establish external trust to a domain in another forest.
- The trust is not transitive beyond the domain.
default: false
required: false
choices: ["true", "false"]
state:
description: State to ensure
default: present
required: true
choices: ["present", "absent"]
author:
- Rob Verduijn
"""
EXAMPLES = """
# add ad-trust
- ipatrust:
realm: ad.example.test
trust_type: ad
admin: Administrator
password: Welcome2020!
state: present
# delete ad-trust
- ipatrust:
realm: ad.example.test
state: absent
"""
RETURN = """
"""
def find_trust(module, realm):
_args = {
"all": True,
"cn": realm,
}
_result = api_command(module, "trust_find", realm, _args)
if len(_result["result"]) > 1:
module.fail_json(msg="There is more than one realm '%s'" % (realm))
elif len(_result["result"]) == 1:
return _result["result"][0]
else:
return None
def del_trust(module, realm):
_args = {}
_result = api_command(module, "trust_del", realm, _args)
if len(_result["result"]["failed"]) > 0:
module.fail_json(
msg="Trust deletion has failed for '%s'" % (realm))
else:
return None
def add_trust(module, realm, args):
_args = args
_result = api_command(module, "trust_add", realm, _args)
if "cn" not in _result["result"]:
module.fail_json(
msg="Trust add has failed for '%s'" % (realm))
else:
return None
def gen_args(trust_type, admin, password, server, trust_secret, base_id,
range_size, range_type, two_way, external):
_args = {}
if trust_type is not None:
_args["trust_type"] = trust_type
if admin is not None:
_args["realm_admin"] = admin
if password is not None:
_args["realm_passwd"] = password
if server is not None:
_args["realm_server"] = server
if trust_secret is not None:
_args["trust_secret"] = trust_secret
if base_id is not None:
_args["base_id"] = base_id
if range_size is not None:
_args["range_size"] = range_size
if two_way is not None:
_args["bidirectional"] = two_way
if external is not None:
_args["external"] = external
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),
realm=dict(type="str", default=None, required=True),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
# present
trust_type=dict(type="str", default="ad", required=False),
admin=dict(type="str", default=None, required=False),
password=dict(type="str", default=None,
required=False, no_log=True),
server=dict(type="str", default=None, required=False),
trust_secret=dict(type="str", default=None,
required=False, no_log=True),
base_id=dict(type="int", default=None, required=False),
range_size=dict(type="int", default=200000, required=False),
range_type=dict(type="str", default="ipa-ad-trust",
required=False, choices=["ipa-ad-trust-posix",
"ipa-ad-trust"]),
two_way=dict(type="bool", default=False, required=False),
external=dict(type="bool", default=False, required=False),
),
mutually_exclusive=[["trust_secret", "admin"]],
required_together=[["admin", "password"]],
supports_check_mode=True
)
ansible_module._ansible_debug = True
# general
ipaadmin_principal = module_params_get(
ansible_module, "ipaadmin_principal")
ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
realm = module_params_get(ansible_module, "realm")
# state
state = module_params_get(ansible_module, "state")
# trust
trust_type = module_params_get(ansible_module, "trust_type")
admin = module_params_get(ansible_module, "admin")
password = module_params_get(ansible_module, "password")
server = module_params_get(ansible_module, "server")
trust_secret = module_params_get(ansible_module, "trust_secret")
base_id = module_params_get(ansible_module, "base_id")
range_size = module_params_get(ansible_module, "range_size")
range_type = module_params_get(ansible_module, "range_type")
two_way = module_params_get(ansible_module, "two_way")
external = module_params_get(ansible_module, "external")
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()
res_find = find_trust(ansible_module, realm)
if state == "absent":
if res_find is not None:
del_trust(ansible_module, realm)
changed = True
elif res_find is None:
if admin is None and trust_secret is None:
ansible_module.fail_json(
msg="one of admin or trust_secret is required when state "
"is present")
else:
args = gen_args(trust_type, admin, password, server,
trust_secret, base_id, range_size, range_type,
two_way, external)
add_trust(ansible_module, realm, args)
changed = True
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

@@ -243,7 +243,7 @@ EXAMPLES = """
state: retrieved state: retrieved
register: result register: result
- debug: - debug:
msg: "{{ result.vault.data }}" msg: "{{ result.data }}"
# Change password of a symmetric vault # Change password of a symmetric vault
- ipavault: - ipavault:
@@ -267,7 +267,7 @@ EXAMPLES = """
username: user01 username: user01
description: An asymmetric vault description: An asymmetric vault
vault_type: asymmetric vault_type: asymmetric
public_key: | public_key:
LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTR LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlHZk1BMEdDU3FHU0liM0RRRUJBUVVBQTR
HTkFEQ0JpUUtCZ1FDdGFudjRkK3ptSTZ0T3ova1RXdGowY3AxRAowUENoYy8vR0pJMTUzTi HTkFEQ0JpUUtCZ1FDdGFudjRkK3ptSTZ0T3ova1RXdGowY3AxRAowUENoYy8vR0pJMTUzTi
9CN3UrN0h3SXlRVlZoNUlXZG1UcCtkWXYzd09yeVpPbzYvbHN5eFJaZ2pZRDRwQ3VGCjlxM 9CN3UrN0h3SXlRVlZoNUlXZG1UcCtkWXYzd09yeVpPbzYvbHN5eFJaZ2pZRDRwQ3VGCjlxM
@@ -303,14 +303,9 @@ EXAMPLES = """
""" """
RETURN = """ RETURN = """
vault: user:
description: Vault dict with archived data.
returned: If state is `retrieved`.
type: dict
options:
data:
description: The vault data. description: The vault data.
returned: always returned: If state is retrieved.
type: string type: string
""" """
@@ -494,10 +489,8 @@ def check_encryption_params(module, state, action, vault_type, salt,
new_password, new_password_file, res_find): new_password, new_password_file, res_find):
vault_type_invalid = [] vault_type_invalid = []
if vault_type is None and res_find is not None: if res_find is not None:
vault_type = res_find['ipavaulttype'] vault_type = res_find['ipavaulttype']
if isinstance(vault_type, (tuple, list)):
vault_type = vault_type[0]
if vault_type == "standard": if vault_type == "standard":
vault_type_invalid = ['public_key', 'public_key_file', 'password', vault_type_invalid = ['public_key', 'public_key_file', 'password',
@@ -517,16 +510,6 @@ def check_encryption_params(module, state, action, vault_type, salt,
module.fail_json( module.fail_json(
msg="Cannot modify password of inexistent vault.") msg="Cannot modify password of inexistent vault.")
if (
salt is not None
and not(
any([password, password_file])
and any([new_password, new_password_file])
)
):
module.fail_json(
msg="Vault `salt` can only change when changing the password.")
if vault_type == "asymmetric": if vault_type == "asymmetric":
vault_type_invalid = [ vault_type_invalid = [
'password', 'password_file', 'new_password', 'new_password_file' 'password', 'password_file', 'new_password', 'new_password_file'
@@ -756,7 +739,7 @@ def main():
res_vault_type = res_find.get('ipavaulttype')[0] res_vault_type = res_find.get('ipavaulttype')[0]
args['ipavaulttype'] = vault_type = res_vault_type args['ipavaulttype'] = vault_type = res_vault_type
else: else:
args['ipavaulttype'] = vault_type = u"symmetric" args['ipavaulttype'] = vault_type = "symmetric"
# Create command # Create command
if state == "present": if state == "present":
@@ -778,12 +761,7 @@ def main():
commands.append([name, "vault_mod_internal", args]) commands.append([name, "vault_mod_internal", args])
else: else:
if vault_type == 'symmetric' \
and 'ipavaultsalt' not in args:
args['ipavaultsalt'] = os.urandom(32)
commands.append([name, "vault_add_internal", args]) commands.append([name, "vault_add_internal", args])
if vault_type != 'standard' and vault_data is None: if vault_type != 'standard' and vault_data is None:
vault_data = '' vault_data = ''
@@ -841,6 +819,14 @@ def main():
commands.append( commands.append(
[name, 'vault_remove_owner', owner_del_args]) [name, 'vault_remove_owner', owner_del_args])
if vault_type == 'symmetric' \
and 'ipavaultsalt' not in args:
args['ipavaultsalt'] = os.urandom(32)
if vault_type == 'symmetric' \
and 'ipavaultsalt' not in args:
args['ipavaultsalt'] = os.urandom(32)
elif action in "member": elif action in "member":
# Add users and groups # Add users and groups
if any([users, groups, services]): if any([users, groups, services]):
@@ -923,11 +909,11 @@ def main():
elif command == 'vault_retrieve': elif command == 'vault_retrieve':
if 'result' not in result: if 'result' not in result:
raise Exception("No result obtained.") raise Exception("No result obtained.")
if "data" in result["result"]: if 'data' in result['result']:
data_return = exit_args.setdefault("vault", {}) exit_args['data'] = result['result']['data']
data_return["data"] = result["result"]["data"] elif 'vault_data' in result['result']:
exit_args['data'] = result['result']['vault_data']
else: else:
if not datafile_out:
raise Exception("No data retrieved.") raise Exception("No data retrieved.")
changed = False changed = False
else: else:

View File

@@ -1,6 +1,2 @@
[pytest] [pytest]
python_files = test_*.py python_files = test_*.py
junit_family = xunit1
markers=
source_order: mark test as order bound
playbook: playbook tests

View File

@@ -1,2 +0,0 @@
-r requirements-tests.txt
ipdb

View File

@@ -1,7 +0,0 @@
-r requirements.txt
pytest>=2.7
pytest-sourceorder>=0.5
pytest-split-tests>=1.0.3
testinfra>=5.0
jmespath>=0.9 # needed for the `json_query` filter
pyyaml>=3

View File

@@ -0,0 +1,9 @@
#!/usr/bin/python3
# Test ipaclient python3 binding
from ipaclient.install.client import SECURE_PATH # noqa: F401
# Check ipapython version to be >= 4.6
from ipapython.version import NUM_VERSION, VERSION
if NUM_VERSION < 40600:
raise Exception("ipa %s not usable with python3" % VERSION)

View File

@@ -37,12 +37,12 @@ description:
options: options:
domain: domain:
description: Primary DNS domain of the IPA deployment description: Primary DNS domain of the IPA deployment
required: yes required: no
firefox_dir: firefox_dir:
description: description:
Specify directory where Firefox is installed (for example Specify directory where Firefox is installed (for example
'/usr/lib/firefox') '/usr/lib/firefox')
required: no required: yes
author: author:
- Thomas Woerner - Thomas Woerner
''' '''

View File

@@ -106,9 +106,6 @@ if NUM_VERSION >= 40400:
from ipaclient import ipadiscovery from ipaclient import ipadiscovery
from ipalib import api, errors, x509 from ipalib import api, errors, x509
from ipalib import constants from ipalib import constants
try:
from ipalib import sysrestore
except ImportError:
try: try:
from ipalib.install import sysrestore from ipalib.install import sysrestore
except ImportError: except ImportError:

View File

@@ -7,6 +7,9 @@
state: present state: present
when: ipaclient_install_packages | bool when: ipaclient_install_packages | bool
#- name: Install - Include Python2/3 import test
# import_tasks: "{{ role_path }}/tasks/python_2_3_test.yml"
- name: Install - Set ipaclient_servers - name: Install - Set ipaclient_servers
set_fact: set_fact:
ipaclient_servers: "{{ groups['ipaservers'] | list }}" ipaclient_servers: "{{ groups['ipaservers'] | list }}"
@@ -110,6 +113,10 @@
fail: msg="Keytab or password is required for getting otp" fail: msg="Keytab or password is required for getting otp"
when: ipaadmin_keytab is undefined and ipaadmin_password is undefined when: ipaadmin_keytab is undefined and ipaadmin_password is undefined
#- name: Install - Include Python2/3 import test
# import_tasks: "{{ role_path }}/tasks/python_2_3_test.yml"
# delegate_to: "{{ result_ipaclient_test.servers[0] }}"
- name: Install - Get One-Time Password for client enrollment - name: Install - Get One-Time Password for client enrollment
no_log: yes no_log: yes
ipaclient_get_otp: ipaclient_get_otp:
@@ -343,7 +350,6 @@
- name: Install - Configure firefox - name: Install - Configure firefox
ipaclient_setup_firefox: ipaclient_setup_firefox:
firefox_dir: "{{ ipaclient_firefox_dir | default(omit) }}" firefox_dir: "{{ ipaclient_firefox_dir | default(omit) }}"
domain: "{{ result_ipaclient_test.domain }}"
when: ipaclient_configure_firefox | bool when: ipaclient_configure_firefox | bool
- name: Install - Configure NIS - name: Install - Configure NIS

View File

@@ -0,0 +1,18 @@
---
- block:
- name: Verify Python3 import
script: py3test.py
register: result_py3test
failed_when: False
changed_when: False
check_mode: no
- name: Set python interpreter to 3
set_fact:
ansible_python_interpreter: "/usr/bin/python3"
when: result_py3test.rc == 0
- name: Set python interpreter to 2
set_fact:
ansible_python_interpreter: "/usr/bin/python2"
when: result_py3test.failed or result_py3test.rc != 0

View File

@@ -1,6 +1,9 @@
--- ---
# tasks to uninstall IPA client # tasks to uninstall IPA client
# - name: Uninstall - Include Python2/3 import test
# import_tasks: "{{ role_path }}/tasks/python_2_3_test.yml"
- name: Uninstall - Uninstall IPA client - name: Uninstall - Uninstall IPA client
command: > command: >
/usr/sbin/ipa-client-install /usr/sbin/ipa-client-install

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