mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-05-07 22:03:18 +00:00
Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40e00a6234 | ||
|
|
c24e5710da | ||
|
|
43a525139b | ||
|
|
e0bdfdfe32 | ||
|
|
65937ed8c3 | ||
|
|
ec2c0c4b59 | ||
|
|
753a8b0bd1 | ||
|
|
a1f882ac52 | ||
|
|
8d99ce4207 | ||
|
|
e3e7d71474 | ||
|
|
285fb6b8e0 | ||
|
|
d2648b142a | ||
|
|
67e192242c | ||
|
|
9eefc1ae7c | ||
|
|
b9d0b35e83 | ||
|
|
85006d611f | ||
|
|
82412ef761 | ||
|
|
2e178e5a38 | ||
|
|
f47d134335 | ||
|
|
541c514aa9 | ||
|
|
85257b9d03 | ||
|
|
e7f902ca48 | ||
|
|
a1bfa608e2 | ||
|
|
eefd94d13f | ||
|
|
667177db07 | ||
|
|
f301ad55aa | ||
|
|
fd9ecc246d | ||
|
|
b15552540c | ||
|
|
25b41b7eca | ||
|
|
b53f2a08d6 | ||
|
|
f2b3e88d5a | ||
|
|
e001ecb1de | ||
|
|
44b3c3003d | ||
|
|
c7a3b26ec4 | ||
|
|
9252284504 | ||
|
|
9665769cfc | ||
|
|
7d02d4d409 | ||
|
|
fb5f59db23 | ||
|
|
90e8098bf4 | ||
|
|
d615d3d4ed | ||
|
|
8ba665213f | ||
|
|
036891d09a | ||
|
|
93a441494d | ||
|
|
77b72af1a2 | ||
|
|
4bfde9b61a | ||
|
|
f113e7071e | ||
|
|
ef9f7fcb84 | ||
|
|
5c5b05a74f | ||
|
|
fa94b14e91 | ||
|
|
cd3646ad67 | ||
|
|
2e8c2f881f | ||
|
|
b88cab07ff | ||
|
|
f406de14e8 | ||
|
|
a86970efe1 | ||
|
|
0af208d271 | ||
|
|
10b16a3bbf | ||
|
|
5c871242a7 | ||
|
|
2f9791f6c5 | ||
|
|
f41104520e | ||
|
|
d81994475e | ||
|
|
612b60766e | ||
|
|
d6eaf91225 | ||
|
|
cb95248ef5 | ||
|
|
ca0aed54b0 | ||
|
|
17bba27abf | ||
|
|
22f31d02f2 | ||
|
|
5e9a2e8c2e | ||
|
|
0757bfee0a | ||
|
|
1eff04a09a | ||
|
|
f43831407b |
8
.github/workflows/lint.yml
vendored
8
.github/workflows/lint.yml
vendored
@@ -76,3 +76,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
pip install pylint==2.10.2
|
pip install pylint==2.10.2
|
||||||
pylint plugins --disable=import-error
|
pylint plugins --disable=import-error
|
||||||
|
|
||||||
|
shellcheck:
|
||||||
|
name: Shellcheck
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Run ShellCheck
|
||||||
|
uses: ludeeus/action-shellcheck@1.1.0
|
||||||
|
|||||||
@@ -38,3 +38,8 @@ repos:
|
|||||||
entry: utils/ansible-doc-test
|
entry: utils/ansible-doc-test
|
||||||
# args: ['-v', 'roles', 'plugins']
|
# args: ['-v', 'roles', 'plugins']
|
||||||
files: ^.*.py$
|
files: ^.*.py$
|
||||||
|
- repo: https://github.com/koalaman/shellcheck-precommit
|
||||||
|
rev: v0.8.0
|
||||||
|
hooks:
|
||||||
|
- id: shellcheck
|
||||||
|
args: ["--severity=warning"] # Only show errors and warnings
|
||||||
|
|||||||
@@ -104,20 +104,164 @@ Example playbook to add an inclusive condition to an existing rule
|
|||||||
ipaadmin_password: SomeADMINpassword
|
ipaadmin_password: SomeADMINpassword
|
||||||
name: "My domain hosts"
|
name: "My domain hosts"
|
||||||
description: "my automember condition"
|
description: "my automember condition"
|
||||||
automember_tye: hostgroup
|
automember_type: hostgroup
|
||||||
action: member
|
action: member
|
||||||
inclusive:
|
inclusive:
|
||||||
- key: fqdn
|
- key: fqdn
|
||||||
expression: ".*.mydomain.com"
|
expression: ".*.mydomain.com"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure group membership for all users has been rebuilt
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure group membership for all users has been rebuilt
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
state: rebuilt
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure group membership for given users has been rebuilt
|
||||||
|
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure group membership for given users has been rebuilt
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
users:
|
||||||
|
- user1
|
||||||
|
- user2
|
||||||
|
state: rebuilt
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure hostgroup membership for all hosts has been rebuilt
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure hostgroup membership for all hosts has been rebuilt
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: rebuilt
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure hostgroup membership for given hosts has been rebuilt
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure hostgroup membership for given hosts has been rebuilt
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
hosts:
|
||||||
|
- host1.mydomain.com
|
||||||
|
- host2.mydomain.com
|
||||||
|
state: rebuilt
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure default group fallback_group for all unmatched group entries is set
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure default group fallback_group for all unmatched group entries is set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
default_group: fallback_group
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure default group for all unmatched group entries is not set
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure default group for all unmatched group entries is not set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
default_group: ""
|
||||||
|
automember_type: group
|
||||||
|
state: absent
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure default hostgroup fallback_hostgroup for all unmatched group entries
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure default hostgroup fallback_hostgroup for all unmatched group entries
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: fallback_hostgroup
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure default hostgroup for all unmatched group entries is not set
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure default hostgroup for all unmatched group entries is not set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: ""
|
||||||
|
state: absent
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure all orphan automember group rules are removed:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure all orphan automember group rules are removed
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
state: orphans_removed
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure all orphan automember hostgroup rules are removed:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure all orphan automember hostgroup rules are removed
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: orphans_removed
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
ipaautomember
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
@@ -129,11 +273,16 @@ Variable | Description | Required
|
|||||||
`automember_type` | Grouping to which the rule applies. It can be one of `group`, `hostgroup`. | yes
|
`automember_type` | Grouping to which the rule applies. It can be one of `group`, `hostgroup`. | yes
|
||||||
`inclusive` | List of dictionaries in the format of `{'key': attribute, 'expression': inclusive_regex}` | no
|
`inclusive` | List of dictionaries in the format of `{'key': attribute, 'expression': inclusive_regex}` | no
|
||||||
`exclusive` | List of dictionaries in the format of `{'key': attribute, 'expression': exclusive_regex}` | no
|
`exclusive` | List of dictionaries in the format of `{'key': attribute, 'expression': exclusive_regex}` | no
|
||||||
|
`users` | Users to rebuild membership for. | no
|
||||||
|
`hosts` | Hosts to rebuild membership for. | no
|
||||||
|
`no_wait` | Don't wait for rebuilding membership. | no
|
||||||
|
`default_group` | Default (fallback) group for all unmatched entries. Use the empty string "" for ensuring the default group is not set. | no
|
||||||
`action` | Work on automember or member level. It can be one of `member` or `automember` and defaults to `automember`. | no
|
`action` | Work on automember or member level. It can be one of `member` or `automember` and defaults to `automember`. | no
|
||||||
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
|
`state` | The state to ensure. It can be one of `present`, `absent`, 'rebuilt'. 'orphans_removed' default: `present`. | no
|
||||||
|
|
||||||
|
|
||||||
Authors
|
Authors
|
||||||
=======
|
=======
|
||||||
|
|
||||||
Mark Hahl
|
Mark Hahl
|
||||||
|
Thomas Woerner
|
||||||
|
|||||||
@@ -97,9 +97,6 @@ Example playbook to ensure absence of an automount location:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipaautomountlocation
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -56,12 +56,12 @@ Example playbook to read config options:
|
|||||||
register: result
|
register: result
|
||||||
- name: display default login shell
|
- name: display default login shell
|
||||||
debug:
|
debug:
|
||||||
msg: '{{ result.config.defaultlogin }}'
|
msg: '{{ result.config.defaultshell }}'
|
||||||
|
|
||||||
- name: ensure defaultloginshell and maxusernamelength are set as required
|
- name: ensure defaultloginshell and maxusernamelength are set as required
|
||||||
ipaconfig:
|
ipaconfig:
|
||||||
ipaadmin_password: password
|
ipaadmin_password: password
|
||||||
defaultlogin: /bin/bash
|
defaultshell: /bin/bash
|
||||||
maxusername: 64
|
maxusername: 64
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -82,9 +82,6 @@ Example playbook to read config options:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipauser
|
|
||||||
-------
|
|
||||||
|
|
||||||
**General Variables:**
|
**General Variables:**
|
||||||
|
|
||||||
Variable | Description | Required
|
Variable | Description | Required
|
||||||
|
|||||||
@@ -135,9 +135,6 @@ Example playbook to make sure delegation "basic manager attributes" is absent:
|
|||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
ipadelegation
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -119,9 +119,6 @@ Example playbook to disallow synchronization of forward (A, AAAA) and reverse (P
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipadnsconfig
|
|
||||||
------------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -100,9 +100,6 @@ Example playbook to ensure presence of a forwardzone to ipa DNS:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipagroup
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -242,9 +242,6 @@ Example playbook to ensure multiple DNS records are absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipadnsrecord
|
|
||||||
------------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -195,9 +195,6 @@ Example playbook to create a zone for reverse DNS lookup, from an IP address, gi
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipadnszone
|
|
||||||
----------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
@@ -233,9 +230,6 @@ Variable | Description | Required
|
|||||||
Return Values
|
Return Values
|
||||||
=============
|
=============
|
||||||
|
|
||||||
ipadnszone
|
|
||||||
----------
|
|
||||||
|
|
||||||
Variable | Description | Returned When
|
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.
|
`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.
|
||||||
|
|||||||
@@ -147,9 +147,6 @@ Example playbook to remove groups:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipagroup
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -129,9 +129,6 @@ Example playbook to make sure HBAC Rule login is absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipahbacrule
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -91,9 +91,6 @@ Example playbook to make sure HBAC Services for http and tftp are absent
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipahbacsvc
|
|
||||||
----------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -129,9 +129,6 @@ Example playbook to make sure HBAC Service Group login is absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipahbacsvcgroup
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -313,9 +313,6 @@ Example playbook to ensure a host is absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipahost
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
@@ -370,9 +367,6 @@ Variable | Description | Required
|
|||||||
Return Values
|
Return Values
|
||||||
=============
|
=============
|
||||||
|
|
||||||
ipahost
|
|
||||||
-------
|
|
||||||
|
|
||||||
There are only return values if one or more random passwords have been generated.
|
There are only return values if one or more random passwords have been generated.
|
||||||
|
|
||||||
Variable | Description | Returned When
|
Variable | Description | Returned When
|
||||||
|
|||||||
@@ -143,9 +143,6 @@ Example playbook to make sure host-group databases is absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipahostgroup
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -74,9 +74,6 @@ Example playbook to make sure location "my_location1" is absent:
|
|||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
ipalocation
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -154,9 +154,6 @@ Example playbook to make sure permission "MyPermission" is renamed to "MyNewPerm
|
|||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
ipapermission
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -126,9 +126,6 @@ Example playbook to make sure privilege "DNS Special Privilege" is absent:
|
|||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
ipaprivilege
|
|
||||||
------------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ Example playbook to ensure maxlife is set to 49 in global policy:
|
|||||||
become: true
|
become: true
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
# Ensure absence of pwpolicies for group ops
|
# Ensure maxlife is set to 49 in global policy
|
||||||
- ipapwpolicy:
|
- ipapwpolicy:
|
||||||
ipaadmin_password: SomeADMINpassword
|
ipaadmin_password: SomeADMINpassword
|
||||||
maxlife: 49
|
maxlife: 49
|
||||||
@@ -91,9 +91,6 @@ Example playbook to ensure maxlife is set to 49 in global policy:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipapwpolicy
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -238,9 +238,6 @@ Example playbook to ensure that different members are not associated with a role
|
|||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
iparole
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -131,9 +131,6 @@ Example playbook to make sure selfservice "Users can manage their own name detai
|
|||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
ipaselfservice
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -242,9 +242,6 @@ This task will always report a change.
|
|||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
ipaserver
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -285,8 +285,6 @@ Example playbook to allow users, groups, hosts or hostgroups to retrieve a keyta
|
|||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
|
|
||||||
ipaservice
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -76,9 +76,6 @@ Example playbook to make sure sudocmd is absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipasudocmd
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -116,9 +116,6 @@ Example playbook to make sure sudocmdgroup is absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipasudocmdgroup
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -113,9 +113,6 @@ Example playbook to make sure Sudo Rule is absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipasudorule
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -94,9 +94,6 @@ This will only delete the ipa-side of the trust and it does NOT delete the id-ra
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipatrust
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
|
|||||||
@@ -356,9 +356,6 @@ Example playbook to ensure users are absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipauser
|
|
||||||
-------
|
|
||||||
|
|
||||||
**General Variables:**
|
**General Variables:**
|
||||||
|
|
||||||
Variable | Description | Required
|
Variable | Description | Required
|
||||||
@@ -432,9 +429,6 @@ Variable | Description | Required
|
|||||||
Return Values
|
Return Values
|
||||||
=============
|
=============
|
||||||
|
|
||||||
ipauser
|
|
||||||
-------
|
|
||||||
|
|
||||||
There are only return values if one or more random passwords have been generated.
|
There are only return values if one or more random passwords have been generated.
|
||||||
|
|
||||||
Variable | Description | Returned When
|
Variable | Description | Returned When
|
||||||
|
|||||||
@@ -210,9 +210,6 @@ Example playbook to make sure vault is absent:
|
|||||||
Variables
|
Variables
|
||||||
=========
|
=========
|
||||||
|
|
||||||
ipavault
|
|
||||||
-------
|
|
||||||
|
|
||||||
Variable | Description | Required
|
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
|
||||||
@@ -250,9 +247,6 @@ Variable | Description | Required
|
|||||||
Return Values
|
Return Values
|
||||||
=============
|
=============
|
||||||
|
|
||||||
ipavault
|
|
||||||
--------
|
|
||||||
|
|
||||||
There is only a return value if `state` is `retrieved`.
|
There is only a return value if `state` is `retrieved`.
|
||||||
|
|
||||||
Variable | Description | Returned When
|
Variable | Description | Returned When
|
||||||
|
|||||||
10
README.md
10
README.md
@@ -13,6 +13,7 @@ Features
|
|||||||
* Repair mode for clients
|
* Repair mode for clients
|
||||||
* Backup and restore, also to and from controller
|
* Backup and restore, also to and from controller
|
||||||
* Modules for automembership rule management
|
* Modules for automembership rule management
|
||||||
|
* Modules for automount location management
|
||||||
* Modules for config management
|
* Modules for config management
|
||||||
* Modules for delegation management
|
* Modules for delegation management
|
||||||
* Modules for dns config management
|
* Modules for dns config management
|
||||||
@@ -424,6 +425,7 @@ Modules in plugin/modules
|
|||||||
=========================
|
=========================
|
||||||
|
|
||||||
* [ipaautomember](README-automember.md)
|
* [ipaautomember](README-automember.md)
|
||||||
|
* [ipaautomountlocation](README-automountlocation.md)
|
||||||
* [ipaconfig](README-config.md)
|
* [ipaconfig](README-config.md)
|
||||||
* [ipadelegation](README-delegation.md)
|
* [ipadelegation](README-delegation.md)
|
||||||
* [ipadnsconfig](README-dnsconfig.md)
|
* [ipadnsconfig](README-dnsconfig.md)
|
||||||
@@ -436,12 +438,12 @@ Modules in plugin/modules
|
|||||||
* [ipahbacsvcgroup](README-hbacsvc.md)
|
* [ipahbacsvcgroup](README-hbacsvc.md)
|
||||||
* [ipahost](README-host.md)
|
* [ipahost](README-host.md)
|
||||||
* [ipahostgroup](README-hostgroup.md)
|
* [ipahostgroup](README-hostgroup.md)
|
||||||
* [ipalocation](README-ipalocation.md)
|
* [ipalocation](README-location.md)
|
||||||
* [ipapermission](README-ipapermission.md)
|
* [ipapermission](README-permission.md)
|
||||||
* [ipaprivilege](README-ipaprivilege.md)
|
* [ipaprivilege](README-privilege.md)
|
||||||
* [ipapwpolicy](README-pwpolicy.md)
|
* [ipapwpolicy](README-pwpolicy.md)
|
||||||
* [iparole](README-role.md)
|
* [iparole](README-role.md)
|
||||||
* [ipaselfservice](README-ipaselfservice.md)
|
* [ipaselfservice](README-selfservice.md)
|
||||||
* [ipaserver](README-server.md)
|
* [ipaserver](README-server.md)
|
||||||
* [ipaservice](README-service.md)
|
* [ipaservice](README-service.md)
|
||||||
* [ipasudocmd](README-sudocmd.md)
|
* [ipasudocmd](README-sudocmd.md)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ readme: "README.md"
|
|||||||
license: "GPL-3.0-or-later"
|
license: "GPL-3.0-or-later"
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
|
- "linux"
|
||||||
- "system"
|
- "system"
|
||||||
- "identity"
|
- "identity"
|
||||||
- "ipa"
|
- "ipa"
|
||||||
|
|||||||
30
molecule/centos-9-build/Dockerfile
Normal file
30
molecule/centos-9-build/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
FROM quay.io/centos/centos:stream9
|
||||||
|
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"]
|
||||||
18
molecule/centos-9-build/molecule.yml
Normal file
18
molecule/centos-9-build/molecule.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
driver:
|
||||||
|
name: docker
|
||||||
|
platforms:
|
||||||
|
- name: centos-9-build
|
||||||
|
image: "quay.io/centos/centos:stream9"
|
||||||
|
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
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
# IPA depends on IPv6 and without it dirsrv service won't start.
|
# IPA depends on IPv6 and without it dirsrv service won't start.
|
||||||
- name: Ensure IPv6 is ENABLED
|
- name: Ensure IPv6 is ENABLED
|
||||||
sysctl:
|
ansible.posix.sysctl:
|
||||||
name: "{{ item.name }}"
|
name: "{{ item.name }}"
|
||||||
value: "{{ item.value }}"
|
value: "{{ item.value }}"
|
||||||
sysctl_set: yes
|
sysctl_set: yes
|
||||||
@@ -19,14 +19,14 @@
|
|||||||
# This is needed in some IPA versions in order to get KRA enabled.
|
# This is needed in some IPA versions in order to get KRA enabled.
|
||||||
# See https://pagure.io/freeipa/issue/7906 for more information.
|
# See https://pagure.io/freeipa/issue/7906 for more information.
|
||||||
- name: stat protected_regular
|
- name: stat protected_regular
|
||||||
stat:
|
ansible.builtin.stat:
|
||||||
path: /proc/sys/fs/protected_regular
|
path: /proc/sys/fs/protected_regular
|
||||||
register: result
|
register: result
|
||||||
|
|
||||||
- name: Ensure fs.protected_regular is disabled
|
- name: Ensure fs.protected_regular is disabled
|
||||||
sysctl:
|
ansible.posix.sysctl:
|
||||||
name: fs.protected_regular
|
name: fs.protected_regular
|
||||||
value: '0'
|
value: 0
|
||||||
sysctl_set: yes
|
sysctl_set: yes
|
||||||
state: present
|
state: present
|
||||||
reload: yes
|
reload: yes
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
# To avoid this problem we create the directories before starting IPA.
|
# To avoid this problem we create the directories before starting IPA.
|
||||||
- name: Ensure lock dirs for DS exists
|
- name: Ensure lock dirs for DS exists
|
||||||
file:
|
ansible.builtin.file:
|
||||||
state: directory
|
state: directory
|
||||||
owner: dirsrv
|
owner: dirsrv
|
||||||
group: dirsrv
|
group: dirsrv
|
||||||
@@ -22,6 +22,6 @@
|
|||||||
- /var/lock/dirsrv/slapd-TEST-LOCAL/
|
- /var/lock/dirsrv/slapd-TEST-LOCAL/
|
||||||
|
|
||||||
- name: Ensure IPA server is up an running
|
- name: Ensure IPA server is up an running
|
||||||
service:
|
ansible.builtin.service:
|
||||||
name: ipa
|
name: ipa
|
||||||
state: started
|
state: started
|
||||||
|
|||||||
10
playbooks/automember/automember-default-group-not-set.yml
Normal file
10
playbooks/automember/automember-default-group-not-set.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember default group not set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure automember default group is not set
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
default_group: ""
|
||||||
10
playbooks/automember/automember-default-group-set.yml
Normal file
10
playbooks/automember/automember-default-group-set.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember default group set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure automember default group is set
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
default_group: fallback_group
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember default hostgroup not set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure automember default hostgroup is not set
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: ""
|
||||||
10
playbooks/automember/automember-default-hostgroup-set.yml
Normal file
10
playbooks/automember/automember-default-hostgroup-set.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember default hostgroup set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure automember default hostgroup is set
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: fallback_hostgroup
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember group membership for all users rebuilt example
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure group automember rule admins is present
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
state: rebuilt
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
- name: Automember group membership for given users rebuilt example
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure group membership for given users has been rebuilt
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
users:
|
||||||
|
- user1
|
||||||
|
- user2
|
||||||
|
state: rebuilt
|
||||||
10
playbooks/automember/automember-group-orphans-removed.yml
Normal file
10
playbooks/automember/automember-group-orphans-removed.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember orphan group rules are removed example
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure orphan group rules are removed
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
state: orphans_removed
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember hostgroup membership for all hosts rebuilt example
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure hostgroup membership for all hosts has been rebuilt
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: rebuilt
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
- name: Automember hostgroup membership for given hosts rebuilt example
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure hostgroup membership for given hosts has been rebuilt
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
hosts:
|
||||||
|
- host1.mydomain.com
|
||||||
|
- host2.mydomain.com
|
||||||
|
state: rebuilt
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember orphan hostgroup rules are removed example
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure orphan hostgroup rules are removed
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: orphans_removed
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
|
||||||
class ModuleDocFragment(object): # pylint: disable=R0205,R0903
|
class ModuleDocFragment(object): # pylint: disable=R0205,R0903
|
||||||
DOCUMENTATION = r"""
|
DOCUMENTATION = r"""
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
__all__ = ["gssapi", "netaddr", "api", "ipalib_errors", "Env",
|
__all__ = ["gssapi", "netaddr", "api", "ipalib_errors", "Env",
|
||||||
"DEFAULT_CONFIG", "LDAP_GENERALIZED_TIME_FORMAT",
|
"DEFAULT_CONFIG", "LDAP_GENERALIZED_TIME_FORMAT",
|
||||||
"kinit_password", "kinit_keytab", "run", "DN", "VERSION",
|
"kinit_password", "kinit_keytab", "run", "DN", "VERSION",
|
||||||
@@ -100,7 +103,7 @@ else:
|
|||||||
|
|
||||||
import socket
|
import socket
|
||||||
import base64
|
import base64
|
||||||
import six
|
from ansible.module_utils import six
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from collections.abc import Mapping # noqa
|
from collections.abc import Mapping # noqa
|
||||||
@@ -397,6 +400,14 @@ else:
|
|||||||
def module_params_get(module, name):
|
def module_params_get(module, name):
|
||||||
return _afm_convert(module.params.get(name))
|
return _afm_convert(module.params.get(name))
|
||||||
|
|
||||||
|
def module_params_get_lowercase(module, name):
|
||||||
|
value = _afm_convert(module.params.get(name))
|
||||||
|
if isinstance(value, list):
|
||||||
|
value = [v.lower() for v in value]
|
||||||
|
if isinstance(value, (str, unicode)):
|
||||||
|
value = value.lower()
|
||||||
|
return value
|
||||||
|
|
||||||
def api_get_domain():
|
def api_get_domain():
|
||||||
return api.env.domain
|
return api.env.domain
|
||||||
|
|
||||||
@@ -408,6 +419,9 @@ else:
|
|||||||
def api_get_realm():
|
def api_get_realm():
|
||||||
return api.env.realm
|
return api.env.realm
|
||||||
|
|
||||||
|
def api_get_basedn():
|
||||||
|
return api.env.basedn
|
||||||
|
|
||||||
def gen_add_del_lists(user_list, res_list):
|
def gen_add_del_lists(user_list, res_list):
|
||||||
"""
|
"""
|
||||||
Generate the lists for the addition and removal of members.
|
Generate the lists for the addition and removal of members.
|
||||||
@@ -555,10 +569,76 @@ else:
|
|||||||
print(jsonify(kwargs))
|
print(jsonify(kwargs))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
class AnsibleFreeIPAParams(Mapping):
|
class IPAParamMapping(Mapping):
|
||||||
def __init__(self, ansible_module):
|
"""
|
||||||
|
Provides IPA API mapping to playbook parameters or computed values.
|
||||||
|
|
||||||
|
It can be used to define a mapping of playbook parameters
|
||||||
|
or methods that provide computed values to IPA API arguments.
|
||||||
|
|
||||||
|
Playbook parameters can be retrieved as properties,
|
||||||
|
and the set of IPA arguments for a command can be
|
||||||
|
retrived with ``get_ipa_command_args()``. The keys for
|
||||||
|
``param_mapping`` are also the keys of the argument set.
|
||||||
|
|
||||||
|
The values of ``param_mapping`` can be either:
|
||||||
|
* a str representing a key of ``AnsibleModule.params``.
|
||||||
|
* a callable.
|
||||||
|
|
||||||
|
In case of an ``AnsibleModule.param`` the value of the playbook
|
||||||
|
param will be used for that argument. If it is a ``callable``,
|
||||||
|
the value returned by the execution of it will be used.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
-------
|
||||||
|
def check_params(ipa_params):
|
||||||
|
# Module parameters can be accessed as properties.
|
||||||
|
if len(ipa_params.name) == 0:
|
||||||
|
ipa_params.ansible_module.fail_json(msg="No given name.")
|
||||||
|
|
||||||
|
|
||||||
|
def define_ipa_commands(self):
|
||||||
|
# Create the argument dict from the defined mapping.
|
||||||
|
args = self.get_ipa_command_args()
|
||||||
|
|
||||||
|
_commands = [("obj-name", "some_ipa_command", args)]
|
||||||
|
return _commands
|
||||||
|
|
||||||
|
|
||||||
|
def a_method_for_a_computed_param():
|
||||||
|
return "Some computed value"
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
ansible_module = SomeIPAModule(argument_spec=dict(
|
||||||
|
name=dict(type="list", aliases=["cn"], required=True),
|
||||||
|
state=dict(type="str", default="present",
|
||||||
|
choices=["present", "absent"]),
|
||||||
|
module_param=(type="str", required=False),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Define the playbook to IPA API mapping
|
||||||
|
ipa_param_mapping = {
|
||||||
|
"arg_to_be_passed_to_ipa_command": "module_param",
|
||||||
|
"another_arg": a_method_for_a_computed_param,
|
||||||
|
}
|
||||||
|
ipa_params = IPAParamMapping(
|
||||||
|
ansible_module,
|
||||||
|
param_mapping=ipa_param_mapping
|
||||||
|
)
|
||||||
|
|
||||||
|
check_params(ipa_params)
|
||||||
|
comands = define_ipa_commands(ipa_params)
|
||||||
|
|
||||||
|
ansible_module.execute_ipa_commands(commands)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, ansible_module, param_mapping=None):
|
||||||
self.mapping = ansible_module.params
|
self.mapping = ansible_module.params
|
||||||
self.ansible_module = ansible_module
|
self.ansible_module = ansible_module
|
||||||
|
self.param_mapping = param_mapping or {}
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
param = self.mapping[key]
|
param = self.mapping[key]
|
||||||
@@ -579,6 +659,36 @@ else:
|
|||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return self.get(name)
|
return self.get(name)
|
||||||
|
|
||||||
|
def get_ipa_command_args(self, **kwargs):
|
||||||
|
"""Return a dict to be passed to an IPA command."""
|
||||||
|
args = {}
|
||||||
|
for ipa_param_name, param_name in self.param_mapping.items():
|
||||||
|
|
||||||
|
# Check if param_name is actually a param
|
||||||
|
if param_name in self.ansible_module.params:
|
||||||
|
value = self.ansible_module.params_get(param_name)
|
||||||
|
if isinstance(value, bool):
|
||||||
|
value = "TRUE" if value else "FALSE"
|
||||||
|
|
||||||
|
# Since param wasn't a param check if it's a method name
|
||||||
|
elif callable(param_name):
|
||||||
|
value = param_name(**kwargs)
|
||||||
|
|
||||||
|
# We don't have a way to guess the value so fail.
|
||||||
|
else:
|
||||||
|
self.ansible_module.fail_json(
|
||||||
|
msg=(
|
||||||
|
"Couldn't get a value for '%s'. Option '%s' is "
|
||||||
|
"not a module argument neither a defined method."
|
||||||
|
)
|
||||||
|
% (ipa_param_name, param_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
if value is not None:
|
||||||
|
args[ipa_param_name] = value
|
||||||
|
|
||||||
|
return args
|
||||||
|
|
||||||
class IPAAnsibleModule(AnsibleModule):
|
class IPAAnsibleModule(AnsibleModule):
|
||||||
"""
|
"""
|
||||||
IPA Ansible Module.
|
IPA Ansible Module.
|
||||||
@@ -699,6 +809,18 @@ else:
|
|||||||
"""
|
"""
|
||||||
return module_params_get(self, name)
|
return module_params_get(self, name)
|
||||||
|
|
||||||
|
def params_get_lowercase(self, name):
|
||||||
|
"""
|
||||||
|
Retrieve value set for module parameter as lowercase, if not None.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
name: string
|
||||||
|
The name of the parameter to retrieve.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return module_params_get_lowercase(self, name)
|
||||||
|
|
||||||
def params_fail_used_invalid(self, invalid_params, state, action=None):
|
def params_fail_used_invalid(self, invalid_params, state, action=None):
|
||||||
"""
|
"""
|
||||||
Fail module execution if one of the invalid parameters is not None.
|
Fail module execution if one of the invalid parameters is not None.
|
||||||
@@ -763,6 +885,11 @@ else:
|
|||||||
"""Retrieve IPA API realm."""
|
"""Retrieve IPA API realm."""
|
||||||
return api_get_realm()
|
return api_get_realm()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def ipa_get_basedn():
|
||||||
|
"""Retrieve IPA API basedn."""
|
||||||
|
return api_get_basedn()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ipa_command_exists(command):
|
def ipa_command_exists(command):
|
||||||
"""
|
"""
|
||||||
@@ -1011,6 +1138,11 @@ else:
|
|||||||
# pylint: disable=super-with-arguments
|
# pylint: disable=super-with-arguments
|
||||||
super(FreeIPABaseModule, self).__init__(*args, **kwargs)
|
super(FreeIPABaseModule, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.deprecate(
|
||||||
|
msg="FreeIPABaseModule is deprecated. Use IPAAnsibleModule.",
|
||||||
|
version="1.5.0"
|
||||||
|
)
|
||||||
|
|
||||||
# Status of an execution. Will be changed to True
|
# Status of an execution. Will be changed to True
|
||||||
# if something is actually peformed.
|
# if something is actually peformed.
|
||||||
self.changed = False
|
self.changed = False
|
||||||
@@ -1026,11 +1158,6 @@ else:
|
|||||||
# Module exit arguments.
|
# Module exit arguments.
|
||||||
self.exit_args = {}
|
self.exit_args = {}
|
||||||
|
|
||||||
# Wrapper around the AnsibleModule.params.
|
|
||||||
# Return the actual params but performing transformations
|
|
||||||
# when needed.
|
|
||||||
self.ipa_params = AnsibleFreeIPAParams(self)
|
|
||||||
|
|
||||||
def get_ipa_command_args(self, **kwargs):
|
def get_ipa_command_args(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
Return a dict to be passed to an IPA command.
|
Return a dict to be passed to an IPA command.
|
||||||
@@ -1051,97 +1178,77 @@ else:
|
|||||||
server).
|
server).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
args = {}
|
self.deprecate(
|
||||||
for ipa_param_name, param_name in self.ipa_param_mapping.items():
|
msg=(
|
||||||
|
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
|
||||||
# Check if param_name is actually a param
|
"Use 'AnsibleFreeIPAParams.get_ipa_command_args()', "
|
||||||
if param_name in self.ipa_params:
|
"Instantiate it using the class 'ipa_params_mapping'."
|
||||||
value = self.ipa_params.get(param_name)
|
),
|
||||||
if isinstance(value, bool):
|
version="1.5.0"
|
||||||
value = "TRUE" if value else "FALSE"
|
)
|
||||||
|
mapping = IPAParamMapping(self, self.ipa_param_mapping)
|
||||||
# Since param wasn't a param check if it's a method name
|
return mapping.get_ipa_command_args(**kwargs)
|
||||||
elif hasattr(self, param_name):
|
|
||||||
method = getattr(self, param_name)
|
|
||||||
if callable(method):
|
|
||||||
value = method(**kwargs)
|
|
||||||
|
|
||||||
# We don't have a way to guess the value so fail.
|
|
||||||
else:
|
|
||||||
self.fail_json(
|
|
||||||
msg=(
|
|
||||||
"Couldn't get a value for '%s'. Option '%s' is "
|
|
||||||
"not a module argument neither a defined method."
|
|
||||||
)
|
|
||||||
% (ipa_param_name, param_name)
|
|
||||||
)
|
|
||||||
|
|
||||||
if value is not None:
|
|
||||||
args[ipa_param_name] = value
|
|
||||||
|
|
||||||
return args
|
|
||||||
|
|
||||||
def check_ipa_params(self):
|
def check_ipa_params(self):
|
||||||
"""Validate ipa_params before command is called."""
|
"""Validate ipa_params before command is called."""
|
||||||
|
self.deprecate(
|
||||||
|
msg=(
|
||||||
|
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
|
||||||
|
),
|
||||||
|
version="1.5.0"
|
||||||
|
)
|
||||||
pass # pylint: disable=unnecessary-pass
|
pass # pylint: disable=unnecessary-pass
|
||||||
|
|
||||||
def define_ipa_commands(self):
|
def define_ipa_commands(self):
|
||||||
"""Define commands that will be run in IPA server."""
|
"""Define commands that will be run in IPA server."""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_command_errors(self, command, result):
|
|
||||||
"""Look for erros into command results."""
|
|
||||||
# Get all errors
|
|
||||||
# All "already a member" and "not a member" failures in the
|
|
||||||
# result are ignored. All others are reported.
|
|
||||||
errors = []
|
|
||||||
for item in result.get("failed", tuple()):
|
|
||||||
failed_item = result["failed"][item]
|
|
||||||
for member_type in failed_item:
|
|
||||||
for member, failure in failed_item[member_type]:
|
|
||||||
if (
|
|
||||||
"already a member" in failure
|
|
||||||
or "not a member" in failure
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
errors.append(
|
|
||||||
"%s: %s %s: %s"
|
|
||||||
% (command, member_type, member, failure)
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(errors) > 0:
|
|
||||||
self.fail_json(", ".join("errors")) # pylint: disable=E1121
|
|
||||||
|
|
||||||
def add_ipa_command(self, command, name=None, args=None):
|
def add_ipa_command(self, command, name=None, args=None):
|
||||||
"""Add a command to the list of commands to be executed."""
|
"""Add a command to the list of commands to be executed."""
|
||||||
self.ipa_commands.append((name, command, args or {}))
|
self.ipa_commands.append((name, command, args or {}))
|
||||||
|
|
||||||
def _run_ipa_commands(self):
|
def _run_ipa_commands(self):
|
||||||
"""Execute commands in self.ipa_commands."""
|
"""Execute commands in self.ipa_commands."""
|
||||||
if self.check_mode:
|
self.changed = self.execute_ipa_commands(
|
||||||
self.changed = len(self.ipa_commands) > 0
|
self.ipa_commands,
|
||||||
return
|
result_handler=self.process_results.__func__,
|
||||||
|
exit_args=self.exit_args
|
||||||
|
)
|
||||||
|
|
||||||
result = None
|
def process_results(
|
||||||
|
self, result, command, name, args, exit_args
|
||||||
|
): # pylint: disable=unused-argument
|
||||||
|
"""
|
||||||
|
Process an API command result.
|
||||||
|
|
||||||
for name, command, args in self.ipa_commands:
|
This method must be overriden in subclasses if 'exit_args'
|
||||||
try:
|
is to be modified.
|
||||||
result = self.ipa_command(command, name, args)
|
"""
|
||||||
except Exception as excpt:
|
self.deprecate(
|
||||||
self.fail_json(msg="%s: %s: %s" % (command, name,
|
msg=(
|
||||||
str(excpt)))
|
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
|
||||||
else:
|
),
|
||||||
self.process_command_result(name, command, args, result)
|
version="1.5.0"
|
||||||
self.get_command_errors(command, result)
|
)
|
||||||
|
self.process_command_result(name, command, args, result)
|
||||||
|
|
||||||
def process_command_result(self, _name, _command, _args, result):
|
def process_command_result(self, _name, _command, _args, result):
|
||||||
"""
|
"""
|
||||||
Process an API command result.
|
Process an API command result.
|
||||||
|
|
||||||
This method can be overriden in subclasses, and
|
This method can be overriden in subclasses, and
|
||||||
change self.exit_values
|
change self.exit_values to return data in the
|
||||||
to return data in the result for the controller.
|
result for the controller.
|
||||||
"""
|
"""
|
||||||
|
self.deprecate(
|
||||||
|
msg=(
|
||||||
|
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
|
||||||
|
"To aid in porting to IPAAnsibleModule, change to "
|
||||||
|
"'FreeIPABaseModule.process_results'."
|
||||||
|
),
|
||||||
|
version="1.5.0"
|
||||||
|
)
|
||||||
|
|
||||||
if "completed" in result:
|
if "completed" in result:
|
||||||
if result["completed"] > 0:
|
if result["completed"] > 0:
|
||||||
self.changed = True
|
self.changed = True
|
||||||
@@ -1155,12 +1262,26 @@ else:
|
|||||||
Returns True in case current IPA object attributes differ from
|
Returns True in case current IPA object attributes differ from
|
||||||
args passed to the module.
|
args passed to the module.
|
||||||
"""
|
"""
|
||||||
|
self.deprecate(
|
||||||
|
msg=(
|
||||||
|
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule. "
|
||||||
|
"FreeIPABaseModule require_ipa_attrs_change() is "
|
||||||
|
"deprecated. Use ansible_freeipa_module.compare_args()."
|
||||||
|
),
|
||||||
|
version="1.5.0"
|
||||||
|
)
|
||||||
equal = compare_args_ipa(self, command_args, ipa_attrs)
|
equal = compare_args_ipa(self, command_args, ipa_attrs)
|
||||||
return not equal
|
return not equal
|
||||||
|
|
||||||
def ipa_run(self):
|
def ipa_run(self):
|
||||||
"""Execute module actions."""
|
"""Execute module actions."""
|
||||||
ipaapi_context = self.ipa_params.get("ipaapi_context")
|
self.deprecate(
|
||||||
|
msg=(
|
||||||
|
"FreeIPABaseModule is deprecated. Use IPAAnsibleModule."
|
||||||
|
),
|
||||||
|
version="1.5.0"
|
||||||
|
)
|
||||||
|
ipaapi_context = self.params_get("ipaapi_context")
|
||||||
with self.ipa_connect(context=ipaapi_context):
|
with self.ipa_connect(context=ipaapi_context):
|
||||||
self.check_ipa_params()
|
self.check_ipa_params()
|
||||||
self.define_ipa_commands()
|
self.define_ipa_commands()
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
# Writing a new Ansible FreeIPA module
|
# Writing a new Ansible FreeIPA module
|
||||||
|
|
||||||
## Minimum requirements
|
|
||||||
A ansible-freeipa module should have:
|
A ansible-freeipa module should have:
|
||||||
|
|
||||||
* Code:
|
* Code:
|
||||||
@@ -13,68 +12,4 @@ A ansible-freeipa module should have:
|
|||||||
* Tests:
|
* Tests:
|
||||||
* Test cases (also playbooks) defined in `tests/<module_name>/test_<something>.yml`. It's ok to have multiple files in this directory.
|
* Test cases (also playbooks) defined in `tests/<module_name>/test_<something>.yml`. It's ok to have multiple files in this directory.
|
||||||
|
|
||||||
## Code
|
Use the script `utils/new_module` to create the stub files for a new module.
|
||||||
|
|
||||||
The module file have to start with the python shebang line, license header and definition of the constants `ANSIBLE_METADATA`, `DOCUMENTATION`, `EXAMPLES` and `RETURNS`. Those constants need to be defined before the code (even imports). See https://docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html#starting-a-new-module for more information.
|
|
||||||
|
|
||||||
|
|
||||||
Although it's use is not yet required, ansible-freeipa provides `FreeIPABaseModule` as a helper class for the implementation of new modules. See the example bellow:
|
|
||||||
|
|
||||||
```python
|
|
||||||
|
|
||||||
from ansible.module_utils.ansible_freeipa_module import FreeIPABaseModule
|
|
||||||
|
|
||||||
|
|
||||||
class SomeIPAModule(FreeIPABaseModule):
|
|
||||||
ipa_param_mapping = {
|
|
||||||
"arg_to_be_passed_to_ipa_command": "module_param",
|
|
||||||
"another_arg": "get_another_module_param",
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_another_module_param(self):
|
|
||||||
another_module_param = self.ipa_params.another_module_param
|
|
||||||
|
|
||||||
# Validate or modify another_module_param ...
|
|
||||||
|
|
||||||
return another_module_param
|
|
||||||
|
|
||||||
def check_ipa_params(self):
|
|
||||||
|
|
||||||
# Validate your params here ...
|
|
||||||
|
|
||||||
# Example:
|
|
||||||
if not self.ipa_params.module_param in VALID_OPTIONS:
|
|
||||||
self.fail_json(msg="Invalid value for argument module_param")
|
|
||||||
|
|
||||||
def define_ipa_commands(self):
|
|
||||||
args = self.get_ipa_command_args()
|
|
||||||
|
|
||||||
self.add_ipa_command("some_ipa_command", name="obj-name", args=args)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
ipa_module = SomeIPAModule(argument_spec=dict(
|
|
||||||
module_param=dict(type="str", default=None, required=False),
|
|
||||||
another_module_param=dict(type="str", default=None, required=False),
|
|
||||||
))
|
|
||||||
ipa_module.ipa_run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
```
|
|
||||||
|
|
||||||
In the example above, the module will call the command `some_ipa_command`, using "obj-name" as name and, `arg_to_be_passed_to_ipa_command` and `another_arg` as arguments.
|
|
||||||
|
|
||||||
The values of the arguments will be determined by the class attribute `ipa_param_mapping`.
|
|
||||||
|
|
||||||
In the case of `arg_to_be_passed_to_ipa_command` the key (`module_param`) is defined in the module `argument_specs` so the value of the argument is actually used.
|
|
||||||
|
|
||||||
On the other hand, `another_arg` as mapped to something else: a callable method. In this case the method will be called and it's result used as value for `another_arg`.
|
|
||||||
|
|
||||||
**NOTE**: Keep mind that to take advantage of the parameters mapping defined in `ipa_param_mapping` you will have to call `args = self.get_ipa_command_args()` and use `args` in your command. There is no implicit call of this method.
|
|
||||||
|
|
||||||
|
|
||||||
## Disclaimer
|
|
||||||
|
|
||||||
The `FreeIPABaseModule` is new and might not be suitable to all cases and every module yet. In case you need to extend it's functionality for a new module please open an issue or PR and we'll be happy to discuss it.
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -21,6 +20,9 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
@@ -77,6 +79,20 @@ options:
|
|||||||
description: The expression of the regex
|
description: The expression of the regex
|
||||||
type: str
|
type: str
|
||||||
required: true
|
required: true
|
||||||
|
users:
|
||||||
|
description: Users to rebuild membership for.
|
||||||
|
type: list
|
||||||
|
required: false
|
||||||
|
hosts:
|
||||||
|
description: Hosts to rebuild membership for.
|
||||||
|
type: list
|
||||||
|
required: false
|
||||||
|
no_wait:
|
||||||
|
description: Don't wait for rebuilding membership.
|
||||||
|
type: bool
|
||||||
|
default_group:
|
||||||
|
description: Default (fallback) group for all unmatched entries.
|
||||||
|
type: str
|
||||||
action:
|
action:
|
||||||
description: Work on automember or member level
|
description: Work on automember or member level
|
||||||
default: automember
|
default: automember
|
||||||
@@ -84,10 +100,11 @@ options:
|
|||||||
state:
|
state:
|
||||||
description: State to ensure
|
description: State to ensure
|
||||||
default: present
|
default: present
|
||||||
choices: ["present", "absent"]
|
choices: ["present", "absent", "rebuilt", "orphans_removed"]
|
||||||
author:
|
author:
|
||||||
- Mark Hahl
|
- Mark Hahl
|
||||||
- Jake Reynolds
|
- Jake Reynolds
|
||||||
|
- Thomas Woerner
|
||||||
"""
|
"""
|
||||||
|
|
||||||
EXAMPLES = """
|
EXAMPLES = """
|
||||||
@@ -100,7 +117,7 @@ EXAMPLES = """
|
|||||||
state: present
|
state: present
|
||||||
inclusive:
|
inclusive:
|
||||||
- key: "mail"
|
- key: "mail"
|
||||||
expression: "example.com$
|
expression: "example.com"
|
||||||
|
|
||||||
# Delete an automember rule
|
# Delete an automember rule
|
||||||
- ipaautomember:
|
- ipaautomember:
|
||||||
@@ -114,12 +131,78 @@ EXAMPLES = """
|
|||||||
- ipaautomember:
|
- ipaautomember:
|
||||||
ipaadmin_password: SomeADMINpassword
|
ipaadmin_password: SomeADMINpassword
|
||||||
name: "My domain hosts"
|
name: "My domain hosts"
|
||||||
automember_tye: hostgroup
|
automember_type: hostgroup
|
||||||
action: member
|
action: member
|
||||||
inclusive:
|
inclusive:
|
||||||
- key: fqdn
|
- key: fqdn
|
||||||
expression: ".*.mydomain.com"
|
expression: ".*.mydomain.com"
|
||||||
|
|
||||||
|
# Ensure group membership for all users has been rebuilt
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
state: rebuilt
|
||||||
|
|
||||||
|
# Ensure group membership for given users has been rebuilt
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
users:
|
||||||
|
- user1
|
||||||
|
- user2
|
||||||
|
state: rebuilt
|
||||||
|
|
||||||
|
# Ensure hostgroup membership for all hosts has been rebuilt
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: rebuilt
|
||||||
|
|
||||||
|
# Ensure hostgroup membership for given hosts has been rebuilt
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
hosts:
|
||||||
|
- host1.mydomain.com
|
||||||
|
- host2.mydomain.com
|
||||||
|
state: rebuilt
|
||||||
|
|
||||||
|
# Ensure default group fallback_group for all unmatched group entries is set
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
default_group: fallback_group
|
||||||
|
|
||||||
|
# Ensure default group for all unmatched group entries is not set
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
default_group: ""
|
||||||
|
automember_type: group
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
# Ensure default hostgroup fallback_hostgroup for all unmatched group entries
|
||||||
|
# is set
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: fallback_hostgroup
|
||||||
|
|
||||||
|
# Ensure default hostgroup for all unmatched group entries is not set
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: ""
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
# Example playbook to ensure all orphan automember group rules are removed:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
state: orphans_removed
|
||||||
|
|
||||||
|
# Example playbook to ensure all orphan automember hostgroup rules are removed:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: orphans_removed
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
RETURN = """
|
||||||
@@ -127,14 +210,14 @@ RETURN = """
|
|||||||
|
|
||||||
|
|
||||||
from ansible.module_utils.ansible_freeipa_module import (
|
from ansible.module_utils.ansible_freeipa_module import (
|
||||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, ipalib_errors
|
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, ipalib_errors, DN
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def find_automember(module, name, grouping):
|
def find_automember(module, name, automember_type):
|
||||||
_args = {
|
_args = {
|
||||||
"all": True,
|
"all": True,
|
||||||
"type": grouping
|
"type": automember_type
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -144,13 +227,40 @@ def find_automember(module, name, grouping):
|
|||||||
return _result["result"]
|
return _result["result"]
|
||||||
|
|
||||||
|
|
||||||
def gen_condition_args(grouping,
|
def find_automember_orphans(module, automember_type):
|
||||||
|
_args = {
|
||||||
|
"all": True,
|
||||||
|
"type": automember_type
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
_result = module.ipa_command_no_name("automember_find_orphans", _args)
|
||||||
|
except ipalib_errors.NotFound:
|
||||||
|
return None
|
||||||
|
return _result
|
||||||
|
|
||||||
|
|
||||||
|
def find_automember_default_group(module, automember_type):
|
||||||
|
_args = {
|
||||||
|
"all": True,
|
||||||
|
"type": automember_type
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
_result = module.ipa_command_no_name("automember_default_group_show",
|
||||||
|
_args)
|
||||||
|
except ipalib_errors.NotFound:
|
||||||
|
return None
|
||||||
|
return _result["result"]
|
||||||
|
|
||||||
|
|
||||||
|
def gen_condition_args(automember_type,
|
||||||
key,
|
key,
|
||||||
inclusiveregex=None,
|
inclusiveregex=None,
|
||||||
exclusiveregex=None):
|
exclusiveregex=None):
|
||||||
_args = {}
|
_args = {}
|
||||||
if grouping is not None:
|
if automember_type is not None:
|
||||||
_args['type'] = grouping
|
_args['type'] = automember_type
|
||||||
if key is not None:
|
if key is not None:
|
||||||
_args['key'] = key
|
_args['key'] = key
|
||||||
if inclusiveregex is not None:
|
if inclusiveregex is not None:
|
||||||
@@ -161,13 +271,23 @@ def gen_condition_args(grouping,
|
|||||||
return _args
|
return _args
|
||||||
|
|
||||||
|
|
||||||
def gen_args(description, grouping):
|
def gen_rebuild_args(automember_type, rebuild_users, rebuild_hosts, no_wait):
|
||||||
|
_args = {"no_wait": no_wait}
|
||||||
|
if automember_type is not None:
|
||||||
|
_args['type'] = automember_type
|
||||||
|
if rebuild_users is not None:
|
||||||
|
_args["users"] = rebuild_users
|
||||||
|
if rebuild_hosts is not None:
|
||||||
|
_args["hosts"] = rebuild_hosts
|
||||||
|
return _args
|
||||||
|
|
||||||
|
|
||||||
|
def gen_args(description, automember_type):
|
||||||
_args = {}
|
_args = {}
|
||||||
if description is not None:
|
if description is not None:
|
||||||
_args["description"] = description
|
_args["description"] = description
|
||||||
if grouping is not None:
|
if automember_type is not None:
|
||||||
_args['type'] = grouping
|
_args['type'] = automember_type
|
||||||
|
|
||||||
return _args
|
return _args
|
||||||
|
|
||||||
|
|
||||||
@@ -192,28 +312,35 @@ def main():
|
|||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
# general
|
# general
|
||||||
inclusive=dict(type="list",
|
inclusive=dict(type="list",
|
||||||
aliases=["automemberinclusiveregex"], default=None,
|
aliases=["automemberinclusiveregex"],
|
||||||
|
default=None,
|
||||||
options=dict(
|
options=dict(
|
||||||
key=dict(type="str", required=True),
|
key=dict(type="str", required=True),
|
||||||
expression=dict(type="str", required=True)
|
expression=dict(type="str", required=True)
|
||||||
),
|
),
|
||||||
elements="dict", required=False),
|
elements="dict",
|
||||||
exclusive=dict(type="list", aliases=[
|
required=False),
|
||||||
"automemberexclusiveregex"], default=None,
|
exclusive=dict(type="list",
|
||||||
|
aliases=["automemberexclusiveregex"],
|
||||||
|
default=None,
|
||||||
options=dict(
|
options=dict(
|
||||||
key=dict(type="str", required=True),
|
key=dict(type="str", required=True),
|
||||||
expression=dict(type="str", required=True)
|
expression=dict(type="str", required=True)
|
||||||
),
|
),
|
||||||
elements="dict", required=False),
|
elements="dict",
|
||||||
|
required=False),
|
||||||
name=dict(type="list", aliases=["cn"],
|
name=dict(type="list", aliases=["cn"],
|
||||||
default=None, required=True),
|
default=None, required=False),
|
||||||
description=dict(type="str", default=None),
|
description=dict(type="str", default=None),
|
||||||
automember_type=dict(type='str', required=False,
|
automember_type=dict(type='str', required=False,
|
||||||
choices=['group', 'hostgroup']),
|
choices=['group', 'hostgroup']),
|
||||||
|
no_wait=dict(type="bool", default=None),
|
||||||
|
default_group=dict(type="str", default=None),
|
||||||
action=dict(type="str", default="automember",
|
action=dict(type="str", default="automember",
|
||||||
choices=["member", "automember"]),
|
choices=["member", "automember"]),
|
||||||
state=dict(type="str", default="present",
|
state=dict(type="str", default="present",
|
||||||
choices=["present", "absent", "rebuild"]),
|
choices=["present", "absent", "rebuilt",
|
||||||
|
"orphans_removed"]),
|
||||||
users=dict(type="list", default=None),
|
users=dict(type="list", default=None),
|
||||||
hosts=dict(type="list", default=None),
|
hosts=dict(type="list", default=None),
|
||||||
),
|
),
|
||||||
@@ -226,6 +353,8 @@ def main():
|
|||||||
|
|
||||||
# general
|
# general
|
||||||
names = ansible_module.params_get("name")
|
names = ansible_module.params_get("name")
|
||||||
|
if names is None:
|
||||||
|
names = []
|
||||||
|
|
||||||
# present
|
# present
|
||||||
description = ansible_module.params_get("description")
|
description = ansible_module.params_get("description")
|
||||||
@@ -234,6 +363,12 @@ def main():
|
|||||||
inclusive = ansible_module.params_get("inclusive")
|
inclusive = ansible_module.params_get("inclusive")
|
||||||
exclusive = ansible_module.params_get("exclusive")
|
exclusive = ansible_module.params_get("exclusive")
|
||||||
|
|
||||||
|
# no_wait for rebuilt
|
||||||
|
no_wait = ansible_module.params_get("no_wait")
|
||||||
|
|
||||||
|
# default_group
|
||||||
|
default_group = ansible_module.params_get("default_group")
|
||||||
|
|
||||||
# action
|
# action
|
||||||
action = ansible_module.params_get("action")
|
action = ansible_module.params_get("action")
|
||||||
# state
|
# state
|
||||||
@@ -248,12 +383,51 @@ def main():
|
|||||||
# Check parameters
|
# Check parameters
|
||||||
invalid = []
|
invalid = []
|
||||||
|
|
||||||
if state != "rebuild":
|
if state in ["rebuilt", "orphans_removed"]:
|
||||||
invalid = ["rebuild_hosts", "rebuild_users"]
|
invalid = ["name", "description", "exclusive", "inclusive",
|
||||||
|
"default_group"]
|
||||||
|
|
||||||
if not automember_type and state != "rebuild":
|
if action == "member":
|
||||||
ansible_module.fail_json(
|
ansible_module.fail_json(
|
||||||
msg="'automember_type' is required unless state: rebuild")
|
msg="'action=member' is not usable with state '%s'" % state)
|
||||||
|
|
||||||
|
if state == "rebuilt":
|
||||||
|
if automember_type == "group" and rebuild_hosts is not None:
|
||||||
|
ansible_module.fail_json(
|
||||||
|
msg="state %s: hosts can not be set when type is '%s'" %
|
||||||
|
(state, automember_type))
|
||||||
|
if automember_type == "hostgroup" and rebuild_users is not None:
|
||||||
|
ansible_module.fail_json(
|
||||||
|
msg="state %s: users can not be set when type is '%s'" %
|
||||||
|
(state, automember_type))
|
||||||
|
|
||||||
|
elif state == "orphans_removed":
|
||||||
|
invalid.extend(["users", "hosts"])
|
||||||
|
|
||||||
|
if not automember_type:
|
||||||
|
ansible_module.fail_json(
|
||||||
|
msg="'automember_type' is required unless state: rebuilt")
|
||||||
|
|
||||||
|
else:
|
||||||
|
if default_group is not None:
|
||||||
|
for param in ["name", "exclusive", "inclusive", "users", "hosts"
|
||||||
|
"no_wait"]:
|
||||||
|
if ansible_module.params.get(param) is not None:
|
||||||
|
msg = "Cannot use {0} together with default_group"
|
||||||
|
ansible_module.fail_json(msg=msg.format(param))
|
||||||
|
if action == "member":
|
||||||
|
ansible_module.fail_json(
|
||||||
|
msg="Cannot use default_group with action:member")
|
||||||
|
if state == "absent":
|
||||||
|
ansible_module.fail_json(
|
||||||
|
msg="Cannot use default_group with state:absent")
|
||||||
|
|
||||||
|
else:
|
||||||
|
invalid = ["users", "hosts", "no_wait"]
|
||||||
|
|
||||||
|
if not automember_type:
|
||||||
|
ansible_module.fail_json(
|
||||||
|
msg="'automember_type' is required.")
|
||||||
|
|
||||||
ansible_module.params_fail_used_invalid(invalid, state, action)
|
ansible_module.params_fail_used_invalid(invalid, state, action)
|
||||||
|
|
||||||
@@ -307,15 +481,21 @@ def main():
|
|||||||
commands.append([name, 'automember_add', args])
|
commands.append([name, 'automember_add', args])
|
||||||
res_find = {}
|
res_find = {}
|
||||||
|
|
||||||
inclusive_add, inclusive_del = gen_add_del_lists(
|
if inclusive is not None:
|
||||||
transform_conditions(inclusive or []),
|
inclusive_add, inclusive_del = gen_add_del_lists(
|
||||||
res_find.get("automemberinclusiveregex", [])
|
transform_conditions(inclusive),
|
||||||
)
|
res_find.get("automemberinclusiveregex", [])
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
inclusive_add, inclusive_del = [], []
|
||||||
|
|
||||||
exclusive_add, exclusive_del = gen_add_del_lists(
|
if exclusive is not None:
|
||||||
transform_conditions(exclusive or []),
|
exclusive_add, exclusive_del = gen_add_del_lists(
|
||||||
res_find.get("automemberexclusiveregex", [])
|
transform_conditions(exclusive),
|
||||||
)
|
res_find.get("automemberexclusiveregex", [])
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
exclusive_add, exclusive_del = [], []
|
||||||
|
|
||||||
elif action == "member":
|
elif action == "member":
|
||||||
if res_find is None:
|
if res_find is None:
|
||||||
@@ -384,16 +564,45 @@ def main():
|
|||||||
'automember_remove_condition',
|
'automember_remove_condition',
|
||||||
condition_args])
|
condition_args])
|
||||||
|
|
||||||
elif state == "rebuild":
|
if len(names) == 0:
|
||||||
if automember_type:
|
if state == "rebuilt":
|
||||||
commands.append([None, 'automember_rebuild',
|
args = gen_rebuild_args(automember_type, rebuild_users,
|
||||||
{"type": automember_type}])
|
rebuild_hosts, no_wait)
|
||||||
if rebuild_users:
|
commands.append([None, 'automember_rebuild', args])
|
||||||
commands.append([None, 'automember_rebuild',
|
|
||||||
{"users": rebuild_users}])
|
elif state == "orphans_removed":
|
||||||
if rebuild_hosts:
|
res_find = find_automember_orphans(ansible_module,
|
||||||
commands.append([None, 'automember_rebuild',
|
automember_type)
|
||||||
{"hosts": rebuild_hosts}])
|
if res_find["count"] > 0:
|
||||||
|
commands.append([None, 'automember_find_orphans',
|
||||||
|
{'type': automember_type,
|
||||||
|
'remove': True}])
|
||||||
|
|
||||||
|
elif default_group is not None and state == "present":
|
||||||
|
res_find = find_automember_default_group(ansible_module,
|
||||||
|
automember_type)
|
||||||
|
|
||||||
|
if default_group == "":
|
||||||
|
if isinstance(res_find["automemberdefaultgroup"], list):
|
||||||
|
commands.append([None,
|
||||||
|
'automember_default_group_remove',
|
||||||
|
{'type': automember_type}])
|
||||||
|
ansible_module.warn("commands: %s" % repr(commands))
|
||||||
|
|
||||||
|
else:
|
||||||
|
dn_default_group = [DN(('cn', default_group),
|
||||||
|
('cn', '%ss' % automember_type),
|
||||||
|
('cn', 'accounts'),
|
||||||
|
ansible_module.ipa_get_basedn())]
|
||||||
|
if repr(res_find["automemberdefaultgroup"]) != \
|
||||||
|
repr(dn_default_group):
|
||||||
|
commands.append(
|
||||||
|
[None, 'automember_default_group_set',
|
||||||
|
{'type': automember_type,
|
||||||
|
'automemberdefaultgroup': default_group}])
|
||||||
|
|
||||||
|
else:
|
||||||
|
ansible_module.fail_json(msg="Invalid operation")
|
||||||
|
|
||||||
# Execute commands
|
# Execute commands
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Authors:
|
# Authors:
|
||||||
# Chris Procter <cprocter@redhat.com>
|
# Chris Procter <cprocter@redhat.com>
|
||||||
@@ -19,6 +18,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -65,13 +68,16 @@ RETURN = '''
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
from ansible.module_utils.ansible_freeipa_module import (
|
from ansible.module_utils.ansible_freeipa_module import (
|
||||||
FreeIPABaseModule, ipalib_errors
|
IPAAnsibleModule, ipalib_errors
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class AutomountLocation(FreeIPABaseModule):
|
class AutomountLocation(IPAAnsibleModule):
|
||||||
|
|
||||||
ipa_param_mapping = {}
|
def __init__(self, *args, **kwargs):
|
||||||
|
# pylint: disable=super-with-arguments
|
||||||
|
super(AutomountLocation, self).__init__(*args, **kwargs)
|
||||||
|
self.commands = []
|
||||||
|
|
||||||
def get_location(self, location):
|
def get_location(self, location):
|
||||||
try:
|
try:
|
||||||
@@ -84,40 +90,28 @@ class AutomountLocation(FreeIPABaseModule):
|
|||||||
return response.get("result", None)
|
return response.get("result", None)
|
||||||
|
|
||||||
def check_ipa_params(self):
|
def check_ipa_params(self):
|
||||||
if len(self.ipa_params.name) == 0:
|
if len(self.params_get("name")) == 0:
|
||||||
self.fail_json(msg="At least one location must be provided.")
|
self.fail_json(msg="At least one location must be provided.")
|
||||||
|
|
||||||
def define_ipa_commands(self):
|
def define_ipa_commands(self):
|
||||||
|
state = self.params_get("state")
|
||||||
|
|
||||||
for location_name in self.ipa_params.name:
|
for location_name in self.params_get("name"):
|
||||||
location = self.get_location(location_name)
|
location = self.get_location(location_name)
|
||||||
|
|
||||||
if not location and self.ipa_params.state == "present":
|
if not location and state == "present":
|
||||||
# does not exist and is wanted
|
# does not exist and is wanted
|
||||||
self.add_ipa_command(
|
self.commands.append(
|
||||||
"automountlocation_add",
|
(location_name, "automountlocation_add", {}))
|
||||||
name=location_name,
|
elif location and state == "absent":
|
||||||
args=None,
|
|
||||||
)
|
|
||||||
elif location and self.ipa_params.state == "absent":
|
|
||||||
# exists and is not wanted
|
# exists and is not wanted
|
||||||
self.add_ipa_command(
|
self.commands.append(
|
||||||
"automountlocation_del",
|
(location_name, "automountlocation_del", {}))
|
||||||
name=location_name,
|
|
||||||
args=None,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
ipa_module = AutomountLocation(
|
ipa_module = AutomountLocation(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
ipaadmin_principal=dict(type="str",
|
|
||||||
default="admin"
|
|
||||||
),
|
|
||||||
ipaadmin_password=dict(type="str",
|
|
||||||
required=False,
|
|
||||||
no_log=True
|
|
||||||
),
|
|
||||||
state=dict(type='str',
|
state=dict(type='str',
|
||||||
default='present',
|
default='present',
|
||||||
choices=['present', 'absent']
|
choices=['present', 'absent']
|
||||||
@@ -129,7 +123,12 @@ def main():
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
ipa_module.ipa_run()
|
ipaapi_context = ipa_module.params_get("ipaapi_context")
|
||||||
|
with ipa_module.ipa_connect(context=ipaapi_context):
|
||||||
|
ipa_module.check_ipa_params()
|
||||||
|
ipa_module.define_ipa_commands()
|
||||||
|
changed = ipa_module.execute_ipa_commands(ipa_module.commands)
|
||||||
|
ipa_module.exit_json(changed=changed)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -296,7 +299,7 @@ def main():
|
|||||||
"KDC:Disable Last Success",
|
"KDC:Disable Last Success",
|
||||||
"KDC:Disable Lockout",
|
"KDC:Disable Lockout",
|
||||||
"KDC:Disable Default Preauth for SPNs",
|
"KDC:Disable Default Preauth for SPNs",
|
||||||
""]), # noqa E128
|
""]), # noqa E128
|
||||||
selinuxusermaporder=dict(type="list", required=False,
|
selinuxusermaporder=dict(type="list", required=False,
|
||||||
aliases=['ipaselinuxusermaporder']),
|
aliases=['ipaselinuxusermaporder']),
|
||||||
selinuxusermapdefault=dict(type="str", required=False,
|
selinuxusermapdefault=dict(type="str", required=False,
|
||||||
@@ -362,15 +365,15 @@ def main():
|
|||||||
|
|
||||||
if params.get("ipadomainresolutionorder", None):
|
if params.get("ipadomainresolutionorder", None):
|
||||||
params["ipadomainresolutionorder"] = \
|
params["ipadomainresolutionorder"] = \
|
||||||
":".join(params["ipadomainresolutionorder"])
|
":".join(params["ipadomainresolutionorder"])
|
||||||
|
|
||||||
if params.get("ipausersearchfields", None):
|
if params.get("ipausersearchfields", None):
|
||||||
params["ipausersearchfields"] = \
|
params["ipausersearchfields"] = \
|
||||||
",".join(params["ipausersearchfields"])
|
",".join(params["ipausersearchfields"])
|
||||||
|
|
||||||
if params.get("ipagroupsearchfields", None):
|
if params.get("ipagroupsearchfields", None):
|
||||||
params["ipagroupsearchfields"] = \
|
params["ipagroupsearchfields"] = \
|
||||||
",".join(params["ipagroupsearchfields"])
|
",".join(params["ipagroupsearchfields"])
|
||||||
|
|
||||||
# verify limits on INT values.
|
# verify limits on INT values.
|
||||||
args_with_limits = [
|
args_with_limits = [
|
||||||
@@ -415,12 +418,12 @@ def main():
|
|||||||
if ansible_module.argument_spec.get(k):
|
if ansible_module.argument_spec.get(k):
|
||||||
arg_type = ansible_module.argument_spec[k]['type']
|
arg_type = ansible_module.argument_spec[k]['type']
|
||||||
if k in (
|
if k in (
|
||||||
'ipaselinuxusermaporder', 'domain_resolution_order'
|
'ipaselinuxusermaporder', 'domain_resolution_order'
|
||||||
):
|
):
|
||||||
exit_args[k] = result.get(key)[0].split('$')
|
exit_args[k] = result.get(key)[0].split('$')
|
||||||
elif k in (
|
elif k in (
|
||||||
'usersearch', 'groupsearch'
|
'usersearch', 'groupsearch'
|
||||||
):
|
):
|
||||||
exit_args[k] = result.get(key)[0].split(',')
|
exit_args[k] = result.get(key)[0].split(',')
|
||||||
elif isinstance(value, str) and arg_type == "list":
|
elif isinstance(value, str) and arg_type == "list":
|
||||||
exit_args[k] = [value]
|
exit_args[k] = [value]
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -21,6 +20,10 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -162,24 +165,23 @@ def gen_args(module, state, dnsconfig, forwarders, forward_policy,
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
forwarder_spec = dict(
|
forwarder_spec = dict(
|
||||||
ip_address=dict(type=str, required=True),
|
ip_address=dict(type=str, required=True),
|
||||||
port=dict(type=int, required=False, default=None)
|
port=dict(type=int, required=False, default=None)
|
||||||
)
|
)
|
||||||
|
|
||||||
ansible_module = IPAAnsibleModule(
|
ansible_module = IPAAnsibleModule(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
# dnsconfig
|
# dnsconfig
|
||||||
forwarders=dict(type='list', default=None, required=False,
|
forwarders=dict(type='list', default=None, required=False,
|
||||||
options=dict(**forwarder_spec)),
|
options=dict(**forwarder_spec)),
|
||||||
forward_policy=dict(type='str', required=False, default=None,
|
forward_policy=dict(type='str', required=False, default=None,
|
||||||
choices=['only', 'first', 'none']),
|
choices=['only', 'first', 'none']),
|
||||||
allow_sync_ptr=dict(type='bool', required=False, default=None),
|
allow_sync_ptr=dict(type='bool', required=False, default=None),
|
||||||
|
|
||||||
# general
|
# general
|
||||||
state=dict(type="str", default="present",
|
state=dict(type="str", default="present",
|
||||||
choices=["present", "absent"]),
|
choices=["present", "absent"]),
|
||||||
|
)
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ansible_module._ansible_debug = True
|
ansible_module._ansible_debug = True
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
"""DNS Record ansible-freeipa module."""
|
"""DNS Record ansible-freeipa module."""
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
@@ -866,8 +869,7 @@ from ansible.module_utils.ansible_freeipa_module import \
|
|||||||
import dns.reversename
|
import dns.reversename
|
||||||
import dns.resolver
|
import dns.resolver
|
||||||
|
|
||||||
import six
|
from ansible.module_utils import six
|
||||||
|
|
||||||
|
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
unicode = str
|
unicode = str
|
||||||
@@ -1106,12 +1108,13 @@ def configure_module():
|
|||||||
name=dict(type="list", aliases=["record_name"], default=None,
|
name=dict(type="list", aliases=["record_name"], default=None,
|
||||||
required=False),
|
required=False),
|
||||||
|
|
||||||
records=dict(type="list", default=None,
|
records=dict(type="list",
|
||||||
|
default=None,
|
||||||
options=dict(
|
options=dict(
|
||||||
# Here name is a simple string
|
# Here name is a simple string
|
||||||
name=dict(type='str', required=True,
|
name=dict(type='str', required=True,
|
||||||
aliases=['record_name']),
|
aliases=['record_name']),
|
||||||
**record_spec),
|
**record_spec),
|
||||||
),
|
),
|
||||||
|
|
||||||
# general
|
# general
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -200,45 +203,55 @@ dnszone:
|
|||||||
|
|
||||||
from ipapython.dnsutil import DNSName # noqa: E402
|
from ipapython.dnsutil import DNSName # noqa: E402
|
||||||
from ansible.module_utils.ansible_freeipa_module import (
|
from ansible.module_utils.ansible_freeipa_module import (
|
||||||
FreeIPABaseModule,
|
IPAAnsibleModule,
|
||||||
is_ip_address,
|
is_ip_address,
|
||||||
is_ip_network_address,
|
is_ip_network_address,
|
||||||
is_valid_port,
|
is_valid_port,
|
||||||
ipalib_errors
|
ipalib_errors,
|
||||||
|
compare_args_ipa,
|
||||||
|
IPAParamMapping,
|
||||||
) # noqa: E402
|
) # noqa: E402
|
||||||
import netaddr
|
import netaddr
|
||||||
import six
|
from ansible.module_utils import six
|
||||||
|
|
||||||
|
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
unicode = str
|
unicode = str
|
||||||
|
|
||||||
|
|
||||||
class DNSZoneModule(FreeIPABaseModule):
|
class DNSZoneModule(IPAAnsibleModule):
|
||||||
|
|
||||||
ipa_param_mapping = {
|
def __init__(self, *args, **kwargs):
|
||||||
# Direct Mapping
|
# pylint: disable=super-with-arguments
|
||||||
"idnsforwardpolicy": "forward_policy",
|
super(DNSZoneModule, self).__init__(*args, **kwargs)
|
||||||
"idnssoarefresh": "refresh",
|
|
||||||
"idnssoaretry": "retry",
|
ipa_param_mapping = {
|
||||||
"idnssoaexpire": "expire",
|
# Direct Mapping
|
||||||
"idnssoaminimum": "minimum",
|
"idnsforwardpolicy": "forward_policy",
|
||||||
"dnsttl": "ttl",
|
"idnssoarefresh": "refresh",
|
||||||
"dnsdefaultttl": "default_ttl",
|
"idnssoaretry": "retry",
|
||||||
"idnsallowsyncptr": "allow_sync_ptr",
|
"idnssoaexpire": "expire",
|
||||||
"idnsallowdynupdate": "dynamic_update",
|
"idnssoaminimum": "minimum",
|
||||||
"idnssecinlinesigning": "dnssec",
|
"dnsttl": "ttl",
|
||||||
"idnsupdatepolicy": "update_policy",
|
"dnsdefaultttl": "default_ttl",
|
||||||
# Mapping by method
|
"idnsallowsyncptr": "allow_sync_ptr",
|
||||||
"idnsforwarders": "get_ipa_idnsforwarders",
|
"idnsallowdynupdate": "dynamic_update",
|
||||||
"idnsallowtransfer": "get_ipa_idnsallowtransfer",
|
"idnssecinlinesigning": "dnssec",
|
||||||
"idnsallowquery": "get_ipa_idnsallowquery",
|
"idnsupdatepolicy": "update_policy",
|
||||||
"idnssoamname": "get_ipa_idnssoamname",
|
# Mapping by method
|
||||||
"idnssoarname": "get_ipa_idnssoarname",
|
"idnsforwarders": self.get_ipa_idnsforwarders,
|
||||||
"skip_nameserver_check": "get_ipa_skip_nameserver_check",
|
"idnsallowtransfer": self.get_ipa_idnsallowtransfer,
|
||||||
"skip_overlap_check": "get_ipa_skip_overlap_check",
|
"idnsallowquery": self.get_ipa_idnsallowquery,
|
||||||
"nsec3paramrecord": "get_ipa_nsec3paramrecord",
|
"idnssoamname": self.get_ipa_idnssoamname,
|
||||||
}
|
"idnssoarname": self.get_ipa_idnssoarname,
|
||||||
|
"skip_nameserver_check": self.get_ipa_skip_nameserver_check,
|
||||||
|
"skip_overlap_check": self.get_ipa_skip_overlap_check,
|
||||||
|
"nsec3paramrecord": self.get_ipa_nsec3paramrecord,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.commands = []
|
||||||
|
self.ipa_params = IPAParamMapping(self, ipa_param_mapping)
|
||||||
|
self.exit_args = {}
|
||||||
|
|
||||||
def validate_ips(self, ips, error_msg):
|
def validate_ips(self, ips, error_msg):
|
||||||
invalid_ips = [
|
invalid_ips = [
|
||||||
@@ -438,39 +451,34 @@ class DNSZoneModule(FreeIPABaseModule):
|
|||||||
for zone_name in self.get_zone_names():
|
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)
|
zone, is_zone_active = self.get_zone(zone_name)
|
||||||
args = self.get_ipa_command_args(zone=zone)
|
args = self.ipa_params.get_ipa_command_args(zone=zone)
|
||||||
|
|
||||||
if self.ipa_params.state in ["present", "enabled", "disabled"]:
|
if self.ipa_params.state in ["present", "enabled", "disabled"]:
|
||||||
if not zone:
|
if not 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.commands.append((zone_name, "dnszone_add", args))
|
||||||
is_zone_active = True
|
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 not compare_args_ipa(self, args, zone):
|
||||||
self.add_ipa_command("dnszone_mod", zone_name, args)
|
self.commands.append((zone_name, "dnszone_mod", args))
|
||||||
|
|
||||||
if self.ipa_params.state == "enabled" and not is_zone_active:
|
if self.ipa_params.state == "enabled" and not is_zone_active:
|
||||||
self.add_ipa_command("dnszone_enable", zone_name)
|
self.commands.append((zone_name, "dnszone_enable", {}))
|
||||||
|
|
||||||
if self.ipa_params.state == "disabled" and is_zone_active:
|
if self.ipa_params.state == "disabled" and is_zone_active:
|
||||||
self.add_ipa_command("dnszone_disable", zone_name)
|
self.commands.append((zone_name, "dnszone_disable", {}))
|
||||||
|
|
||||||
if self.ipa_params.state == "absent" and zone is not None:
|
if self.ipa_params.state == "absent" and zone is not None:
|
||||||
self.add_ipa_command("dnszone_del", zone_name)
|
self.commands.append((zone_name, "dnszone_del", {}))
|
||||||
|
|
||||||
def process_command_result(self, name, command, args, result):
|
def process_results(self, _result, command, name, _args, exit_args):
|
||||||
# pylint: disable=super-with-arguments
|
|
||||||
super(DNSZoneModule, self).process_command_result(
|
|
||||||
name, command, args, result
|
|
||||||
)
|
|
||||||
if command == "dnszone_add" and self.ipa_params.name_from_ip:
|
if command == "dnszone_add" and self.ipa_params.name_from_ip:
|
||||||
dnszone_exit_args = self.exit_args.setdefault('dnszone', {})
|
exit_args.setdefault('dnszone', {})["name"] = name
|
||||||
dnszone_exit_args['name'] = name
|
|
||||||
|
|
||||||
|
|
||||||
def get_argument_spec():
|
def get_argument_spec():
|
||||||
@@ -529,12 +537,24 @@ def get_argument_spec():
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
DNSZoneModule(
|
ansible_module = DNSZoneModule(
|
||||||
argument_spec=get_argument_spec(),
|
argument_spec=get_argument_spec(),
|
||||||
mutually_exclusive=[["name", "name_from_ip"]],
|
mutually_exclusive=[["name", "name_from_ip"]],
|
||||||
required_one_of=[["name", "name_from_ip"]],
|
required_one_of=[["name", "name_from_ip"]],
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
).ipa_run()
|
)
|
||||||
|
|
||||||
|
exit_args = {}
|
||||||
|
ipaapi_context = ansible_module.params_get("ipaapi_context")
|
||||||
|
with ansible_module.ipa_connect(context=ipaapi_context):
|
||||||
|
ansible_module.check_ipa_params()
|
||||||
|
ansible_module.define_ipa_commands()
|
||||||
|
changed = ansible_module.execute_ipa_commands(
|
||||||
|
ansible_module.commands,
|
||||||
|
result_handler=DNSZoneModule.process_results,
|
||||||
|
exit_args=exit_args
|
||||||
|
)
|
||||||
|
ansible_module.exit_json(changed=changed, **exit_args)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -390,13 +393,13 @@ def main():
|
|||||||
# If yes: modify
|
# If yes: modify
|
||||||
# Also if it is a modification from nonposix to posix
|
# Also if it is a modification from nonposix to posix
|
||||||
# or nonposix to external.
|
# or nonposix to external.
|
||||||
if not compare_args_ipa(ansible_module, args,
|
if not compare_args_ipa(
|
||||||
res_find) or \
|
ansible_module, args, res_find
|
||||||
(
|
) or (
|
||||||
not is_posix_group(res_find) and
|
not is_posix_group(res_find) and
|
||||||
not is_external_group(res_find) and
|
not is_external_group(res_find) and
|
||||||
(posix or external)
|
(posix or external)
|
||||||
):
|
):
|
||||||
if posix:
|
if posix:
|
||||||
args['posix'] = True
|
args['posix'] = True
|
||||||
if external:
|
if external:
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -403,7 +406,7 @@ host:
|
|||||||
from ansible.module_utils.ansible_freeipa_module import \
|
from ansible.module_utils.ansible_freeipa_module import \
|
||||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
|
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
|
||||||
encode_certificate, is_ipv4_addr, is_ipv6_addr, ipalib_errors
|
encode_certificate, is_ipv4_addr, is_ipv6_addr, ipalib_errors
|
||||||
import six
|
from ansible.module_utils import six
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
unicode = str
|
unicode = str
|
||||||
|
|
||||||
@@ -436,7 +439,7 @@ def find_dnsrecord(module, name):
|
|||||||
This function may raise ipalib_errors.NotFound in some cases,
|
This function may raise ipalib_errors.NotFound in some cases,
|
||||||
and it should be handled by the caller.
|
and it should be handled by the caller.
|
||||||
"""
|
"""
|
||||||
domain_name = name[name.find(".")+1:]
|
domain_name = name[name.find(".") + 1:]
|
||||||
host_name = name[:name.find(".")]
|
host_name = name[:name.find(".")]
|
||||||
|
|
||||||
_args = {
|
_args = {
|
||||||
@@ -1228,7 +1231,7 @@ def main():
|
|||||||
}])
|
}])
|
||||||
|
|
||||||
if len(dnsrecord_a_add) > 0 or len(dnsrecord_aaaa_add) > 0:
|
if len(dnsrecord_a_add) > 0 or len(dnsrecord_aaaa_add) > 0:
|
||||||
domain_name = name[name.find(".")+1:]
|
domain_name = name[name.find(".") + 1:]
|
||||||
host_name = name[:name.find(".")]
|
host_name = name[:name.find(".")]
|
||||||
|
|
||||||
_args = {"idnsname": host_name}
|
_args = {"idnsname": host_name}
|
||||||
@@ -1245,7 +1248,7 @@ def main():
|
|||||||
"dnsrecord_add", _args])
|
"dnsrecord_add", _args])
|
||||||
|
|
||||||
if len(dnsrecord_a_del) > 0 or len(dnsrecord_aaaa_del) > 0:
|
if len(dnsrecord_a_del) > 0 or len(dnsrecord_aaaa_del) > 0:
|
||||||
domain_name = name[name.find(".")+1:]
|
domain_name = name[name.find(".") + 1:]
|
||||||
host_name = name[:name.find(".")]
|
host_name = name[:name.find(".")]
|
||||||
|
|
||||||
# There seems to be an issue with dnsrecord_del (not
|
# There seems to be an issue with dnsrecord_del (not
|
||||||
@@ -1361,7 +1364,7 @@ def main():
|
|||||||
|
|
||||||
if "arecord" in dnsrecord_args or \
|
if "arecord" in dnsrecord_args or \
|
||||||
"aaaarecord" in dnsrecord_args:
|
"aaaarecord" in dnsrecord_args:
|
||||||
domain_name = name[name.find(".")+1:]
|
domain_name = name[name.find(".") + 1:]
|
||||||
host_name = name[:name.find(".")]
|
host_name = name[:name.find(".")]
|
||||||
dnsrecord_args["idnsname"] = host_name
|
dnsrecord_args["idnsname"] = host_name
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
"""ansible-freeipa module to manage FreeIPA privileges."""
|
"""ansible-freeipa module to manage FreeIPA privileges."""
|
||||||
|
|
||||||
|
|
||||||
@@ -108,8 +111,9 @@ RETURN = """
|
|||||||
|
|
||||||
|
|
||||||
from ansible.module_utils.ansible_freeipa_module import \
|
from ansible.module_utils.ansible_freeipa_module import \
|
||||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists
|
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
|
||||||
import six
|
gen_intersection_list
|
||||||
|
from ansible.module_utils import six
|
||||||
|
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
unicode = str
|
unicode = str
|
||||||
@@ -126,22 +130,6 @@ def find_privilege(module, name):
|
|||||||
return _result["result"]
|
return _result["result"]
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
|
||||||
def result_handler(module, result, command, name, args, errors):
|
|
||||||
# Get all errors
|
|
||||||
# All "already a member" and "not a member" failures in the
|
|
||||||
# result are ignored. All others are reported.
|
|
||||||
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))
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
ansible_module = IPAAnsibleModule(
|
ansible_module = IPAAnsibleModule(
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
@@ -230,47 +218,31 @@ def main():
|
|||||||
if action == "privilege":
|
if action == "privilege":
|
||||||
# Found the privilege
|
# Found the privilege
|
||||||
if res_find is not None:
|
if res_find is not None:
|
||||||
res_cmp = {
|
cmp = {"description": res_find.get("description")}
|
||||||
k: v for k, v in res_find.items()
|
if not compare_args_ipa(ansible_module, args, cmp):
|
||||||
if k not in [
|
|
||||||
"objectclass", "cn", "dn",
|
|
||||||
"memberof_permisssion"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
# For all settings is args, check if there are
|
|
||||||
# different settings in the find result.
|
|
||||||
# If yes: modify
|
|
||||||
if args and not compare_args_ipa(ansible_module, args,
|
|
||||||
res_cmp):
|
|
||||||
commands.append([name, "privilege_mod", args])
|
commands.append([name, "privilege_mod", args])
|
||||||
else:
|
else:
|
||||||
commands.append([name, "privilege_add", args])
|
commands.append([name, "privilege_add", args])
|
||||||
res_find = {}
|
res_find = {}
|
||||||
|
|
||||||
member_args = {}
|
# Generate addition and removal lists
|
||||||
if permission:
|
permission_add, permission_del = gen_add_del_lists(
|
||||||
member_args['permission'] = permission
|
permission, res_find.get("memberof_permission")
|
||||||
|
)
|
||||||
|
|
||||||
if not compare_args_ipa(ansible_module, member_args,
|
# Add members
|
||||||
res_find):
|
if len(permission_add) > 0:
|
||||||
|
commands.append([name, "privilege_add_permission",
|
||||||
# Generate addition and removal lists
|
{
|
||||||
permission_add, permission_del = gen_add_del_lists(
|
"permission": permission_add,
|
||||||
permission, res_find.get("member_permission"))
|
}])
|
||||||
|
# Remove members
|
||||||
# Add members
|
if len(permission_del) > 0:
|
||||||
if len(permission_add) > 0:
|
commands.append([
|
||||||
commands.append([name, "privilege_add_permission",
|
name,
|
||||||
{
|
"privilege_remove_permission",
|
||||||
"permission": permission_add,
|
{"permission": permission_del}
|
||||||
}])
|
])
|
||||||
# Remove members
|
|
||||||
if len(permission_del) > 0:
|
|
||||||
commands.append([
|
|
||||||
name,
|
|
||||||
"privilege_remove_permission",
|
|
||||||
{"permission": permission_del}
|
|
||||||
])
|
|
||||||
|
|
||||||
elif action == "member":
|
elif action == "member":
|
||||||
if res_find is None:
|
if res_find is None:
|
||||||
@@ -280,8 +252,11 @@ def main():
|
|||||||
if permission is None:
|
if permission is None:
|
||||||
ansible_module.fail_json(msg="No permission given")
|
ansible_module.fail_json(msg="No permission given")
|
||||||
|
|
||||||
commands.append([name, "privilege_add_permission",
|
permission = gen_add_list(
|
||||||
{"permission": permission}])
|
permission, res_find.get("memberof_permission"))
|
||||||
|
if permission:
|
||||||
|
commands.append([name, "privilege_add_permission",
|
||||||
|
{"permission": permission}])
|
||||||
|
|
||||||
elif state == "absent":
|
elif state == "absent":
|
||||||
if action == "privilege":
|
if action == "privilege":
|
||||||
@@ -296,10 +271,11 @@ def main():
|
|||||||
if permission is None:
|
if permission is None:
|
||||||
ansible_module.fail_json(msg="No permission given")
|
ansible_module.fail_json(msg="No permission given")
|
||||||
|
|
||||||
commands.append([name, "privilege_remove_permission",
|
permission = gen_intersection_list(
|
||||||
{
|
permission, res_find.get("memberof_permission"))
|
||||||
"permission": permission,
|
if permission:
|
||||||
}])
|
commands.append([name, "privilege_remove_permission",
|
||||||
|
{"permission": permission}])
|
||||||
|
|
||||||
elif state == "renamed":
|
elif state == "renamed":
|
||||||
if not rename:
|
if not rename:
|
||||||
@@ -318,7 +294,8 @@ def main():
|
|||||||
|
|
||||||
# Execute commands
|
# Execute commands
|
||||||
|
|
||||||
changed = ansible_module.execute_ipa_commands(commands, result_handler)
|
changed = ansible_module.execute_ipa_commands(
|
||||||
|
commands, fail_on_member_errors=True)
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""ansible-freeipa iparole module implementation."""
|
"""ansible-freeipa iparole module implementation."""
|
||||||
|
|
||||||
@@ -21,6 +20,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -101,7 +104,7 @@ EXAMPLES = """
|
|||||||
from ansible.module_utils._text import to_text
|
from ansible.module_utils._text import to_text
|
||||||
from ansible.module_utils.ansible_freeipa_module import \
|
from ansible.module_utils.ansible_freeipa_module import \
|
||||||
IPAAnsibleModule, gen_add_del_lists, compare_args_ipa
|
IPAAnsibleModule, gen_add_del_lists, compare_args_ipa
|
||||||
import six
|
from ansible.module_utils import six
|
||||||
|
|
||||||
|
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
@@ -196,7 +199,7 @@ def ensure_absent_state(module, name, action, res_find):
|
|||||||
member_args = {}
|
member_args = {}
|
||||||
for key in ['user', 'group', 'host', 'hostgroup']:
|
for key in ['user', 'group', 'host', 'hostgroup']:
|
||||||
items = member_intersect(
|
items = member_intersect(
|
||||||
module, key, 'member_%s' % key, res_find)
|
module, key, 'member_%s' % key, res_find)
|
||||||
if items:
|
if items:
|
||||||
member_args[key] = items
|
member_args[key] = items
|
||||||
|
|
||||||
@@ -295,7 +298,7 @@ def ensure_members_are_present(module, name, res_find):
|
|||||||
member_args = {}
|
member_args = {}
|
||||||
for key in ['user', 'group', 'host', 'hostgroup']:
|
for key in ['user', 'group', 'host', 'hostgroup']:
|
||||||
items = member_difference(
|
items = member_difference(
|
||||||
module, key, 'member_%s' % key, res_find)
|
module, key, 'member_%s' % key, res_find)
|
||||||
if items:
|
if items:
|
||||||
member_args[key] = items
|
member_args[key] = items
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -183,21 +186,23 @@ EXAMPLES = """
|
|||||||
ipaadmin_password: SomeADMINpassword
|
ipaadmin_password: SomeADMINpassword
|
||||||
name: HTTP/www.example.com
|
name: HTTP/www.example.com
|
||||||
certificate:
|
certificate:
|
||||||
- MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAw
|
- >
|
||||||
DzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8xDT
|
MIIC/zCCAeegAwIBAgIUMNHIbn+hhrOVew/2WbkteisV29QwDQYJKoZIhvcNAQELBQAw
|
||||||
ALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVGFYpH
|
DzENMAsGA1UEAwwEdGVzdDAeFw0yMDAyMDQxNDQxMDhaFw0zMDAyMDExNDQxMDhaMA8x
|
||||||
VkcDfVnNInE1Y/pFciegdzqTjMwUWlRL4Zt3u96GhaMLRbtk+OfEkzLUAhWBOwEraELJzM
|
DTALBgNVBAMMBHRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+XVVG
|
||||||
LJOMvjYF3C+TiGO7dStFLikZmccuSsSIXjnzIPwBXa8KvgRVRyGLoVvGbLJvmjfMXp0nIT
|
FYpHVkcDfVnNInE1Y/pFciegdzqTjMwUWlRL4Zt3u96GhaMLRbtk+OfEkzLUAhWBOwEr
|
||||||
oTx/i74KF9S++WEes9H5ErJ99CDhLKFgq0amnvsgparYXhypHaRLnikn0vQINt55YoEd1s
|
aELJzMLJOMvjYF3C+TiGO7dStFLikZmccuSsSIXjnzIPwBXa8KvgRVRyGLoVvGbLJvmj
|
||||||
4KrvEcD2VdZkIMPbLRu2zFvMprF3cjQQG4LT9ggfEXNIPZ1nQWAnAsu7OJEkNF+E4Mkmpc
|
fMXp0nIToTx/i74KF9S++WEes9H5ErJ99CDhLKFgq0amnvsgparYXhypHaRLnikn0vQI
|
||||||
xj9aGUVt5bsq1D+Tzj3GsidSX0nSNcZ2JltXRnL/5v63g5cZyE+nAgMBAAGjUzBRMB0GA1
|
Nt55YoEd1s4KrvEcD2VdZkIMPbLRu2zFvMprF3cjQQG4LT9ggfEXNIPZ1nQWAnAsu7OJ
|
||||||
UdDgQWBBRV0j7JYukuH/r/t9+QeNlRLXDlEDAfBgNVHSMEGDAWgBRV0j7JYukuH/r/t9+Q
|
EkNF+E4Mkmpcxj9aGUVt5bsq1D+Tzj3GsidSX0nSNcZ2JltXRnL/5v63g5cZyE+nAgMB
|
||||||
eNlRLXDlEDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCgVy1+1kNwHs
|
AAGjUzBRMB0GA1UdDgQWBBRV0j7JYukuH/r/t9+QeNlRLXDlEDAfBgNVHSMEGDAWgBRV
|
||||||
5y1Zp0WjMWGCJC6/zw7FDG4OW5r2GJiCXZYdJ0UonY9ZtoVLJPrp2/DAv1m5DtnDhBYqic
|
0j7JYukuH/r/t9+QeNlRLXDlEDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
|
||||||
uPgLzEkOS1KdTi20Otm/J4yxLLrZC5W4x0XOeSVPXOJuQWfwQ5pPvKkn6WxYUYkGwIt1OH
|
A4IBAQCgVy1+1kNwHs5y1Zp0WjMWGCJC6/zw7FDG4OW5r2GJiCXZYdJ0UonY9ZtoVLJP
|
||||||
2nSMngkbami3CbSmKZOCpgQIiSlQeDJ8oGjWFMLDymYSHoVOIXHwNoooyEiaio3693l6no
|
rp2/DAv1m5DtnDhBYqicuPgLzEkOS1KdTi20Otm/J4yxLLrZC5W4x0XOeSVPXOJuQWfw
|
||||||
obyGv49zyCVLVR1DC7i6RJ186ql0av+D4vPoiF5mX7+sKC2E8xEj9uKQ5GTWRh59VnRBVC
|
Q5pPvKkn6WxYUYkGwIt1OH2nSMngkbami3CbSmKZOCpgQIiSlQeDJ8oGjWFMLDymYSHo
|
||||||
/SiMJ/H78tJnBAvoBwXxSEvj8Z3Kjm/BQqZfv4IBsA5yqV7MVq
|
VOIXHwNoooyEiaio3693l6noobyGv49zyCVLVR1DC7i6RJ186ql0av+D4vPoiF5mX7+s
|
||||||
|
KC2E8xEj9uKQ5GTWRh59VnRBVC/SiMJ/H78tJnBAvoBwXxSEvj8Z3Kjm/BQqZfv4IBsA
|
||||||
|
5yqV7MVq
|
||||||
action: member
|
action: member
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
@@ -224,7 +229,8 @@ RETURN = """
|
|||||||
|
|
||||||
from ansible.module_utils.ansible_freeipa_module import \
|
from ansible.module_utils.ansible_freeipa_module import \
|
||||||
IPAAnsibleModule, compare_args_ipa, encode_certificate, \
|
IPAAnsibleModule, compare_args_ipa, encode_certificate, \
|
||||||
gen_add_del_lists, ipalib_errors
|
gen_add_del_lists, gen_add_list, gen_intersection_list, ipalib_errors, \
|
||||||
|
api_get_realm, to_text
|
||||||
|
|
||||||
|
|
||||||
def find_service(module, name):
|
def find_service(module, name):
|
||||||
@@ -283,9 +289,7 @@ def gen_args_smb(netbiosname, ok_as_delegate, ok_to_auth_as_delegate):
|
|||||||
return _args
|
return _args
|
||||||
|
|
||||||
|
|
||||||
def check_parameters(module, state, action, names, parameters):
|
def check_parameters(module, state, action, names):
|
||||||
assert isinstance(parameters, dict)
|
|
||||||
|
|
||||||
# invalid parameters for everything but state 'present', action 'service'.
|
# invalid parameters for everything but state 'present', action 'service'.
|
||||||
invalid = ['pac_type', 'auth_ind', 'skip_host_check',
|
invalid = ['pac_type', 'auth_ind', 'skip_host_check',
|
||||||
'force', 'requires_pre_auth', 'ok_as_delegate',
|
'force', 'requires_pre_auth', 'ok_as_delegate',
|
||||||
@@ -307,8 +311,8 @@ def check_parameters(module, state, action, names, parameters):
|
|||||||
invalid = ['delete_continue']
|
invalid = ['delete_continue']
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not parameters.get('smb', False)
|
not module.params_get('smb')
|
||||||
and parameters.get('netbiosname')
|
and module.params_get('netbiosname')
|
||||||
):
|
):
|
||||||
module.fail_json(
|
module.fail_json(
|
||||||
msg="Argument 'netbiosname' can not be used without "
|
msg="Argument 'netbiosname' can not be used without "
|
||||||
@@ -405,23 +409,6 @@ def init_ansible_module():
|
|||||||
return ansible_module
|
return ansible_module
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
|
||||||
def result_handler(module, result, command, name, args, errors):
|
|
||||||
# Get all errors
|
|
||||||
# All "already a member" and "not a member" failures in the
|
|
||||||
# result are ignored. All others are reported.
|
|
||||||
if "failed" in result and len(result["failed"]) > 0:
|
|
||||||
for item in result["failed"]:
|
|
||||||
failed_item = result["failed"][item]
|
|
||||||
for member_type in failed_item:
|
|
||||||
for member, failure in failed_item[member_type]:
|
|
||||||
if "already a member" in failure \
|
|
||||||
or "not a member" in failure:
|
|
||||||
continue
|
|
||||||
errors.append("%s: %s %s: %s" % (
|
|
||||||
command, member_type, member, failure))
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
ansible_module = init_ansible_module()
|
ansible_module = init_ansible_module()
|
||||||
|
|
||||||
@@ -447,23 +434,6 @@ def main():
|
|||||||
|
|
||||||
host = ansible_module.params_get("host")
|
host = ansible_module.params_get("host")
|
||||||
|
|
||||||
allow_create_keytab_user = ansible_module.params_get(
|
|
||||||
"allow_create_keytab_user")
|
|
||||||
allow_create_keytab_group = ansible_module.params_get(
|
|
||||||
"allow_create_keytab_group")
|
|
||||||
allow_create_keytab_host = ansible_module.params_get(
|
|
||||||
"allow_create_keytab_host")
|
|
||||||
allow_create_keytab_hostgroup = ansible_module.params_get(
|
|
||||||
"allow_create_keytab_hostgroup")
|
|
||||||
|
|
||||||
allow_retrieve_keytab_user = ansible_module.params_get(
|
|
||||||
"allow_retrieve_keytab_user")
|
|
||||||
allow_retrieve_keytab_group = ansible_module.params_get(
|
|
||||||
"allow_retrieve_keytab_group")
|
|
||||||
allow_retrieve_keytab_host = ansible_module.params_get(
|
|
||||||
"allow_retrieve_keytab_host")
|
|
||||||
allow_retrieve_keytab_hostgroup = ansible_module.params_get(
|
|
||||||
"allow_retrieve_keytab_hostgroup")
|
|
||||||
delete_continue = ansible_module.params_get("delete_continue")
|
delete_continue = ansible_module.params_get("delete_continue")
|
||||||
|
|
||||||
# action
|
# action
|
||||||
@@ -472,7 +442,7 @@ def main():
|
|||||||
state = ansible_module.params_get("state")
|
state = ansible_module.params_get("state")
|
||||||
|
|
||||||
# check parameters
|
# check parameters
|
||||||
check_parameters(ansible_module, state, action, names, vars())
|
check_parameters(ansible_module, state, action, names)
|
||||||
|
|
||||||
# Init
|
# Init
|
||||||
|
|
||||||
@@ -489,9 +459,48 @@ def main():
|
|||||||
msg="Skipping host check is not supported by your IPA version")
|
msg="Skipping host check is not supported by your IPA version")
|
||||||
|
|
||||||
commands = []
|
commands = []
|
||||||
|
keytab_members = ["user", "group", "host", "hostgroup"]
|
||||||
|
|
||||||
for name in names:
|
for name in names:
|
||||||
res_find = find_service(ansible_module, name)
|
res_find = find_service(ansible_module, name)
|
||||||
|
res_principals = []
|
||||||
|
|
||||||
|
keytab = {
|
||||||
|
"retrieve": {
|
||||||
|
"allow": {k: [] for k in keytab_members},
|
||||||
|
"disallow": {k: [] for k in keytab_members},
|
||||||
|
},
|
||||||
|
"create": {
|
||||||
|
"allow": {k: [] for k in keytab_members},
|
||||||
|
"disallow": {k: [] for k in keytab_members},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
certificate_add, certificate_del = [], []
|
||||||
|
host_add, host_del = [], []
|
||||||
|
principal_add, principal_del = [], []
|
||||||
|
|
||||||
|
if principal and res_find:
|
||||||
|
# When comparing principals to the existing ones,
|
||||||
|
# the REALM is needded, and are added here for those
|
||||||
|
# that do not have it.
|
||||||
|
principal = [
|
||||||
|
p if "@" in p
|
||||||
|
else "%s@%s" % (p, api_get_realm())
|
||||||
|
for p in principal
|
||||||
|
]
|
||||||
|
principal = list(set(principal))
|
||||||
|
|
||||||
|
# Create list of existing principal aliases as strings
|
||||||
|
# to compare with provided ones.
|
||||||
|
canonicalname = {
|
||||||
|
to_text(p)
|
||||||
|
for p in res_find.get("krbcanonicalname", [])
|
||||||
|
}
|
||||||
|
res_principals = [
|
||||||
|
to_text(elem)
|
||||||
|
for elem in res_find.get("krbprincipalname", [])
|
||||||
|
]
|
||||||
|
res_principals = list(set(res_principals) - canonicalname)
|
||||||
|
|
||||||
if state == "present":
|
if state == "present":
|
||||||
if action == "service":
|
if action == "service":
|
||||||
@@ -520,37 +529,8 @@ def main():
|
|||||||
|
|
||||||
if res_find is None:
|
if res_find is None:
|
||||||
commands.append([name, 'service_add', args])
|
commands.append([name, 'service_add', args])
|
||||||
|
# Use an empty res_find to manage members
|
||||||
certificate_add = certificate or []
|
res_find = {}
|
||||||
certificate_del = []
|
|
||||||
host_add = host or []
|
|
||||||
host_del = []
|
|
||||||
principal_add = principal or []
|
|
||||||
principal_del = []
|
|
||||||
allow_create_keytab_user_add = \
|
|
||||||
allow_create_keytab_user or []
|
|
||||||
allow_create_keytab_user_del = []
|
|
||||||
allow_create_keytab_group_add = \
|
|
||||||
allow_create_keytab_group or []
|
|
||||||
allow_create_keytab_group_del = []
|
|
||||||
allow_create_keytab_host_add = \
|
|
||||||
allow_create_keytab_host or []
|
|
||||||
allow_create_keytab_host_del = []
|
|
||||||
allow_create_keytab_hostgroup_add = \
|
|
||||||
allow_create_keytab_hostgroup or []
|
|
||||||
allow_create_keytab_hostgroup_del = []
|
|
||||||
allow_retrieve_keytab_user_add = \
|
|
||||||
allow_retrieve_keytab_user or []
|
|
||||||
allow_retrieve_keytab_user_del = []
|
|
||||||
allow_retrieve_keytab_group_add = \
|
|
||||||
allow_retrieve_keytab_group or []
|
|
||||||
allow_retrieve_keytab_group_del = []
|
|
||||||
allow_retrieve_keytab_host_add = \
|
|
||||||
allow_retrieve_keytab_host or []
|
|
||||||
allow_retrieve_keytab_host_del = []
|
|
||||||
allow_retrieve_keytab_hostgroup_add = \
|
|
||||||
allow_retrieve_keytab_hostgroup or []
|
|
||||||
allow_retrieve_keytab_hostgroup_del = []
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
for remove in ['skip_host_check', 'force']:
|
for remove in ['skip_host_check', 'force']:
|
||||||
@@ -563,207 +543,54 @@ def main():
|
|||||||
args.get("krbprincipalauthind", [""]) ==
|
args.get("krbprincipalauthind", [""]) ==
|
||||||
res_find.get("krbprincipalauthind", [""])
|
res_find.get("krbprincipalauthind", [""])
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
del args["krbprincipalauthind"]
|
del args["krbprincipalauthind"]
|
||||||
|
|
||||||
if not compare_args_ipa(ansible_module, args,
|
if not compare_args_ipa(ansible_module, args,
|
||||||
res_find):
|
res_find):
|
||||||
commands.append([name, "service_mod", args])
|
commands.append([name, "service_mod", args])
|
||||||
|
|
||||||
certificate_add, certificate_del = gen_add_del_lists(
|
# Manage members
|
||||||
certificate, res_find.get("usercertificate"))
|
certificate_add, certificate_del = gen_add_del_lists(
|
||||||
|
certificate, res_find.get("usercertificate"))
|
||||||
|
|
||||||
host_add, host_del = gen_add_del_lists(
|
host_add, host_del = gen_add_del_lists(
|
||||||
host, res_find.get('managedby_host', []))
|
host, res_find.get('managedby_host'))
|
||||||
|
|
||||||
principal_add, principal_del = gen_add_del_lists(
|
principal_add, principal_del = gen_add_del_lists(
|
||||||
principal, res_find.get("principal"))
|
principal, res_principals)
|
||||||
|
|
||||||
(allow_create_keytab_user_add,
|
|
||||||
allow_create_keytab_user_del) = \
|
|
||||||
gen_add_del_lists(
|
|
||||||
allow_create_keytab_user, res_find.get(
|
|
||||||
'ipaallowedtoperform_write_keys_user',
|
|
||||||
[]))
|
|
||||||
(allow_retrieve_keytab_user_add,
|
|
||||||
allow_retrieve_keytab_user_del) = \
|
|
||||||
gen_add_del_lists(
|
|
||||||
allow_retrieve_keytab_user, res_find.get(
|
|
||||||
'ipaallowedtoperform_read_keys_user',
|
|
||||||
[]))
|
|
||||||
(allow_create_keytab_group_add,
|
|
||||||
allow_create_keytab_group_del) = \
|
|
||||||
gen_add_del_lists(
|
|
||||||
allow_create_keytab_group, res_find.get(
|
|
||||||
'ipaallowedtoperform_write_keys_group',
|
|
||||||
[]))
|
|
||||||
(allow_retrieve_keytab_group_add,
|
|
||||||
allow_retrieve_keytab_group_del) = \
|
|
||||||
gen_add_del_lists(
|
|
||||||
allow_retrieve_keytab_group,
|
|
||||||
res_find.get(
|
|
||||||
'ipaallowedtoperform_read_keys_group',
|
|
||||||
[]))
|
|
||||||
(allow_create_keytab_host_add,
|
|
||||||
allow_create_keytab_host_del) = \
|
|
||||||
gen_add_del_lists(
|
|
||||||
allow_create_keytab_host,
|
|
||||||
res_find.get(
|
|
||||||
'ipaallowedtoperform_write_keys_host',
|
|
||||||
[]))
|
|
||||||
(allow_retrieve_keytab_host_add,
|
|
||||||
allow_retrieve_keytab_host_del) = \
|
|
||||||
gen_add_del_lists(
|
|
||||||
allow_retrieve_keytab_host,
|
|
||||||
res_find.get(
|
|
||||||
'ipaallowedtoperform_read_keys_host',
|
|
||||||
[]))
|
|
||||||
(allow_create_keytab_hostgroup_add,
|
|
||||||
allow_create_keytab_hostgroup_del) = \
|
|
||||||
gen_add_del_lists(
|
|
||||||
allow_create_keytab_hostgroup,
|
|
||||||
res_find.get(
|
|
||||||
'ipaallowedtoperform_write_keys_hostgroup',
|
|
||||||
[]))
|
|
||||||
(allow_retrieve_keytab_hostgroup_add,
|
|
||||||
allow_retrieve_keytab_hostgroup_del) = \
|
|
||||||
gen_add_del_lists(
|
|
||||||
allow_retrieve_keytab_hostgroup,
|
|
||||||
res_find.get(
|
|
||||||
'ipaallowedtoperform_read_keys_hostgroup',
|
|
||||||
[]))
|
|
||||||
|
|
||||||
elif action == "member":
|
elif action == "member":
|
||||||
if res_find is None:
|
if res_find is None:
|
||||||
ansible_module.fail_json(msg="No service '%s'" % name)
|
ansible_module.fail_json(msg="No service '%s'" % name)
|
||||||
|
|
||||||
existing = res_find.get('usercertificate', [])
|
certificate_add = gen_add_list(
|
||||||
if certificate is None:
|
certificate, res_find.get("usercertificate"))
|
||||||
certificate_add = []
|
|
||||||
else:
|
|
||||||
certificate_add = [c for c in certificate
|
|
||||||
if c not in existing]
|
|
||||||
certificate_del = []
|
|
||||||
host_add = host or []
|
|
||||||
host_del = []
|
|
||||||
principal_add = principal or []
|
|
||||||
principal_del = []
|
|
||||||
|
|
||||||
allow_create_keytab_user_add = \
|
host_add = gen_add_list(
|
||||||
allow_create_keytab_user or []
|
host, res_find.get('managedby_host'))
|
||||||
allow_create_keytab_user_del = []
|
|
||||||
allow_create_keytab_group_add = \
|
|
||||||
allow_create_keytab_group or []
|
|
||||||
allow_create_keytab_group_del = []
|
|
||||||
allow_create_keytab_host_add = \
|
|
||||||
allow_create_keytab_host or []
|
|
||||||
allow_create_keytab_host_del = []
|
|
||||||
allow_create_keytab_hostgroup_add = \
|
|
||||||
allow_create_keytab_hostgroup or []
|
|
||||||
allow_create_keytab_hostgroup_del = []
|
|
||||||
allow_retrieve_keytab_user_add = \
|
|
||||||
allow_retrieve_keytab_user or []
|
|
||||||
allow_retrieve_keytab_user_del = []
|
|
||||||
allow_retrieve_keytab_group_add = \
|
|
||||||
allow_retrieve_keytab_group or []
|
|
||||||
allow_retrieve_keytab_group_del = []
|
|
||||||
allow_retrieve_keytab_host_add = \
|
|
||||||
allow_retrieve_keytab_host or []
|
|
||||||
allow_retrieve_keytab_host_del = []
|
|
||||||
allow_retrieve_keytab_hostgroup_add = \
|
|
||||||
allow_retrieve_keytab_hostgroup or []
|
|
||||||
allow_retrieve_keytab_hostgroup_del = []
|
|
||||||
|
|
||||||
# Add principals
|
principal_add = gen_add_list(principal, res_principals)
|
||||||
for _principal in principal_add:
|
|
||||||
commands.append([name, "service_add_principal",
|
|
||||||
{
|
|
||||||
"krbprincipalname":
|
|
||||||
_principal,
|
|
||||||
}])
|
|
||||||
|
|
||||||
# Remove principals
|
# get keytab management lists for any 'action'.
|
||||||
for _principal in principal_del:
|
for perm in ["create", "retrieve"]:
|
||||||
commands.append([name, "service_remove_principal",
|
oper = "write" if perm == "create" else "read"
|
||||||
{
|
for key in ["user", "group", "host", "hostgroup"]:
|
||||||
"krbprincipalname":
|
add_list, del_list = (
|
||||||
_principal,
|
gen_add_del_lists(
|
||||||
}])
|
ansible_module.params_get(
|
||||||
|
"allow_%s_keytab_%s" % (perm, key)
|
||||||
for _certificate in certificate_add:
|
),
|
||||||
commands.append([name, "service_add_cert",
|
res_find.get(
|
||||||
{
|
'ipaallowedtoperform_%s_keys_%s'
|
||||||
"usercertificate":
|
% (oper, key)
|
||||||
_certificate,
|
)
|
||||||
}])
|
)
|
||||||
# Remove certificates
|
)
|
||||||
for _certificate in certificate_del:
|
keytab[perm]["allow"][key] = add_list
|
||||||
commands.append([name, "service_remove_cert",
|
# Only remove members if action is 'service'
|
||||||
{
|
if action == "service":
|
||||||
"usercertificate":
|
keytab[perm]["disallow"][key] = del_list
|
||||||
_certificate,
|
|
||||||
}])
|
|
||||||
|
|
||||||
# Add hosts.
|
|
||||||
if host is not None and len(host) > 0 and len(host_add) > 0:
|
|
||||||
commands.append([name, "service_add_host",
|
|
||||||
{"host": host_add}])
|
|
||||||
# Remove hosts
|
|
||||||
if host is not None and len(host) > 0 and len(host_del) > 0:
|
|
||||||
commands.append([name, "service_remove_host",
|
|
||||||
{"host": host_del}])
|
|
||||||
|
|
||||||
# Allow create keytab
|
|
||||||
if len(allow_create_keytab_user_add) > 0 or \
|
|
||||||
len(allow_create_keytab_group_add) > 0 or \
|
|
||||||
len(allow_create_keytab_host_add) > 0 or \
|
|
||||||
len(allow_create_keytab_hostgroup_add) > 0:
|
|
||||||
commands.append(
|
|
||||||
[name, "service_allow_create_keytab",
|
|
||||||
{'user': allow_create_keytab_user_add,
|
|
||||||
'group': allow_create_keytab_group_add,
|
|
||||||
'host': allow_create_keytab_host_add,
|
|
||||||
'hostgroup': allow_create_keytab_hostgroup_add
|
|
||||||
}])
|
|
||||||
|
|
||||||
# Disallow create keytab
|
|
||||||
if len(allow_create_keytab_user_del) > 0 or \
|
|
||||||
len(allow_create_keytab_group_del) > 0 or \
|
|
||||||
len(allow_create_keytab_host_del) > 0 or \
|
|
||||||
len(allow_create_keytab_hostgroup_del) > 0:
|
|
||||||
commands.append(
|
|
||||||
[name, "service_disallow_create_keytab",
|
|
||||||
{'user': allow_create_keytab_user_del,
|
|
||||||
'group': allow_create_keytab_group_del,
|
|
||||||
'host': allow_create_keytab_host_del,
|
|
||||||
'hostgroup': allow_create_keytab_hostgroup_del
|
|
||||||
}])
|
|
||||||
|
|
||||||
# Allow retrieve keytab
|
|
||||||
if len(allow_retrieve_keytab_user_add) > 0 or \
|
|
||||||
len(allow_retrieve_keytab_group_add) > 0 or \
|
|
||||||
len(allow_retrieve_keytab_host_add) > 0 or \
|
|
||||||
len(allow_retrieve_keytab_hostgroup_add) > 0:
|
|
||||||
commands.append(
|
|
||||||
[name, "service_allow_retrieve_keytab",
|
|
||||||
{'user': allow_retrieve_keytab_user_add,
|
|
||||||
'group': allow_retrieve_keytab_group_add,
|
|
||||||
'host': allow_retrieve_keytab_host_add,
|
|
||||||
'hostgroup': allow_retrieve_keytab_hostgroup_add
|
|
||||||
}])
|
|
||||||
|
|
||||||
# Disllow retrieve keytab
|
|
||||||
if len(allow_retrieve_keytab_user_del) > 0 or \
|
|
||||||
len(allow_retrieve_keytab_group_del) > 0 or \
|
|
||||||
len(allow_retrieve_keytab_host_del) > 0 or \
|
|
||||||
len(allow_retrieve_keytab_hostgroup_del) > 0:
|
|
||||||
commands.append(
|
|
||||||
[name, "service_disallow_retrieve_keytab",
|
|
||||||
{'user': allow_retrieve_keytab_user_del,
|
|
||||||
'group': allow_retrieve_keytab_group_del,
|
|
||||||
'host': allow_retrieve_keytab_host_del,
|
|
||||||
'hostgroup': allow_retrieve_keytab_hostgroup_del
|
|
||||||
}])
|
|
||||||
|
|
||||||
elif state == "absent":
|
elif state == "absent":
|
||||||
if action == "service":
|
if action == "service":
|
||||||
@@ -775,55 +602,30 @@ def main():
|
|||||||
if res_find is None:
|
if res_find is None:
|
||||||
ansible_module.fail_json(msg="No service '%s'" % name)
|
ansible_module.fail_json(msg="No service '%s'" % name)
|
||||||
|
|
||||||
# Remove principals
|
principal_del = gen_intersection_list(
|
||||||
if principal is not None:
|
principal, res_principals)
|
||||||
for _principal in principal:
|
|
||||||
commands.append([name, "service_remove_principal",
|
|
||||||
{
|
|
||||||
"krbprincipalname":
|
|
||||||
_principal,
|
|
||||||
}])
|
|
||||||
# Remove certificates
|
|
||||||
if certificate is not None:
|
|
||||||
existing = res_find.get('usercertificate', [])
|
|
||||||
for _certificate in certificate:
|
|
||||||
if _certificate in existing:
|
|
||||||
commands.append([name, "service_remove_cert",
|
|
||||||
{
|
|
||||||
"usercertificate":
|
|
||||||
_certificate,
|
|
||||||
}])
|
|
||||||
|
|
||||||
# Add hosts
|
certificate_del = gen_intersection_list(
|
||||||
if host is not None:
|
certificate, res_find.get("usercertificate"))
|
||||||
commands.append(
|
|
||||||
[name, "service_remove_host", {"host": host}])
|
|
||||||
|
|
||||||
# Allow create keytab
|
host_del = gen_intersection_list(
|
||||||
if allow_create_keytab_user is not None or \
|
host, res_find.get("managedby_host"))
|
||||||
allow_create_keytab_group is not None or \
|
|
||||||
allow_create_keytab_host is not None or \
|
|
||||||
allow_create_keytab_hostgroup is not None:
|
|
||||||
commands.append(
|
|
||||||
[name, "service_disallow_create_keytab",
|
|
||||||
{'user': allow_create_keytab_user,
|
|
||||||
'group': allow_create_keytab_group,
|
|
||||||
'host': allow_create_keytab_host,
|
|
||||||
'hostgroup': allow_create_keytab_hostgroup
|
|
||||||
}])
|
|
||||||
|
|
||||||
# Allow retriev keytab
|
for perm in ["create", "retrieve"]:
|
||||||
if allow_retrieve_keytab_user is not None or \
|
oper = "write" if perm == "create" else "read"
|
||||||
allow_retrieve_keytab_group is not None or \
|
for key in ["user", "group", "host", "hostgroup"]:
|
||||||
allow_retrieve_keytab_host is not None or \
|
res_param = (
|
||||||
allow_retrieve_keytab_hostgroup is not None:
|
'ipaallowedtoperform_%s_keys_%s'
|
||||||
commands.append(
|
% (oper, key)
|
||||||
[name, "service_disallow_retrieve_keytab",
|
)
|
||||||
{'user': allow_retrieve_keytab_user,
|
module_params = ansible_module.params_get(
|
||||||
'group': allow_retrieve_keytab_group,
|
"allow_%s_keytab_%s" % (perm, key)
|
||||||
'host': allow_retrieve_keytab_host,
|
)
|
||||||
'hostgroup': allow_retrieve_keytab_hostgroup
|
existing = res_find.get(res_param)
|
||||||
}])
|
del_list = (
|
||||||
|
gen_intersection_list(module_params, existing)
|
||||||
|
)
|
||||||
|
keytab[perm]["disallow"][key] = del_list
|
||||||
|
|
||||||
elif state == "disabled":
|
elif state == "disabled":
|
||||||
if action == "service":
|
if action == "service":
|
||||||
@@ -836,16 +638,53 @@ def main():
|
|||||||
ansible_module.fail_json(
|
ansible_module.fail_json(
|
||||||
msg="Invalid action '%s' for state '%s'" %
|
msg="Invalid action '%s' for state '%s'" %
|
||||||
(action, state))
|
(action, state))
|
||||||
|
# Members are not managed when disabling service.
|
||||||
|
# Continue with next 'name'.
|
||||||
|
continue
|
||||||
else:
|
else:
|
||||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||||
|
|
||||||
|
# Manage members
|
||||||
|
if principal_add:
|
||||||
|
commands.append([name, "service_add_principal",
|
||||||
|
{"krbprincipalname": principal_add}])
|
||||||
|
if principal_del:
|
||||||
|
commands.append([name, "service_remove_principal",
|
||||||
|
{"krbprincipalname": principal_del}])
|
||||||
|
|
||||||
|
if certificate_add:
|
||||||
|
commands.append([name, "service_add_cert",
|
||||||
|
{"usercertificate": certificate_add}])
|
||||||
|
if certificate_del:
|
||||||
|
commands.append([name, "service_remove_cert",
|
||||||
|
{"usercertificate": certificate_del}])
|
||||||
|
|
||||||
|
if host_add:
|
||||||
|
commands.append([name, "service_add_host",
|
||||||
|
{"host": host_add}])
|
||||||
|
if host_del:
|
||||||
|
commands.append([name, "service_remove_host",
|
||||||
|
{"host": host_del}])
|
||||||
|
|
||||||
|
# manage keytab permissions.
|
||||||
|
for perm in ["create", "retrieve"]:
|
||||||
|
for mode in ["allow", "disallow"]:
|
||||||
|
for key in ["user", "group", "host", "hostgroup"]:
|
||||||
|
if keytab[perm][mode][key]:
|
||||||
|
commands.append([
|
||||||
|
name,
|
||||||
|
"service_%s_%s_keytab" % (mode, perm),
|
||||||
|
keytab[perm][mode]
|
||||||
|
])
|
||||||
|
break
|
||||||
|
|
||||||
# Check mode exit
|
# Check mode exit
|
||||||
if ansible_module.check_mode:
|
if ansible_module.check_mode:
|
||||||
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
|
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
|
||||||
|
|
||||||
# Execute commands
|
# Execute commands
|
||||||
|
changed = ansible_module.execute_ipa_commands(
|
||||||
changed = ansible_module.execute_ipa_commands(commands, result_handler)
|
commands, fail_on_member_errors=True)
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
ansible_module.exit_json(changed=changed, **exit_args)
|
ansible_module.exit_json(changed=changed, **exit_args)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -456,11 +459,31 @@ def main():
|
|||||||
sudooption_add, sudooption_del = gen_add_del_lists(
|
sudooption_add, sudooption_del = gen_add_del_lists(
|
||||||
sudooption, res_find.get('ipasudoopt', []))
|
sudooption, res_find.get('ipasudoopt', []))
|
||||||
|
|
||||||
|
# runasuser attribute can be used with both IPA and
|
||||||
|
# non-IPA (external) users. IPA will handle the correct
|
||||||
|
# attribute to properly store data, so we need to compare
|
||||||
|
# the provided list against both users and external
|
||||||
|
# users list.
|
||||||
runasuser_add, runasuser_del = gen_add_del_lists(
|
runasuser_add, runasuser_del = gen_add_del_lists(
|
||||||
runasuser, res_find.get('ipasudorunas_user', []))
|
runasuser,
|
||||||
|
(
|
||||||
|
res_find.get('ipasudorunas_user', [])
|
||||||
|
+ res_find.get('ipasudorunasextuser', [])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# runasgroup attribute can be used with both IPA and
|
||||||
|
# non-IPA (external) groups. IPA will handle the correct
|
||||||
|
# attribute to properly store data, so we need to compare
|
||||||
|
# the provided list against both groups and external
|
||||||
|
# groups list.
|
||||||
runasgroup_add, runasgroup_del = gen_add_del_lists(
|
runasgroup_add, runasgroup_del = gen_add_del_lists(
|
||||||
runasgroup, res_find.get('ipasudorunas_group', []))
|
runasgroup,
|
||||||
|
(
|
||||||
|
res_find.get('ipasudorunas_group', [])
|
||||||
|
+ res_find.get('ipasudorunasextgroup', [])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Add hosts and hostgroups
|
# Add hosts and hostgroups
|
||||||
if len(host_add) > 0 or len(hostgroup_add) > 0:
|
if len(host_add) > 0 or len(hostgroup_add) > 0:
|
||||||
@@ -593,14 +616,38 @@ def main():
|
|||||||
"ipasudoopt" in res_find:
|
"ipasudoopt" in res_find:
|
||||||
sudooption = gen_add_list(
|
sudooption = gen_add_list(
|
||||||
sudooption, res_find["ipasudoopt"])
|
sudooption, res_find["ipasudoopt"])
|
||||||
if runasuser is not None and \
|
# runasuser attribute can be used with both IPA and
|
||||||
"ipasudorunas_user" in res_find:
|
# non-IPA (external) users, so we need to compare
|
||||||
|
# the provided list against both users and external
|
||||||
|
# users list.
|
||||||
|
if (
|
||||||
|
runasuser is not None
|
||||||
|
and (
|
||||||
|
"ipasudorunas_user" in res_find
|
||||||
|
or "ipasudorunasextuser" in res_find
|
||||||
|
)
|
||||||
|
):
|
||||||
runasuser = gen_add_list(
|
runasuser = gen_add_list(
|
||||||
runasuser, res_find["ipasudorunas_user"])
|
runasuser,
|
||||||
if runasgroup is not None and \
|
(list(res_find.get('ipasudorunas_user', []))
|
||||||
"ipasudorunasgroup_group" in res_find:
|
+ list(res_find.get('ipasudorunasextuser', [])))
|
||||||
|
)
|
||||||
|
# runasgroup attribute can be used with both IPA and
|
||||||
|
# non-IPA (external) groups, so we need to compare
|
||||||
|
# the provided list against both users and external
|
||||||
|
# groups list.
|
||||||
|
if (
|
||||||
|
runasgroup is not None
|
||||||
|
and (
|
||||||
|
"ipasudorunasgroup_group" in res_find
|
||||||
|
or "ipasudorunasextgroup" in res_find
|
||||||
|
)
|
||||||
|
):
|
||||||
runasgroup = gen_add_list(
|
runasgroup = gen_add_list(
|
||||||
runasgroup, res_find["ipasudorunasgroup_group"])
|
runasgroup,
|
||||||
|
(list(res_find.get("ipasudorunasgroup_group", []))
|
||||||
|
+ list(res_find.get("ipasudorunasextgroup", [])))
|
||||||
|
)
|
||||||
|
|
||||||
# Add hosts and hostgroups
|
# Add hosts and hostgroups
|
||||||
if host is not None or hostgroup is not None:
|
if host is not None or hostgroup is not None:
|
||||||
@@ -724,17 +771,43 @@ def main():
|
|||||||
sudooption, res_find["ipasudoopt"])
|
sudooption, res_find["ipasudoopt"])
|
||||||
else:
|
else:
|
||||||
sudooption = None
|
sudooption = None
|
||||||
|
# runasuser attribute can be used with both IPA and
|
||||||
|
# non-IPA (external) users, so we need to compare
|
||||||
|
# the provided list against both users and external
|
||||||
|
# users list.
|
||||||
if runasuser is not None:
|
if runasuser is not None:
|
||||||
if "ipasudorunas_user" in res_find:
|
if (
|
||||||
|
"ipasudorunas_user" in res_find
|
||||||
|
or "ipasudorunasextuser" in res_find
|
||||||
|
):
|
||||||
runasuser = gen_intersection_list(
|
runasuser = gen_intersection_list(
|
||||||
runasuser, res_find["ipasudorunas_user"])
|
runasuser,
|
||||||
|
(
|
||||||
|
list(res_find.get('ipasudorunas_user', []))
|
||||||
|
+ list(res_find.get(
|
||||||
|
'ipasudorunasextuser', []))
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
runasuser = None
|
runasuser = None
|
||||||
|
# runasgroup attribute can be used with both IPA and
|
||||||
|
# non-IPA (external) groups, so we need to compare
|
||||||
|
# the provided list against both groups and external
|
||||||
|
# groups list.
|
||||||
if runasgroup is not None:
|
if runasgroup is not None:
|
||||||
if "ipasudorunasgroup_group" in res_find:
|
if (
|
||||||
|
"ipasudorunasgroup_group" in res_find
|
||||||
|
or "ipasudorunasextgroup" in res_find
|
||||||
|
):
|
||||||
runasgroup = gen_intersection_list(
|
runasgroup = gen_intersection_list(
|
||||||
runasgroup,
|
runasgroup,
|
||||||
res_find["ipasudorunasgroup_group"])
|
(
|
||||||
|
list(res_find.get(
|
||||||
|
"ipasudorunasgroup_group", []))
|
||||||
|
+ list(res_find.get(
|
||||||
|
"ipasudorunasextgroup", []))
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
runasgroup = None
|
runasgroup = None
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
'status': ['preview'],
|
'status': ['preview'],
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -472,7 +475,7 @@ user:
|
|||||||
from ansible.module_utils.ansible_freeipa_module import \
|
from ansible.module_utils.ansible_freeipa_module import \
|
||||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, date_format, \
|
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, date_format, \
|
||||||
encode_certificate, load_cert_from_str, DN_x500_text, to_text
|
encode_certificate, load_cert_from_str, DN_x500_text, to_text
|
||||||
import six
|
from ansible.module_utils import six
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
unicode = str
|
unicode = str
|
||||||
|
|
||||||
@@ -696,8 +699,8 @@ def check_certmapdata(data):
|
|||||||
|
|
||||||
i = data.find("<I>", 4)
|
i = data.find("<I>", 4)
|
||||||
s = data.find("<S>", i) # pylint: disable=invalid-name
|
s = data.find("<S>", i) # pylint: disable=invalid-name
|
||||||
issuer = data[i+3:s]
|
issuer = data[i + 3:s]
|
||||||
subject = data[s+3:]
|
subject = data[s + 3:]
|
||||||
|
|
||||||
if i < 0 or s < 0 or "CN" not in issuer or "CN" not in subject:
|
if i < 0 or s < 0 or "CN" not in issuer or "CN" not in subject:
|
||||||
return False
|
return False
|
||||||
@@ -821,14 +824,17 @@ def main():
|
|||||||
# general
|
# general
|
||||||
name=dict(type="list", aliases=["login"], default=None,
|
name=dict(type="list", aliases=["login"], default=None,
|
||||||
required=False),
|
required=False),
|
||||||
users=dict(type="list", aliases=["login"], default=None,
|
users=dict(type="list",
|
||||||
|
aliases=["login"],
|
||||||
|
default=None,
|
||||||
options=dict(
|
options=dict(
|
||||||
# Here name is a simple string
|
# Here name is a simple string
|
||||||
name=dict(type="str", required=True),
|
name=dict(type="str", required=True),
|
||||||
# Add user specific parameters
|
# Add user specific parameters
|
||||||
**user_spec
|
**user_spec
|
||||||
),
|
),
|
||||||
elements='dict', required=False),
|
elements='dict',
|
||||||
|
required=False),
|
||||||
|
|
||||||
# deleted
|
# deleted
|
||||||
preserve=dict(required=False, type='bool', default=None),
|
preserve=dict(required=False, type='bool', default=None),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
"metadata_version": "1.0",
|
"metadata_version": "1.0",
|
||||||
"supported_by": "community",
|
"supported_by": "community",
|
||||||
@@ -631,7 +634,7 @@ def main():
|
|||||||
vault_password_file=dict(type="str", required=False, default=None,
|
vault_password_file=dict(type="str", required=False, default=None,
|
||||||
no_log=False,
|
no_log=False,
|
||||||
aliases=[
|
aliases=[
|
||||||
'password_file', "old_password_file"
|
'password_file', "old_password_file"
|
||||||
]),
|
]),
|
||||||
new_password=dict(type="str", required=False, default=None,
|
new_password=dict(type="str", required=False, default=None,
|
||||||
no_log=True),
|
no_log=True),
|
||||||
|
|||||||
@@ -3,5 +3,4 @@ pytest>=2.7
|
|||||||
pytest-sourceorder>=0.5
|
pytest-sourceorder>=0.5
|
||||||
pytest-split-tests>=1.0.3
|
pytest-split-tests>=1.0.3
|
||||||
pytest-testinfra>=5.0
|
pytest-testinfra>=5.0
|
||||||
jmespath>=0.9 # needed for the `json_query` filter
|
|
||||||
pyyaml>=3
|
pyyaml>=3
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
@@ -40,8 +43,9 @@ author:
|
|||||||
|
|
||||||
EXAMPLES = '''
|
EXAMPLES = '''
|
||||||
# Get IPA_BACKUP_DIR from ipaplatform
|
# Get IPA_BACKUP_DIR from ipaplatform
|
||||||
- name: ipabackup_get_backup_dir:
|
- name: Get IPA_BACKUP_DIR from ipaplatform
|
||||||
register result
|
ipabackup_get_backup_dir:
|
||||||
|
register: result
|
||||||
'''
|
'''
|
||||||
|
|
||||||
RETURN = '''
|
RETURN = '''
|
||||||
|
|||||||
10
roles/ipabackup/vars/Ubuntu-18.04.yml
Normal file
10
roles/ipabackup/vars/Ubuntu-18.04.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# vars/Ubuntu.yml
|
||||||
|
---
|
||||||
|
ipaserver_packages: [ "freeipa-server" ]
|
||||||
|
ipaserver_packages_dns: [ "freeipa-server-dns" ]
|
||||||
|
ipaserver_packages_adtrust: [ "freeipa-server-trust-ad" ]
|
||||||
|
ipaserver_packages_firewalld: [ "firewalld" ]
|
||||||
|
# Ubuntu Bionic Beaver must use python2 as Python interpreter due
|
||||||
|
# to the way python-ipalib package is defined.
|
||||||
|
# Package python2.7 must be installed before executing this role.
|
||||||
|
ansible_python_interpreter: '/usr/bin/python2.7'
|
||||||
@@ -17,6 +17,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import gssapi
|
import gssapi
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
||||||
'status': ['preview'],
|
'status': ['preview'],
|
||||||
'supported_by': 'community'}
|
'supported_by': 'community'}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
||||||
'status': ['preview'],
|
'status': ['preview'],
|
||||||
'supported_by': 'community'}
|
'supported_by': 'community'}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
DOCUMENTATION = """
|
DOCUMENTATION = """
|
||||||
---
|
---
|
||||||
module: ipaclient_get_facts
|
module: ipaclient_get_facts
|
||||||
@@ -12,9 +15,9 @@ author:
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import six
|
from ansible.module_utils import six
|
||||||
try:
|
try:
|
||||||
from six.moves.configparser import RawConfigParser
|
from ansible.module_utils.six.moves.configparser import RawConfigParser
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from ConfigParser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
|
|
||||||
@@ -81,7 +84,8 @@ def is_dogtag_configured(subsystem):
|
|||||||
# ca / kra is configured when the directory
|
# ca / kra is configured when the directory
|
||||||
# /var/lib/pki/pki-tomcat/[ca|kra] # exists
|
# /var/lib/pki/pki-tomcat/[ca|kra] # exists
|
||||||
available_subsystems = {'ca', 'kra'}
|
available_subsystems = {'ca', 'kra'}
|
||||||
assert subsystem in available_subsystems
|
if subsystem not in available_subsystems:
|
||||||
|
raise AssertionError("Subsystem '%s' not available" % subsystem)
|
||||||
|
|
||||||
return os.path.isdir(os.path.join(VAR_LIB_PKI_TOMCAT, subsystem))
|
return os.path.isdir(os.path.join(VAR_LIB_PKI_TOMCAT, subsystem))
|
||||||
|
|
||||||
@@ -120,7 +124,7 @@ def get_ipa_conf():
|
|||||||
basedn=basedn,
|
basedn=basedn,
|
||||||
realm=realm,
|
realm=realm,
|
||||||
domain=domain
|
domain=domain
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_ipa_version():
|
def get_ipa_version():
|
||||||
@@ -147,7 +151,7 @@ def get_ipa_version():
|
|||||||
vendor_version=version.VENDOR_VERSION,
|
vendor_version=version.VENDOR_VERSION,
|
||||||
version=version.VERSION,
|
version=version.VERSION,
|
||||||
version_info=version_info
|
version_info=version_info
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -193,7 +197,7 @@ def main():
|
|||||||
module.exit_json(
|
module.exit_json(
|
||||||
changed=False,
|
changed=False,
|
||||||
ansible_facts=dict(ipa=facts)
|
ansible_facts=dict(ipa=facts)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -20,6 +19,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
ANSIBLE_METADATA = {'metadata_version': '1.0',
|
||||||
'status': ['preview'],
|
'status': ['preview'],
|
||||||
'supported_by': 'community'}
|
'supported_by': 'community'}
|
||||||
@@ -121,9 +124,9 @@ host:
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import six
|
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils import six
|
||||||
|
|
||||||
from ipalib import api, errors
|
from ipalib import api, errors
|
||||||
from ipaplatform.paths import paths
|
from ipaplatform.paths import paths
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
@@ -179,7 +182,7 @@ def main():
|
|||||||
if password is None and admin_keytab is None:
|
if password is None and admin_keytab is None:
|
||||||
module.fail_json(msg="Password or admin_keytab is needed")
|
module.fail_json(msg="Password or admin_keytab is needed")
|
||||||
|
|
||||||
client_domain = hostname[hostname.find(".")+1:]
|
client_domain = hostname[hostname.find(".") + 1:]
|
||||||
nolog = tuple()
|
nolog = tuple()
|
||||||
env = {'PATH': SECURE_PATH}
|
env = {'PATH': SECURE_PATH}
|
||||||
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
@@ -156,7 +159,7 @@ def main():
|
|||||||
options.krb5_offline_passwords = not options.no_krb5_offline_passwords
|
options.krb5_offline_passwords = not options.no_krb5_offline_passwords
|
||||||
|
|
||||||
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
||||||
client_domain = hostname[hostname.find(".")+1:]
|
client_domain = hostname[hostname.find(".") + 1:]
|
||||||
|
|
||||||
if configure_sssd_conf(fstore, cli_realm, cli_domain, cli_server,
|
if configure_sssd_conf(fstore, cli_realm, cli_domain, cli_server,
|
||||||
options, client_domain, hostname):
|
options, client_domain, hostname):
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Authors:
|
# Authors:
|
||||||
@@ -22,6 +21,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from __future__ import (absolute_import, division, print_function)
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
ANSIBLE_METADATA = {
|
ANSIBLE_METADATA = {
|
||||||
'metadata_version': '1.0',
|
'metadata_version': '1.0',
|
||||||
'supported_by': 'community',
|
'supported_by': 'community',
|
||||||
@@ -197,7 +200,7 @@ import socket
|
|||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from six.moves.configparser import RawConfigParser
|
from ansible.module_utils.six.moves.configparser import RawConfigParser
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from ConfigParser import RawConfigParser
|
from ConfigParser import RawConfigParser
|
||||||
|
|
||||||
@@ -319,7 +322,7 @@ def main():
|
|||||||
if options.domain_name is None and options.servers is not None:
|
if options.domain_name is None and options.servers is not None:
|
||||||
if len(options.servers) > 0:
|
if len(options.servers) > 0:
|
||||||
options.domain_name = options.servers[0][
|
options.domain_name = options.servers[0][
|
||||||
options.servers[0].find(".")+1:]
|
options.servers[0].find(".") + 1:]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self = options
|
self = options
|
||||||
@@ -701,7 +704,7 @@ def main():
|
|||||||
cli_domain_source = ds.domain_source
|
cli_domain_source = ds.domain_source
|
||||||
logger.debug("will use discovered domain: %s", cli_domain)
|
logger.debug("will use discovered domain: %s", cli_domain)
|
||||||
|
|
||||||
client_domain = hostname[hostname.find(".")+1:]
|
client_domain = hostname[hostname.find(".") + 1:]
|
||||||
|
|
||||||
if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
|
if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
|
||||||
or not ds.server:
|
or not ds.server:
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user