mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-31 07:43:06 +00:00
Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1930d8c8be | ||
|
|
1837ee662c | ||
|
|
26e171df79 | ||
|
|
01440e3c04 | ||
|
|
2426e04c22 | ||
|
|
92e44f6a6c | ||
|
|
16c8ee87e9 | ||
|
|
3109e9d1bc | ||
|
|
b457de545d | ||
|
|
f1a6f44477 | ||
|
|
1dbe19cefb | ||
|
|
7982fad342 | ||
|
|
212719496c | ||
|
|
3de6f9146e | ||
|
|
48f2ef88a4 | ||
|
|
6845acd596 | ||
|
|
ba7bf0f6cd | ||
|
|
fe2d17e4df | ||
|
|
319a0d3d86 | ||
|
|
c71a2b33dd | ||
|
|
02223dfb67 | ||
|
|
5731a1539b | ||
|
|
ee7354230b | ||
|
|
4bb40f3397 | ||
|
|
55b8729c52 | ||
|
|
539ace413d | ||
|
|
0c20b34d28 | ||
|
|
f9ff41320f | ||
|
|
69c6b4d644 | ||
|
|
b63716b724 | ||
|
|
3cf138674b | ||
|
|
12e0d110f6 | ||
|
|
34654d1090 | ||
|
|
72d3ab8e04 | ||
|
|
fb75aed663 | ||
|
|
6f5bb9eebf | ||
|
|
e5b2c122ce | ||
|
|
c0692e1746 | ||
|
|
2d079c8eec | ||
|
|
b70a1ecf61 | ||
|
|
7cb5e481e5 | ||
|
|
60593b7dd3 | ||
|
|
e84ed3b6ba | ||
|
|
6e1f9f1a72 | ||
|
|
46a307aaeb | ||
|
|
d8f8211a1c | ||
|
|
34daa992f5 | ||
|
|
07c1a5ee61 | ||
|
|
63d0272385 | ||
|
|
d0a8005a7f | ||
|
|
24efad73fa | ||
|
|
fd1352ad7e | ||
|
|
de38e8f0bc | ||
|
|
847ae2a374 | ||
|
|
bcee9aba92 | ||
|
|
c34c66fa79 | ||
|
|
0a3cd06c6e | ||
|
|
b5b22c3f7e | ||
|
|
7ee385ee02 | ||
|
|
7d9e4da9df | ||
|
|
0a20b5902d | ||
|
|
be9a2db404 | ||
|
|
ba4a360520 | ||
|
|
3534fcdce7 | ||
|
|
f0f21fc8aa | ||
|
|
5ed96eda05 |
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
@@ -16,10 +16,10 @@ jobs:
|
||||
python-version: "3.x"
|
||||
- name: Run ansible-lint
|
||||
run: |
|
||||
pip install "ansible-core >=2.15,<2.16" ansible-lint
|
||||
pip install "ansible-core>=2.16,<2.17" 'ansible-lint>=6.21'
|
||||
utils/build-galaxy-release.sh -ki
|
||||
cd .galaxy-build
|
||||
ansible-lint
|
||||
ansible-lint --profile production --exclude tests/integration/ --exclude tests/unit/ --parseable --nocolor
|
||||
|
||||
yamllint:
|
||||
name: Verify yamllint
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
python-version: "3.x"
|
||||
- name: Run pylint
|
||||
run: |
|
||||
pip install pylint==2.14.4 wrapt==1.14.0
|
||||
pip install 'pylint>=3.0'
|
||||
pylint plugins roles --disable=import-error
|
||||
|
||||
shellcheck:
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
---
|
||||
repos:
|
||||
- repo: https://github.com/ansible/ansible-lint.git
|
||||
rev: v6.6.1
|
||||
rev: v6.22.0
|
||||
hooks:
|
||||
- id: ansible-lint
|
||||
always_run: false
|
||||
pass_filenames: true
|
||||
files: \.(yaml|yml)$
|
||||
exclude: /env[^/]*.(yaml|yml)$
|
||||
entry: |
|
||||
env ANSIBLE_LIBRARY=./plugins/modules ANSIBLE_MODULE_UTILS=./plugins/module_utils ANSIBLE_DOC_FRAGMENT_PLUGINS=./plugins/doc_fragments ansible-lint
|
||||
entry: |-
|
||||
env
|
||||
ANSIBLE_LIBRARY=./plugins/modules
|
||||
ANSIBLE_MODULE_UTILS=./plugins/module_utils
|
||||
ANSIBLE_DOC_FRAGMENT_PLUGINS=./plugins/doc_fragments
|
||||
ansible-lint
|
||||
--offline
|
||||
--profile production
|
||||
--exclude tests/integration/
|
||||
--exclude tests/unit/
|
||||
--parseable
|
||||
--nocolor
|
||||
- repo: https://github.com/adrienverge/yamllint.git
|
||||
rev: v1.28.0
|
||||
rev: v1.32.0
|
||||
hooks:
|
||||
- id: yamllint
|
||||
files: \.(yaml|yml)$
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 5.0.3
|
||||
rev: 6.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
- repo: https://github.com/pycqa/pydocstyle
|
||||
@@ -24,7 +34,7 @@ repos:
|
||||
hooks:
|
||||
- id: pydocstyle
|
||||
- repo: https://github.com/pycqa/pylint
|
||||
rev: v2.14.4
|
||||
rev: v3.0.2
|
||||
hooks:
|
||||
- id: pylint
|
||||
args:
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -21,7 +21,7 @@ FreeIPA versions 4.4.0 and up are supported by the ipaautomountkey module.
|
||||
Requirements
|
||||
------------
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -21,7 +21,7 @@ FreeIPA versions 4.4.0 and up are supported by the ipaautomountlocation module.
|
||||
Requirements
|
||||
------------
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -21,7 +21,7 @@ FreeIPA versions 4.4.0 and up are supported by the ipaautomountmap module.
|
||||
Requirements
|
||||
------------
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
* Some tool to generate a certificate signing request (CSR) might be needed, like `openssl`.
|
||||
|
||||
**Node**
|
||||
@@ -77,6 +77,23 @@ Example playbook to revoke an existing certificate:
|
||||
ipacert:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
serial_number: 123456789
|
||||
reason: 5
|
||||
state: revoked
|
||||
```
|
||||
|
||||
When revoking a certificate a mnemonic can also be used to set the revocation reason:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Revoke certificate
|
||||
hosts: ipaserver
|
||||
|
||||
tasks:
|
||||
- name Revoke a certificate
|
||||
ipacert:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
serial_number: 123456789
|
||||
reason: cessationOfOperation
|
||||
state: revoked
|
||||
```
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -23,7 +23,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -21,7 +21,7 @@ FreeIPA versions 4.4.0 and up are supported by the ipadnsforwardzone module.
|
||||
Requirements
|
||||
------------
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -23,7 +23,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
|
||||
**Node**
|
||||
|
||||
@@ -29,7 +29,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -26,7 +26,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
233
README-idoverridegroup.md
Normal file
233
README-idoverridegroup.md
Normal file
@@ -0,0 +1,233 @@
|
||||
Idoverridegroup module
|
||||
============
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The idoverridegroup module allows to ensure presence and absence of idoverridegroups and idoverridegroup members.
|
||||
|
||||
|
||||
Use Cases
|
||||
---------
|
||||
|
||||
With idoverridegroup it is possible to manage group attributes within ID views. These attributes are for example the group name or gid.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Idoverridegroup management
|
||||
|
||||
|
||||
Supported FreeIPA Versions
|
||||
--------------------------
|
||||
|
||||
FreeIPA versions 4.4.0 and up are supported by the ipaidoverridegroup module.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.13
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Example inventory file
|
||||
|
||||
```ini
|
||||
[ipaserver]
|
||||
ipaserver.test.local
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test group test_group is present in idview test_idview
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test group test_group is present in idview test_idview.
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test group test_group is present in idview test_idview with description
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test group test_group is present in idview test_idview with description
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
description: "test_group description"
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test group test_group is present in idview test_idview without description
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test group test_group is present in idview test_idview without description
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
description: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test group test_group is present in idview test_idview with internal name test_123_group
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test group test_group is present in idview test_idview with internal name test_123_group
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
name: test_123_group
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test group test_group is present in idview test_idview without internal name
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
- name: Ensure test group test_group is present in idview test_idview without internal name
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
name: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test group test_group is present in idview test_idview with gid 20001
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test group test_group is present in idview test_idview with gid 20001
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
gid: 20001
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test group test_group is present in idview test_idview without gid
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test group test_group is present in idview test_idview without gid
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
gid: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test group test_group is present in idview test_idview with enabling falling back to AD DC LDAP when resolving AD trusted objects. (For two-way trusts only.)
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test group test_group is present in idview test_idview with fallback_to_ldap enabled
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
fallback_to_ldap: true
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test group test_group is absent in idview test_idview
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test group test_group is absent in idview test_idview
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
continue: true
|
||||
state: absent
|
||||
```
|
||||
|
||||
|
||||
Variables
|
||||
---------
|
||||
|
||||
Variable | Description | Required
|
||||
-------- | ----------- | --------
|
||||
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
|
||||
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
|
||||
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
|
||||
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | no
|
||||
`idview` \| `idviewcn` | The doverridegroup idview string. | yes
|
||||
`anchor` \| `ipaanchoruuid` | The list of anchors to override. | yes
|
||||
`description` \| `desc` | Description | no
|
||||
`name` \| `group_name` \| `cn` | The group. | no
|
||||
`gid` \| `gidnumber` | Group ID Number (int or "") | no
|
||||
`fallback_to_ldap` | Allow falling back to AD DC LDAP when resolving AD trusted objects. For two-way trusts only. | no
|
||||
`delete_continue` \| `continue` | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
|
||||
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
Thomas Woerner
|
||||
503
README-idoverrideuser.md
Normal file
503
README-idoverrideuser.md
Normal file
@@ -0,0 +1,503 @@
|
||||
Idoverrideuser module
|
||||
============
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The idoverrideuser module allows to ensure presence and absence of idoverrideusers and idoverrideuser members.
|
||||
|
||||
|
||||
Use Cases
|
||||
---------
|
||||
|
||||
With idoverrideuser it is possible to manage user attributes within ID views. These attributes are for example the login name, home directory, certificate for authentication or SSH keys.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Idoverrideuser management
|
||||
|
||||
|
||||
Supported FreeIPA Versions
|
||||
--------------------------
|
||||
|
||||
FreeIPA versions 4.4.0 and up are supported by the ipaidoverrideuser module.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.13
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Example inventory file
|
||||
|
||||
```ini
|
||||
[ipaserver]
|
||||
ipaserver.test.local
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview.
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with description
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with description
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
description: "test_user description"
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without description
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without description
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
description: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with internal name test_123_user
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with internal name test_123_user
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
name: test_123_user
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without internal name
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without internal name
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
name: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with uid 20001
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with uid 20001
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
uid: 20001
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without uid
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without uid
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
uid: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with gecos "Gecos Test"
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with gecos "Gecos Test"
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
gecos: Gecos Test
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without gecos
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without gecos
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
gecos: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with gidnumber
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with gidnumber
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
gidnumber: 20001
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without gidnumber
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without gidnumber
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
gidnumber: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with homedir /Users
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with homedir /Users
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
homedir: /Users
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without homedir
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without homedir
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
homedir: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with shell
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with shell
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
shell: /bin/someshell
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without shell
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without shell
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
shell: ""
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with sshpubkey
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with sshpubkey
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
sshpubkey:
|
||||
- ssh-rsa AAAAB3NzaC1yc2EAAADAQABAAABgQCqmVDpEX5gnSjKuv97Ay ...
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without sshpubkey
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without sshpubkey
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
sshpubkey: []
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with 1 certificate
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with 1 certificate
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate:
|
||||
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with 3 certificate members
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with 3 certificate members
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate:
|
||||
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
|
||||
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
|
||||
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
|
||||
action: member
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without 2 certificate members
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without 2 certificate members
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate:
|
||||
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
|
||||
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
|
||||
action: member
|
||||
state: absent
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview without certificates
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview without certificates
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate: []
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is present in idview test_idview with enabling falling back to AD DC LDAP when resolving AD trusted objects. (For two-way trusts only.)
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview with fallback_to_ldap enabled
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
fallback_to_ldap: true
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure test user test_user is absent in idview test_idview
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is absent in idview test_idview
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
continue: true
|
||||
state: absent
|
||||
```
|
||||
|
||||
|
||||
Variables
|
||||
---------
|
||||
|
||||
Variable | Description | Required
|
||||
-------- | ----------- | --------
|
||||
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
|
||||
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
|
||||
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
|
||||
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | no
|
||||
`idview` \| `idviewcn` | The doverrideuser idview string. | yes
|
||||
`anchor` \| `ipaanchoruuid` | The list of anchors to override. | yes
|
||||
`description` \| `desc` | Description | no
|
||||
`name` \| `login` | The user (internally uid) | no
|
||||
`uid` \| `uidnumber` | User ID Number (int or "") | no
|
||||
`gecos` | GECOS | no
|
||||
`gidnumber` | Group ID Number (int or ""). | no
|
||||
`homedir` \| `homedirectory` | Home directory. | no
|
||||
`shell` \| `loginshell` | Login shell. | no
|
||||
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys. | no
|
||||
`certificate` \| `usercertificate` | List of Base-64 encoded user certificates. This variable can also be used with `action: member`. | no
|
||||
`fallback_to_ldap` | Allow falling back to AD DC LDAP when resolving AD trusted objects. For two-way trusts only. | no
|
||||
`delete_continue` \| `continue` | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
|
||||
`nomembers` \| `no_members` | Suppress processing of membership attributes. Valid only if `state` is `absent`. | no
|
||||
`action` | Work on idoverrideuser or member level. It can be on of `member` or `idoverrideuser` and defaults to `idoverrideuser`. | no
|
||||
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
Thomas Woerner
|
||||
192
README-idp.md
Normal file
192
README-idp.md
Normal file
@@ -0,0 +1,192 @@
|
||||
Idp module
|
||||
============
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The idp module allows to ensure presence and absence of idps.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Idp management
|
||||
|
||||
|
||||
Supported FreeIPA Versions
|
||||
--------------------------
|
||||
|
||||
FreeIPA versions 4.4.0 and up are supported by the ipaidp module.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.13
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Example inventory file
|
||||
|
||||
```ini
|
||||
[ipaserver]
|
||||
ipaserver.test.local
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure keycloak idp my-keycloak-idp is present:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idp.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure keycloak idp my-keycloak-idp is present
|
||||
ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-keycloak-idp
|
||||
provider: keycloak
|
||||
organization: main
|
||||
base_url: keycloak.idm.example.com:8443/auth
|
||||
client_id: my-client-id
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure keycloak idp my-keycloak-idp is absent:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idp.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure keycloak idp my-keycloak-idp is absent
|
||||
ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-keycloak-idp
|
||||
delete_continue: true
|
||||
state: absent
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure github idp my-github-idp is present:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idp.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure github idp my-github-idp is present
|
||||
ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-github-idp
|
||||
provider: github
|
||||
client_id: my-github-client-id
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure google idp my-google-idp is present using provider defaults without specifying provider:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idp.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure google idp my-google-idp is present using provider defaults without specifying provider
|
||||
ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-google-idp
|
||||
auth_uri: https://accounts.google.com/o/oauth2/auth
|
||||
dev_auth_uri: https://oauth2.googleapis.com/device/code
|
||||
token_uri: https://oauth2.googleapis.com/token
|
||||
keys_uri: https://www.googleapis.com/oauth2/v3/certs
|
||||
userinfo_uri: https://openidconnect.googleapis.com/v1/userinfo
|
||||
client_id: my-google-client-id
|
||||
scope: "openid email"
|
||||
idp_user_id: email
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure google idp my-google-idp is present using provider:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idp.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure google idp my-google-idp is present using provider
|
||||
ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-google-idp
|
||||
provider: google
|
||||
client_id: my-google-client-id
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure idps my-keycloak-idp, my-github-idp and my-google-idp are absent:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idp.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure idps my-keycloak-idp, my-github-idp and my-google-idp are absent
|
||||
ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name:
|
||||
- my-keycloak-idp
|
||||
- my-github-idp
|
||||
- my-google-idp
|
||||
delete_continue: true
|
||||
state: absent
|
||||
```
|
||||
|
||||
|
||||
Variables
|
||||
---------
|
||||
|
||||
Variable | Description | Required
|
||||
-------- | ----------- | --------
|
||||
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
|
||||
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
|
||||
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
|
||||
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | false
|
||||
`name` \| `cn` | The list of idp name strings. | yes
|
||||
auth_uri \| ipaidpauthendpoint | OAuth 2.0 authorization endpoint string. | no
|
||||
dev_auth_uri \| ipaidpdevauthendpoint | Device authorization endpoint string. | no
|
||||
token_uri \| ipaidptokenendpoint | Token endpoint string. | no
|
||||
userinfo_uri \| ipaidpuserinfoendpoint | User information endpoint string. | no
|
||||
keys_uri \| ipaidpkeysendpoint | JWKS endpoint string. | no
|
||||
issuer_url \| ipaidpissuerurl | The Identity Provider OIDC URL string. | no
|
||||
client_id \| ipaidpclientid | OAuth 2.0 client identifier string. | no
|
||||
secret \| ipaidpclientsecret | OAuth 2.0 client secret string. | no
|
||||
scope \| ipaidpscope | OAuth 2.0 scope string. Multiple scopes separated by space. | no
|
||||
idp_user_id \| ipaidpsub | Attribute string for user identity in OAuth 2.0 userinfo. | no
|
||||
provider \| ipaidpprovider | Pre-defined template string. This provides the provider defaults, which can be overridden with the other IdP options. Choices: ["google","github","microsoft","okta","keycloak"] | no
|
||||
organization \| ipaidporg | Organization ID string or Realm name for IdP provider templates. | no
|
||||
base_url \| ipaidpbaseurl | Base URL string for IdP provider templates. | no
|
||||
rename \| new_name | New name for the Identity Provider server object. Only with `state: renamed`. | no
|
||||
delete_continue \| continue | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
|
||||
`state` | The state to ensure. It can be one of `present`, `absent`, `renamed`, default: `present`. | no
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
Thomas Woerner
|
||||
@@ -37,7 +37,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
153
README-idview.md
Normal file
153
README-idview.md
Normal file
@@ -0,0 +1,153 @@
|
||||
Idview module
|
||||
============
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The idview module allows to ensure presence and absence of idviews and idview host members.
|
||||
|
||||
Use Cases
|
||||
---------
|
||||
|
||||
With ID views it is possible to override user or group attributes for users stored in the LDAP server. For example the login name, home directory, certificate for authentication or SSH keys. An ID view is client-side and specifies new values for user or group attributes and also the client host or hosts on which the values apply.
|
||||
|
||||
The ID view and the applied hosts are managed with idview, the user attributes are managed with idoverrideuser and the group attributes with idoverridegroup.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Idview management
|
||||
|
||||
|
||||
Supported FreeIPA Versions
|
||||
--------------------------
|
||||
|
||||
FreeIPA versions 4.4.0 and up are supported by the ipaidview module.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.13
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Example inventory file
|
||||
|
||||
```ini
|
||||
[ipaserver]
|
||||
ipaserver.test.local
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure idview "test_idview" is present:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idview.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure idview "test_idview" member host "testhost.example.com" is present:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idview host member.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
host: testhost.example.com
|
||||
action: member
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure idview "test_idview" member host "testhost.example.com" is absent:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idview host member.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
host: testhost.example.com
|
||||
action: member
|
||||
state: absent
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure idview "test_idview" is present with domain_resolution_order for "ad.example.com:ipa.example.com":
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idview host member.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
domain_resolution_order: "ad.example.com:ipa.example.com"
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure idview "test_idview" is absent:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idview.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
state: absent
|
||||
```
|
||||
|
||||
|
||||
Variables
|
||||
---------
|
||||
|
||||
Variable | Description | Required
|
||||
-------- | ----------- | --------
|
||||
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
|
||||
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
|
||||
`ipaapi_context` | The context in which the module will execute. Executing in a server context is preferred. If not provided context will be determined by the execution environment. Valid values are `server` and `client`. | no
|
||||
`ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to true. (bool) | no
|
||||
`name` \| `cn` | The list of idview name strings. | yes
|
||||
`description` \| `desc` | The description string of the idview. | no
|
||||
`domain_resolution_order` \| `ipadomainresolutionorder` | Colon-separated list of domains used for short name qualification. | no
|
||||
`host` \| `hosts` | List of hosts to apply the ID View to. A host can only be applied to a single idview at any time. Applying a host that is already applied to a different idview will change the idview the host is applied to to the new one. | no
|
||||
`rename` \| `new_name` | Rename the ID view object to the new name string. Only usable with `state: renamed`. | no
|
||||
`delete_continue` \| `continue` | Continuous mode. Don't stop on errors. Valid only if `state` is `absent`. | no
|
||||
`action` | Work on idview or member level. It can be on of `member` or `idview` and defaults to `idview`. | no
|
||||
`state` | The state to ensure. It can be one of `present`, `absent` and `renamed`, default: `present`. | no
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
Thomas Woerner
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -23,7 +23,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FReeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -21,7 +21,7 @@ Requirements
|
||||
|
||||
**Controller**
|
||||
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
20
README.md
20
README.md
@@ -30,7 +30,11 @@ Features
|
||||
* Modules for hbacsvcgroup management
|
||||
* Modules for host management
|
||||
* Modules for hostgroup management
|
||||
* Modules for idoverridegroup management
|
||||
* Modules for idoverrideuser management
|
||||
* Modules for idp management
|
||||
* Modules for idrange management
|
||||
* Modules for idview management
|
||||
* Modules for location management
|
||||
* Modules for netgroup management
|
||||
* Modules for permission management
|
||||
@@ -69,7 +73,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+ (ansible-freeipa is an Ansible Collection)
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
@@ -129,18 +133,8 @@ This command will get the whole collection from galaxy:
|
||||
ansible-galaxy collection install freeipa.ansible_freeipa
|
||||
```
|
||||
|
||||
Installing collections using the ansible-galaxy command is only supported with ansible 2.9+.
|
||||
|
||||
The mazer tool can be used for to install the collection for ansible 2.8:
|
||||
|
||||
```bash
|
||||
mazer install freeipa.ansible_freeipa
|
||||
```
|
||||
|
||||
Ansible galaxy does not support the use of dash ('-') in a name and is automatically replacing this with an underscore ('\_'). Therefore the name is `ansible_freeipa`. The ansible_freeipa collection will be placed in the directory `~/.ansible/collections/ansible_collections/freeipa/ansible_freeipa` where it will be automatically be found for this user.
|
||||
|
||||
The needed adaptions of collection prefixes for `modules` and `module_utils` will be done with ansible-freeipa release `0.1.6` for galaxy.
|
||||
|
||||
|
||||
Ansible inventory file
|
||||
----------------------
|
||||
@@ -450,7 +444,11 @@ Modules in plugin/modules
|
||||
* [ipahbacsvcgroup](README-hbacsvcgroup.md)
|
||||
* [ipahost](README-host.md)
|
||||
* [ipahostgroup](README-hostgroup.md)
|
||||
* [idoverridegroup](README-idoverridegroup.md)
|
||||
* [idoverrideuser](README-idoverrideuser.md)
|
||||
* [idp](README-idp.md)
|
||||
* [idrange](README-idrange.md)
|
||||
* [idview](README-idview.md)
|
||||
* [ipalocation](README-location.md)
|
||||
* [ipanetgroup](README-netgroup.md)
|
||||
* [ipapermission](README-permission.md)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
requires_ansible: ">=2.9"
|
||||
requires_ansible: ">=2.13"
|
||||
|
||||
13
playbooks/idoverridegroup/idoverridegroup-absent.yml
Normal file
13
playbooks/idoverridegroup/idoverridegroup-absent.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure idoverridegroup test_group is absent in idview test_idview.
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
continue: true
|
||||
state: absent
|
||||
11
playbooks/idoverridegroup/idoverridegroup-present.yml
Normal file
11
playbooks/idoverridegroup/idoverridegroup-present.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Playbook to manage idoverridegroup
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure idoverridegroup test_group is present in idview test_idview.
|
||||
ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
13
playbooks/idoverrideuser/idoverrideuser-absent.yml
Normal file
13
playbooks/idoverrideuser/idoverrideuser-absent.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is absent in idview test_idview
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
continue: true
|
||||
state: absent
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user certificate member is absent in idview test_idview
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate:
|
||||
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
|
||||
action: member
|
||||
state: absent
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user certificate member is present in idview test_idview
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate:
|
||||
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
|
||||
action: member
|
||||
11
playbooks/idoverrideuser/idoverrideuser-present.yml
Normal file
11
playbooks/idoverrideuser/idoverrideuser-present.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Playbook to manage idoverrideuser
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure test user test_user is present in idview test_idview.
|
||||
ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
11
playbooks/idp/idp-absent.yml
Normal file
11
playbooks/idp/idp-absent.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Idp absent example
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure github idp my-github-idp is absent
|
||||
ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-github-idp
|
||||
state: absent
|
||||
12
playbooks/idp/idp-present.yml
Normal file
12
playbooks/idp/idp-present.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: Idp present example
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure github idp my-github-idp is present
|
||||
ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-github-idp
|
||||
provider: github
|
||||
client_id: my-github-client-id
|
||||
11
playbooks/idview/idview-absent.yml
Normal file
11
playbooks/idview/idview-absent.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Idview absent example
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure idview test_idview is absent
|
||||
ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
state: absent
|
||||
12
playbooks/idview/idview-host-applied.yml
Normal file
12
playbooks/idview/idview-host-applied.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: Idview host member applied example
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure host testhost.example.com is applied to idview test_idview
|
||||
ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
host: testhost.example.com
|
||||
action: member
|
||||
13
playbooks/idview/idview-host-unapplied.yml
Normal file
13
playbooks/idview/idview-host-unapplied.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
- name: Idview host member unapplied example
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure host testhost.example.com is not applied to idview test_idview
|
||||
ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
host: testhost.example.com
|
||||
action: member
|
||||
state: absent
|
||||
10
playbooks/idview/idview-present.yml
Normal file
10
playbooks/idview/idview-present.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Idview present example
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure idview test_idview is present
|
||||
ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
@@ -30,7 +30,7 @@ __all__ = ["gssapi", "netaddr", "api", "ipalib_errors", "Env",
|
||||
"kinit_password", "kinit_keytab", "run", "DN", "VERSION",
|
||||
"paths", "tasks", "get_credentials_if_valid", "Encoding",
|
||||
"DNSName", "getargspec", "certificate_loader",
|
||||
"write_certificate_list", "boolean"]
|
||||
"write_certificate_list", "boolean", "template_str"]
|
||||
|
||||
import os
|
||||
# ansible-freeipa requires locale to be C, IPA requires utf-8.
|
||||
@@ -90,6 +90,7 @@ try:
|
||||
except ImportError:
|
||||
from ipapython.ipautil import kinit_password, kinit_keytab
|
||||
from ipapython.ipautil import run
|
||||
from ipapython.ipautil import template_str
|
||||
from ipapython.dn import DN
|
||||
from ipapython.version import VERSION
|
||||
from ipaplatform.paths import paths
|
||||
@@ -226,7 +227,7 @@ def temp_kdestroy(ccache_dir, ccache_name):
|
||||
"""Destroy temporary ticket and remove temporary ccache."""
|
||||
if ccache_name is not None:
|
||||
run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False)
|
||||
del os.environ['KRB5CCNAME']
|
||||
os.environ.pop('KRB5CCNAME', None)
|
||||
if ccache_dir is not None:
|
||||
shutil.rmtree(ccache_dir, ignore_errors=True)
|
||||
|
||||
|
||||
@@ -121,8 +121,7 @@ class AutomountKey(IPAAnsibleModule):
|
||||
resp = self.ipa_command("automountkey_show", location, args)
|
||||
except ipalib_errors.NotFound:
|
||||
return None
|
||||
else:
|
||||
return resp.get("result")
|
||||
return resp.get("result")
|
||||
|
||||
def check_ipa_params(self):
|
||||
invalid = []
|
||||
|
||||
@@ -92,8 +92,7 @@ class AutomountLocation(IPAAnsibleModule):
|
||||
)
|
||||
except ipalib_errors.NotFound:
|
||||
return None
|
||||
else:
|
||||
return response.get("result", None)
|
||||
return response.get("result", None)
|
||||
|
||||
def check_ipa_params(self):
|
||||
if len(self.params_get("name")) == 0:
|
||||
|
||||
@@ -126,8 +126,7 @@ class AutomountMap(IPAAnsibleModule):
|
||||
)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
return None
|
||||
else:
|
||||
return response["result"]
|
||||
return response["result"]
|
||||
|
||||
def get_indirect_map_keys(self, location, name):
|
||||
"""Check if 'name' is an indirect map for 'parentmap'."""
|
||||
|
||||
@@ -358,8 +358,7 @@ def get_netbios_name(module):
|
||||
_result = module.ipa_command_no_name("trustconfig_show", {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
return None
|
||||
else:
|
||||
return _result["result"]["ipantflatname"][0]
|
||||
return _result["result"]["ipantflatname"][0]
|
||||
|
||||
|
||||
def is_enable_sid(module):
|
||||
@@ -477,7 +476,7 @@ def main():
|
||||
params = {}
|
||||
for x in field_map:
|
||||
val = ansible_module.params_get(
|
||||
x, allow_empty_string=(x in allow_empty_string))
|
||||
x, allow_empty_string=x in allow_empty_string)
|
||||
|
||||
if val is not None:
|
||||
params[field_map.get(x, x)] = val
|
||||
@@ -620,7 +619,7 @@ def main():
|
||||
# boolean values, so we need to convert it to str
|
||||
# for comparison.
|
||||
# See: https://github.com/freeipa/freeipa/pull/6294
|
||||
exit_args[k] = (str(value[0]).upper() == "TRUE")
|
||||
exit_args[k] = str(value[0]).upper() == "TRUE"
|
||||
else:
|
||||
if arg_type not in type_map:
|
||||
raise ValueError(
|
||||
|
||||
@@ -134,8 +134,7 @@ def find_delegation(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if delegation name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(permission, attribute, membergroup, group):
|
||||
|
||||
@@ -258,7 +258,7 @@ def main():
|
||||
invalid = [
|
||||
"forwarders", "forwardpolicy", "skip_overlap_check", "permission"
|
||||
]
|
||||
wants_enable = (state == "enabled")
|
||||
wants_enable = state == "enabled"
|
||||
|
||||
if operation == "del":
|
||||
invalid = [
|
||||
|
||||
@@ -1453,7 +1453,7 @@ def define_commands_for_present_state(module, zone_name, entry, res_find):
|
||||
else:
|
||||
# Create reverse records for existing records
|
||||
for ipv in ['a', 'aaaa']:
|
||||
record = ('%srecord' % ipv)
|
||||
record = '%srecord' % ipv
|
||||
if record in args and ('%s_extra_create_reverse' % ipv) in args:
|
||||
cmds = create_reverse_ip_record(
|
||||
module, zone_name, name, args[record])
|
||||
|
||||
@@ -186,7 +186,17 @@ def find_hbacrule(module, name):
|
||||
module.fail_json(
|
||||
msg="There is more than one hbacrule '%s'" % (name))
|
||||
elif len(_result["result"]) == 1:
|
||||
return _result["result"][0]
|
||||
res = _result["result"][0]
|
||||
# hbacsvcgroup names are converted to lower case while creation with
|
||||
# hbacsvcgroup_add.
|
||||
# The hbacsvcgroup for sudo is builtin with the name "Sudo" though.
|
||||
# This breaks the lower case comparison. Therefore all
|
||||
# memberservice_hbacsvcgroup items are converted to lower case if
|
||||
# "Sudo" is in the list.
|
||||
_member = "memberservice_hbacsvcgroup"
|
||||
if _member in res and "Sudo" in res[_member]:
|
||||
res[_member] = [item.lower() for item in res[_member]]
|
||||
return res
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@@ -146,21 +146,6 @@ def gen_member_args(hbacsvc):
|
||||
return _args
|
||||
|
||||
|
||||
# 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 "member" in result["failed"]:
|
||||
failed = result["failed"]["member"]
|
||||
for member_type in failed:
|
||||
for member, failure in failed[member_type]:
|
||||
if "already a member" not in failure \
|
||||
and "not a member" not in failure:
|
||||
errors.append("%s: %s %s: %s" % (
|
||||
command, member_type, member, failure))
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = IPAAnsibleModule(
|
||||
argument_spec=dict(
|
||||
@@ -303,7 +288,8 @@ def main():
|
||||
}])
|
||||
|
||||
# Execute commands
|
||||
changed = ansible_module.execute_ipa_commands(commands, result_handler)
|
||||
changed = ansible_module.execute_ipa_commands(
|
||||
commands, fail_on_member_errors=True)
|
||||
|
||||
# Done
|
||||
|
||||
|
||||
354
plugins/modules/ipaidoverridegroup.py
Normal file
354
plugins/modules/ipaidoverridegroup.py
Normal file
@@ -0,0 +1,354 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2023 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, exither version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
"metadata_version": "1.0",
|
||||
"supported_by": "community",
|
||||
"status": ["preview"],
|
||||
}
|
||||
|
||||
# No rename support: 'ID overrides cannot be renamed'
|
||||
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
|
||||
|
||||
DOCUMENTATION = """
|
||||
---
|
||||
module: ipaidoverridegroup
|
||||
short_description: Manage FreeIPA idoverridegroup
|
||||
description: Manage FreeIPA idoverridegroups
|
||||
extends_documentation_fragment:
|
||||
- ipamodule_base_docs
|
||||
options:
|
||||
idview:
|
||||
description: The idoverridegroup idview string.
|
||||
type: str
|
||||
required: true
|
||||
aliases: ["idviewcn"]
|
||||
anchor:
|
||||
description: The list of anchors to override
|
||||
type: list
|
||||
elements: str
|
||||
required: true
|
||||
aliases: ["ipaanchoruuid"]
|
||||
description:
|
||||
description: Description
|
||||
type: str
|
||||
required: False
|
||||
aliases: ["desc"]
|
||||
name:
|
||||
description: Group name
|
||||
type: str
|
||||
required: False
|
||||
aliases: ["group_name", "cn"]
|
||||
gid:
|
||||
description: Group ID Number (int or "")
|
||||
type: str
|
||||
required: False
|
||||
aliases: ["gidnumber"]
|
||||
fallback_to_ldap:
|
||||
description: |
|
||||
Allow falling back to AD DC LDAP when resolving AD trusted objects.
|
||||
For two-way trusts only.
|
||||
required: False
|
||||
type: bool
|
||||
delete_continue:
|
||||
description: |
|
||||
Continuous mode. Don't stop on errors.
|
||||
Valid only if `state` is `absent`.
|
||||
required: false
|
||||
type: bool
|
||||
aliases: ["continue"]
|
||||
state:
|
||||
description: The state to ensure.
|
||||
choices: ["present", "absent"]
|
||||
default: present
|
||||
type: str
|
||||
author:
|
||||
- Thomas Woerner (@t-woerner)
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
# Ensure test group test_group is present in idview test_idview
|
||||
- ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
|
||||
# Ensure test group test_group is present in idview test_idview with
|
||||
# description
|
||||
- ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
description: "test_group description"
|
||||
|
||||
# Ensure test group test_group is present in idview test_idview without
|
||||
# description
|
||||
- ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
description: ""
|
||||
|
||||
# Ensure test group test_group is present in idview test_idview with internal
|
||||
# name test_123_group
|
||||
- ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
name: test_123_group
|
||||
|
||||
# Ensure test group test_group is present in idview test_idview without
|
||||
# internal name
|
||||
- ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
name: ""
|
||||
|
||||
# Ensure test group test_group is present in idview test_idview with gid 20001
|
||||
- ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
gid: 20001
|
||||
|
||||
# Ensure test group test_group is present in idview test_idview without gid
|
||||
- ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
gid: ""
|
||||
|
||||
# Ensure test group test_group is absent in idview test_idview
|
||||
- ipaidoverridegroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_group
|
||||
continue: true
|
||||
state: absent
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
"""
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa
|
||||
from ansible.module_utils import six
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
|
||||
def find_idoverridegroup(module, idview, anchor):
|
||||
"""Find if a idoverridegroup with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("idoverridegroup_show", idview,
|
||||
{"ipaanchoruuid": anchor,
|
||||
"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if idoverridegroup anchor is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(anchor, description, name, gid):
|
||||
# fallback_to_ldap is only a runtime tuning parameter
|
||||
_args = {}
|
||||
if anchor is not None:
|
||||
_args["ipaanchoruuid"] = anchor
|
||||
if description is not None:
|
||||
_args["description"] = description
|
||||
if name is not None:
|
||||
_args["cn"] = name
|
||||
if gid is not None:
|
||||
_args["gidnumber"] = gid
|
||||
return _args
|
||||
|
||||
|
||||
def gen_args_runtime(fallback_to_ldap):
|
||||
_args = {}
|
||||
if fallback_to_ldap is not None:
|
||||
_args["fallback_to_ldap"] = fallback_to_ldap
|
||||
return _args
|
||||
|
||||
|
||||
def merge_dicts(dict1, dict2):
|
||||
ret = dict1.copy()
|
||||
ret.update(dict2)
|
||||
return ret
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = IPAAnsibleModule(
|
||||
argument_spec=dict(
|
||||
# general
|
||||
idview=dict(type="str", required=True, aliases=["idviewcn"]),
|
||||
anchor=dict(type="list", elements="str", required=True,
|
||||
aliases=["ipaanchoruuid"]),
|
||||
|
||||
# present
|
||||
description=dict(type="str", required=False, aliases=["desc"]),
|
||||
name=dict(type="str", required=False,
|
||||
aliases=["group_name", "cn"]),
|
||||
gid=dict(type="str", required=False, aliases=["gidnumber"]),
|
||||
|
||||
# runtime flags
|
||||
fallback_to_ldap=dict(type="bool", required=False),
|
||||
|
||||
# absent
|
||||
delete_continue=dict(type="bool", required=False,
|
||||
aliases=['continue'], default=None),
|
||||
|
||||
# No rename support: 'ID overrides cannot be renamed'
|
||||
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
|
||||
|
||||
# state
|
||||
state=dict(type="str", default="present",
|
||||
choices=["present", "absent"]),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
ansible_module._ansible_debug = True
|
||||
|
||||
# Get parameters
|
||||
|
||||
# general
|
||||
idview = ansible_module.params_get("idview")
|
||||
anchors = ansible_module.params_get("anchor")
|
||||
|
||||
# present
|
||||
description = ansible_module.params_get("description")
|
||||
name = ansible_module.params_get("name")
|
||||
gid = ansible_module.params_get("gid")
|
||||
|
||||
# runtime flags
|
||||
fallback_to_ldap = ansible_module.params_get("fallback_to_ldap")
|
||||
|
||||
# absent
|
||||
delete_continue = ansible_module.params_get("delete_continue")
|
||||
|
||||
# state
|
||||
state = ansible_module.params_get("state")
|
||||
|
||||
# Check parameters
|
||||
|
||||
invalid = []
|
||||
|
||||
if state == "present":
|
||||
if len(anchors) != 1:
|
||||
ansible_module.fail_json(
|
||||
msg="Only one idoverridegroup can be added at a time.")
|
||||
invalid = ["delete_continue"]
|
||||
|
||||
if state == "absent":
|
||||
if len(anchors) < 1:
|
||||
ansible_module.fail_json(msg="No name given.")
|
||||
invalid = ["description", "name", "gid"]
|
||||
|
||||
ansible_module.params_fail_used_invalid(invalid, state)
|
||||
|
||||
# Ensure parameter values are valid and have proper type.
|
||||
def int_or_empty_param(value, param):
|
||||
if value is not None and value != "":
|
||||
try:
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
ansible_module.fail_json(
|
||||
msg="Invalid value '%s' for argument '%s'" % (value, param)
|
||||
)
|
||||
return value
|
||||
|
||||
gid = int_or_empty_param(gid, "gid")
|
||||
|
||||
# Init
|
||||
|
||||
changed = False
|
||||
exit_args = {}
|
||||
|
||||
# Connect to IPA API
|
||||
with ansible_module.ipa_connect():
|
||||
|
||||
runtime_args = gen_args_runtime(fallback_to_ldap)
|
||||
commands = []
|
||||
for anchor in anchors:
|
||||
# Make sure idoverridegroup exists
|
||||
res_find = find_idoverridegroup(ansible_module, idview, anchor)
|
||||
|
||||
# Create command
|
||||
if state == "present":
|
||||
|
||||
# Generate args
|
||||
args = gen_args(anchor, description, name, gid)
|
||||
# fallback_to_ldap is only a runtime tuning parameter
|
||||
all_args = merge_dicts(args, runtime_args)
|
||||
|
||||
# Found the idoverridegroup
|
||||
if res_find is not None:
|
||||
# For idempotency: Remove empty sshpubkey list if
|
||||
# there are no sshpubkey in the found entry.
|
||||
if "ipasshpubkey" in args and \
|
||||
len(args["ipasshpubkey"]) < 1 and \
|
||||
"ipasshpubkey" not in res_find:
|
||||
del args["ipasshpubkey"]
|
||||
# For all settings is args, check if there are
|
||||
# different settings in the find result.
|
||||
# If yes: modify
|
||||
if not compare_args_ipa(ansible_module, args,
|
||||
res_find):
|
||||
commands.append([idview, "idoverridegroup_mod",
|
||||
all_args])
|
||||
else:
|
||||
commands.append([idview, "idoverridegroup_add",
|
||||
all_args])
|
||||
|
||||
elif state == "absent":
|
||||
if res_find is not None:
|
||||
commands.append(
|
||||
[idview, "idoverridegroup_del",
|
||||
merge_dicts(
|
||||
{
|
||||
"ipaanchoruuid": anchor,
|
||||
"continue": delete_continue or False
|
||||
},
|
||||
runtime_args
|
||||
)]
|
||||
)
|
||||
|
||||
else:
|
||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||
|
||||
# Execute commands
|
||||
|
||||
changed = ansible_module.execute_ipa_commands(commands)
|
||||
|
||||
# Done
|
||||
|
||||
ansible_module.exit_json(changed=changed, **exit_args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
631
plugins/modules/ipaidoverrideuser.py
Normal file
631
plugins/modules/ipaidoverrideuser.py
Normal file
@@ -0,0 +1,631 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2023 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
"metadata_version": "1.0",
|
||||
"supported_by": "community",
|
||||
"status": ["preview"],
|
||||
}
|
||||
|
||||
# No rename support: 'ID overrides cannot be renamed'
|
||||
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
|
||||
|
||||
DOCUMENTATION = """
|
||||
---
|
||||
module: ipaidoverrideuser
|
||||
short_description: Manage FreeIPA idoverrideuser
|
||||
description: Manage FreeIPA idoverrideuser and idoverrideuser members
|
||||
extends_documentation_fragment:
|
||||
- ipamodule_base_docs
|
||||
options:
|
||||
idview:
|
||||
description: The idoverrideuser idview string.
|
||||
type: str
|
||||
required: true
|
||||
aliases: ["idviewcn"]
|
||||
anchor:
|
||||
description: The list of anchors to override
|
||||
type: list
|
||||
elements: str
|
||||
required: true
|
||||
aliases: ["ipaanchoruuid"]
|
||||
description:
|
||||
description: Description
|
||||
type: str
|
||||
required: False
|
||||
aliases: ["desc"]
|
||||
name:
|
||||
description: The user (internally uid)
|
||||
type: str
|
||||
required: False
|
||||
aliases: ["login"]
|
||||
uid:
|
||||
description: User ID Number (int or "")
|
||||
type: str
|
||||
required: False
|
||||
aliases: ["uidnumber"]
|
||||
gecos:
|
||||
description: GECOS
|
||||
required: False
|
||||
type: str
|
||||
gidnumber:
|
||||
description: Group ID Number (int or "")
|
||||
required: False
|
||||
type: str
|
||||
homedir:
|
||||
description: Home directory
|
||||
type: str
|
||||
required: False
|
||||
aliases: ["homedirectory"]
|
||||
shell:
|
||||
description: Login shell
|
||||
type: str
|
||||
required: False
|
||||
aliases: ["loginshell"]
|
||||
sshpubkey:
|
||||
description: List of SSH public keys
|
||||
type: list
|
||||
element: str
|
||||
required: False
|
||||
aliases: ["ipasshpubkey"]
|
||||
certificate:
|
||||
description: List of Base-64 encoded user certificates
|
||||
type: list
|
||||
elements: str
|
||||
required: False
|
||||
aliases: ["usercertificate"]
|
||||
fallback_to_ldap:
|
||||
description: |
|
||||
Allow falling back to AD DC LDAP when resolving AD trusted objects.
|
||||
For two-way trusts only.
|
||||
required: False
|
||||
type: bool
|
||||
delete_continue:
|
||||
description: |
|
||||
Continuous mode. Don't stop on errors.
|
||||
Valid only if `state` is `absent`.
|
||||
required: false
|
||||
type: bool
|
||||
aliases: ["continue"]
|
||||
nomembers:
|
||||
description: |
|
||||
Suppress processing of membership attributes.
|
||||
Valid only if `state` is `absent`.
|
||||
type: str
|
||||
required: False
|
||||
aliases: ["no_members"]
|
||||
action:
|
||||
description: Work on idoverrideuser or member level.
|
||||
choices: ["idoverrideuser", "member"]
|
||||
default: idoverrideuser
|
||||
type: str
|
||||
state:
|
||||
description: The state to ensure.
|
||||
choices: ["present", "absent"]
|
||||
default: present
|
||||
type: str
|
||||
author:
|
||||
- Thomas Woerner (@t-woerner)
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
# Ensure test user test_user is present in idview test_idview
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with description
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
description: "test_user description"
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without
|
||||
# description
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
description: ""
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with internal
|
||||
# name test_123_user
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
name: test_123_user
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without internal
|
||||
# name
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
name: ""
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with uid 20001
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
uid: 20001
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without uid
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
uid: ""
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with gecos
|
||||
# "Gecos Test"
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
gecos: Gecos Test
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without gecos
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
gecos: ""
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with gidnumber
|
||||
# 20001
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
gidnumber: 20001
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without
|
||||
# gidnumber
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
gidnumber: ""
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with homedir
|
||||
# /Users
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
homedir: /Users
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without homedir
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
homedir: ""
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with shell
|
||||
# /bin/someshell
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
shell: /bin/someshell
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without shell
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
shell: ""
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with sshpubkey
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
sshpubkey:
|
||||
- ssh-rsa AAAAB3NzaC1yc2EAAADAQABAAABgQCqmVDpEX5gnSjKuv97Ay ...
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without
|
||||
# sshpubkey
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
sshpubkey: []
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with 1
|
||||
# certificate
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate:
|
||||
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview with 3
|
||||
# certificate members
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate:
|
||||
- "{{ lookup('file', 'cert1.b64', rstrip=False) }}"
|
||||
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
|
||||
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
|
||||
action: member
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without
|
||||
# 2 certificate members
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate:
|
||||
- "{{ lookup('file', 'cert2.b64', rstrip=False) }}"
|
||||
- "{{ lookup('file', 'cert3.b64', rstrip=False) }}"
|
||||
action: member
|
||||
state: absent
|
||||
|
||||
# Ensure test user test_user is present in idview test_idview without
|
||||
# certificates
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
certificate: []
|
||||
|
||||
# Ensure test user test_user is absent in idview test_idview
|
||||
- ipaidoverrideuser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
idview: test_idview
|
||||
anchor: test_user
|
||||
continue: true
|
||||
state: absent
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
"""
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
|
||||
gen_intersection_list, encode_certificate
|
||||
from ansible.module_utils import six
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
|
||||
def find_idoverrideuser(module, idview, anchor):
|
||||
"""Find if a idoverrideuser with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("idoverrideuser_show", idview,
|
||||
{"ipaanchoruuid": anchor,
|
||||
"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if idoverrideuser anchor is not found.
|
||||
return None
|
||||
|
||||
_res = _result["result"]
|
||||
certs = _res.get("usercertificate")
|
||||
if certs is not None:
|
||||
_res["usercertificate"] = [encode_certificate(cert) for cert in certs]
|
||||
return _res
|
||||
|
||||
|
||||
def gen_args(anchor, description, name, uid, gecos, gidnumber, homedir, shell,
|
||||
sshpubkey):
|
||||
# fallback_to_ldap and nomembers are only runtime tuning parameters
|
||||
_args = {}
|
||||
if anchor is not None:
|
||||
_args["ipaanchoruuid"] = anchor
|
||||
if description is not None:
|
||||
_args["description"] = description
|
||||
if name is not None:
|
||||
_args["uid"] = name
|
||||
if uid is not None:
|
||||
_args["uidnumber"] = uid
|
||||
if gecos is not None:
|
||||
_args["gecos"] = gecos
|
||||
if gidnumber is not None:
|
||||
_args["gidnumber"] = gidnumber
|
||||
if homedir is not None:
|
||||
_args["homedirectory"] = homedir
|
||||
if shell is not None:
|
||||
_args["loginshell"] = shell
|
||||
if sshpubkey is not None:
|
||||
_args["ipasshpubkey"] = sshpubkey
|
||||
return _args
|
||||
|
||||
|
||||
def gen_args_runtime(fallback_to_ldap, nomembers):
|
||||
_args = {}
|
||||
if fallback_to_ldap is not None:
|
||||
_args["fallback_to_ldap"] = fallback_to_ldap
|
||||
if nomembers is not None:
|
||||
_args["no_members"] = nomembers
|
||||
return _args
|
||||
|
||||
|
||||
def gen_member_args(certificate):
|
||||
_args = {}
|
||||
if certificate is not None:
|
||||
_args["usercertificate"] = certificate
|
||||
return _args
|
||||
|
||||
|
||||
def merge_dicts(dict1, dict2):
|
||||
ret = dict1.copy()
|
||||
ret.update(dict2)
|
||||
return ret
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = IPAAnsibleModule(
|
||||
argument_spec=dict(
|
||||
# general
|
||||
idview=dict(type="str", required=True, aliases=["idviewcn"]),
|
||||
anchor=dict(type="list", elements="str", required=True,
|
||||
aliases=["ipaanchoruuid"]),
|
||||
|
||||
# present
|
||||
description=dict(type="str", required=False, aliases=["desc"]),
|
||||
name=dict(type="str", required=False, aliases=["login"]),
|
||||
uid=dict(type="str", required=False, aliases=["uidnumber"]),
|
||||
gecos=dict(type="str", required=False),
|
||||
gidnumber=dict(type="str", required=False),
|
||||
homedir=dict(type="str", required=False,
|
||||
aliases=["homedirectory"]),
|
||||
shell=dict(type="str", required=False, aliases=["loginshell"]),
|
||||
sshpubkey=dict(type="list", elements="str", required=False,
|
||||
aliases=["ipasshpubkey"]),
|
||||
certificate=dict(type="list", elements="str", required=False,
|
||||
aliases=["usercertificate"]),
|
||||
fallback_to_ldap=dict(type="bool", required=False),
|
||||
nomembers=dict(type="bool", required=False,
|
||||
aliases=["no_members"]),
|
||||
|
||||
# absent
|
||||
delete_continue=dict(type="bool", required=False,
|
||||
aliases=['continue'], default=None),
|
||||
|
||||
# No rename support: 'ID overrides cannot be renamed'
|
||||
# ipaserver/plugins/idviews.py:baseidoverride_mod:pre_callback
|
||||
|
||||
# action
|
||||
action=dict(type="str", default="idoverrideuser",
|
||||
choices=["member", "idoverrideuser"]),
|
||||
# state
|
||||
state=dict(type="str", default="present",
|
||||
choices=["present", "absent"]),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
ansible_module._ansible_debug = True
|
||||
|
||||
# Get parameters
|
||||
|
||||
# general
|
||||
idview = ansible_module.params_get("idview")
|
||||
anchors = ansible_module.params_get("anchor")
|
||||
|
||||
# present
|
||||
description = ansible_module.params_get("description")
|
||||
name = ansible_module.params_get("name")
|
||||
uid = ansible_module.params_get("uid")
|
||||
gecos = ansible_module.params_get("gecos")
|
||||
gidnumber = ansible_module.params_get("gidnumber")
|
||||
homedir = ansible_module.params_get("homedir")
|
||||
shell = ansible_module.params_get("shell")
|
||||
sshpubkey = ansible_module.params_get("sshpubkey")
|
||||
certificate = ansible_module.params_get("certificate")
|
||||
fallback_to_ldap = ansible_module.params_get("fallback_to_ldap")
|
||||
nomembers = ansible_module.params_get("nomembers")
|
||||
action = ansible_module.params_get("action")
|
||||
|
||||
# absent
|
||||
delete_continue = ansible_module.params_get("delete_continue")
|
||||
|
||||
# state
|
||||
state = ansible_module.params_get("state")
|
||||
|
||||
# Check parameters
|
||||
|
||||
invalid = []
|
||||
|
||||
if state == "present":
|
||||
if len(anchors) != 1:
|
||||
ansible_module.fail_json(
|
||||
msg="Only one idoverrideuser can be added at a time.")
|
||||
invalid = ["delete_continue"]
|
||||
if action == "member":
|
||||
invalid += ["description", "name", "uid", "gecos", "gidnumber",
|
||||
"homedir", "shell", "sshpubkey"]
|
||||
|
||||
if state == "absent":
|
||||
if len(anchors) < 1:
|
||||
ansible_module.fail_json(msg="No name given.")
|
||||
invalid = ["description", "name", "uid", "gecos", "gidnumber",
|
||||
"homedir", "shell", "sshpubkey", "nomembers"]
|
||||
if action == "idoverrideuser":
|
||||
invalid += ["certificate"]
|
||||
|
||||
ansible_module.params_fail_used_invalid(invalid, state, action)
|
||||
|
||||
# Ensure parameter values are valid and have proper type.
|
||||
def int_or_empty_param(value, param):
|
||||
if value is not None and value != "":
|
||||
try:
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
ansible_module.fail_json(
|
||||
msg="Invalid value '%s' for argument '%s'" % (value, param)
|
||||
)
|
||||
return value
|
||||
|
||||
uid = int_or_empty_param(uid, "uid")
|
||||
gidnumber = int_or_empty_param(gidnumber, "gidnumber")
|
||||
|
||||
if certificate is not None:
|
||||
certificate = [cert.strip() for cert in certificate]
|
||||
|
||||
# Init
|
||||
|
||||
changed = False
|
||||
exit_args = {}
|
||||
|
||||
# Connect to IPA API
|
||||
with ansible_module.ipa_connect():
|
||||
|
||||
runtime_args = gen_args_runtime(fallback_to_ldap, nomembers)
|
||||
commands = []
|
||||
for anchor in anchors:
|
||||
# Make sure idoverrideuser exists
|
||||
res_find = find_idoverrideuser(ansible_module, idview, anchor)
|
||||
|
||||
# add/del lists
|
||||
certificate_add, certificate_del = [], []
|
||||
|
||||
# Create command
|
||||
if state == "present":
|
||||
|
||||
# Generate args
|
||||
args = gen_args(anchor, description, name, uid, gecos,
|
||||
gidnumber, homedir, shell, sshpubkey)
|
||||
# fallback_to_ldap and nomembers are only runtime tuning
|
||||
# parameters
|
||||
all_args = merge_dicts(args, runtime_args)
|
||||
|
||||
if action == "idoverrideuser":
|
||||
# Found the idoverrideuser
|
||||
if res_find is not None:
|
||||
# For idempotency: Remove empty sshpubkey list if
|
||||
# there are no sshpubkey in the found entry.
|
||||
if "ipasshpubkey" in args and \
|
||||
len(args["ipasshpubkey"]) < 1 and \
|
||||
"ipasshpubkey" not in res_find:
|
||||
del args["ipasshpubkey"]
|
||||
# For all settings is args, check if there are
|
||||
# different settings in the find result.
|
||||
# If yes: modify
|
||||
if not compare_args_ipa(ansible_module, args,
|
||||
res_find):
|
||||
commands.append([idview, "idoverrideuser_mod",
|
||||
all_args])
|
||||
else:
|
||||
commands.append([idview, "idoverrideuser_add",
|
||||
all_args])
|
||||
res_find = {}
|
||||
|
||||
member_args = gen_member_args(certificate)
|
||||
if not compare_args_ipa(ansible_module, member_args,
|
||||
res_find):
|
||||
|
||||
# Generate addition and removal lists
|
||||
certificate_add, certificate_del = gen_add_del_lists(
|
||||
certificate, res_find.get("usercertificate"))
|
||||
|
||||
elif action == "member":
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(
|
||||
msg="No idoverrideuser '%s' in idview '%s'" %
|
||||
(anchor, idview))
|
||||
|
||||
# Reduce add lists for certificate
|
||||
# to new entries only that are not in res_find.
|
||||
if certificate is not None:
|
||||
certificate_add = gen_add_list(
|
||||
certificate, res_find.get("usercertificate"))
|
||||
|
||||
elif state == "absent":
|
||||
if action == "idoverrideuser":
|
||||
if res_find is not None:
|
||||
commands.append(
|
||||
[idview, "idoverrideuser_del",
|
||||
merge_dicts(
|
||||
{
|
||||
"ipaanchoruuid": anchor,
|
||||
"continue": delete_continue or False
|
||||
},
|
||||
runtime_args
|
||||
)]
|
||||
)
|
||||
|
||||
elif action == "member":
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(
|
||||
msg="No idoverrideuser '%s' in idview '%s'" %
|
||||
(anchor, idview))
|
||||
|
||||
# Reduce del lists of member_host and member_hostgroup,
|
||||
# to the entries only that are in res_find.
|
||||
if certificate is not None:
|
||||
certificate_del = gen_intersection_list(
|
||||
certificate, res_find.get("usercertificate"))
|
||||
|
||||
else:
|
||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||
|
||||
# Member management
|
||||
|
||||
# Add members
|
||||
if certificate_add:
|
||||
commands.append([idview, "idoverrideuser_add_cert",
|
||||
merge_dicts(
|
||||
{
|
||||
"ipaanchoruuid": anchor,
|
||||
"usercertificate": certificate_add
|
||||
},
|
||||
runtime_args
|
||||
)])
|
||||
|
||||
# Remove members
|
||||
|
||||
if certificate_del:
|
||||
commands.append([idview, "idoverrideuser_remove_cert",
|
||||
merge_dicts(
|
||||
{
|
||||
"ipaanchoruuid": anchor,
|
||||
"usercertificate": certificate_del
|
||||
},
|
||||
runtime_args
|
||||
)])
|
||||
|
||||
# Execute commands
|
||||
|
||||
changed = ansible_module.execute_ipa_commands(commands)
|
||||
|
||||
# Done
|
||||
|
||||
ansible_module.exit_json(changed=changed, **exit_args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
544
plugins/modules/ipaidp.py
Normal file
544
plugins/modules/ipaidp.py
Normal file
@@ -0,0 +1,544 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2023 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
"metadata_version": "1.0",
|
||||
"supported_by": "community",
|
||||
"status": ["preview"],
|
||||
}
|
||||
|
||||
DOCUMENTATION = """
|
||||
---
|
||||
module: ipaidp
|
||||
short_description: Manage FreeIPA idp
|
||||
description: Manage FreeIPA idp
|
||||
extends_documentation_fragment:
|
||||
- ipamodule_base_docs
|
||||
options:
|
||||
name:
|
||||
description: The list of idp name strings.
|
||||
required: true
|
||||
type: list
|
||||
elements: str
|
||||
aliases: ["cn"]
|
||||
auth_uri:
|
||||
description: OAuth 2.0 authorization endpoint
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidpauthendpoint"]
|
||||
dev_auth_uri:
|
||||
description: Device authorization endpoint
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidpdevauthendpoint"]
|
||||
token_uri:
|
||||
description: Token endpoint
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidptokenendpoint"]
|
||||
userinfo_uri:
|
||||
description: User information endpoint
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidpuserinfoendpoint"]
|
||||
keys_uri:
|
||||
description: JWKS endpoint
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidpkeysendpoint"]
|
||||
issuer_url:
|
||||
description: The Identity Provider OIDC URL
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidpissuerurl"]
|
||||
client_id:
|
||||
description: OAuth 2.0 client identifier
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidpclientid"]
|
||||
secret:
|
||||
description: OAuth 2.0 client secret
|
||||
required: false
|
||||
type: str
|
||||
no_log: true
|
||||
aliases: ["ipaidpclientsecret"]
|
||||
scope:
|
||||
description: OAuth 2.0 scope. Multiple scopes separated by space
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidpscope"]
|
||||
idp_user_id:
|
||||
description: Attribute for user identity in OAuth 2.0 userinfo
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidpsub"]
|
||||
provider:
|
||||
description: |
|
||||
Pre-defined template string. This provides the provider defaults, which
|
||||
can be overridden with the other IdP options.
|
||||
required: false
|
||||
type: str
|
||||
choices: ["google","github","microsoft","okta","keycloak"]
|
||||
aliases: ["ipaidpprovider"]
|
||||
organization:
|
||||
description: Organization ID or Realm name for IdP provider templates
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidporg"]
|
||||
base_url:
|
||||
description: Base URL for IdP provider templates
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["ipaidpbaseurl"]
|
||||
rename:
|
||||
description: |
|
||||
New name the Identity Provider server object. Only with state: renamed.
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["new_name"]
|
||||
delete_continue:
|
||||
description:
|
||||
Continuous mode. Don't stop on errors. Valid only if `state` is `absent`.
|
||||
required: false
|
||||
type: bool
|
||||
aliases: ["continue"]
|
||||
state:
|
||||
description: The state to ensure.
|
||||
choices: ["present", "absent", "renamed"]
|
||||
default: present
|
||||
type: str
|
||||
author:
|
||||
- Thomas Woerner (@t-woerner)
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
# Ensure keycloak idp my-keycloak-idp is present
|
||||
- ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-keycloak-idp
|
||||
provider: keycloak
|
||||
organization: main
|
||||
base_url: keycloak.idm.example.com:8443/auth
|
||||
client_id: my-client-id
|
||||
|
||||
# Ensure google idp my-google-idp is present
|
||||
- ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-google-idp
|
||||
auth_uri: https://accounts.google.com/o/oauth2/auth
|
||||
dev_auth_uri: https://oauth2.googleapis.com/device/code
|
||||
token_uri: https://oauth2.googleapis.com/token
|
||||
userinfo_uri: https://openidconnect.googleapis.com/v1/userinfo
|
||||
client_id: my-client-id
|
||||
scope: "openid email"
|
||||
idp_user_id: email
|
||||
|
||||
# Ensure google idp my-google-idp is present without using provider
|
||||
- ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-google-idp
|
||||
provider: google
|
||||
client_id: my-google-client-id
|
||||
|
||||
# Ensure keycloak idp my-keycloak-idp is absent
|
||||
- ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-keycloak-idp
|
||||
delete_continue: true
|
||||
state: absent
|
||||
|
||||
# Ensure idps my-keycloak-idp, my-github-idp and my-google-idp are absent
|
||||
- ipaidp:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name:
|
||||
- my-keycloak-idp
|
||||
- my-github-idp
|
||||
- my-google-idp
|
||||
delete_continue: true
|
||||
state: absent
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
"""
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, template_str
|
||||
from ansible.module_utils import six
|
||||
from copy import deepcopy
|
||||
import string
|
||||
from itertools import chain
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
# Copy from FreeIPA ipaserver/plugins/idp.py
|
||||
idp_providers = {
|
||||
'google': {
|
||||
'ipaidpauthendpoint':
|
||||
'https://accounts.google.com/o/oauth2/auth',
|
||||
'ipaidpdevauthendpoint':
|
||||
'https://oauth2.googleapis.com/device/code',
|
||||
'ipaidptokenendpoint':
|
||||
'https://oauth2.googleapis.com/token',
|
||||
'ipaidpuserinfoendpoint':
|
||||
'https://openidconnect.googleapis.com/v1/userinfo',
|
||||
'ipaidpkeysendpoint':
|
||||
'https://www.googleapis.com/oauth2/v3/certs',
|
||||
'ipaidpscope': 'openid email',
|
||||
'ipaidpsub': 'email'},
|
||||
'github': {
|
||||
'ipaidpauthendpoint':
|
||||
'https://github.com/login/oauth/authorize',
|
||||
'ipaidpdevauthendpoint':
|
||||
'https://github.com/login/device/code',
|
||||
'ipaidptokenendpoint':
|
||||
'https://github.com/login/oauth/access_token',
|
||||
'ipaidpuserinfoendpoint':
|
||||
'https://api.github.com/user',
|
||||
'ipaidpscope': 'user',
|
||||
'ipaidpsub': 'login'},
|
||||
'microsoft': {
|
||||
'ipaidpauthendpoint':
|
||||
'https://login.microsoftonline.com/${ipaidporg}/oauth2/v2.0/'
|
||||
'authorize',
|
||||
'ipaidpdevauthendpoint':
|
||||
'https://login.microsoftonline.com/${ipaidporg}/oauth2/v2.0/'
|
||||
'devicecode',
|
||||
'ipaidptokenendpoint':
|
||||
'https://login.microsoftonline.com/${ipaidporg}/oauth2/v2.0/'
|
||||
'token',
|
||||
'ipaidpuserinfoendpoint':
|
||||
'https://graph.microsoft.com/oidc/userinfo',
|
||||
'ipaidpkeysendpoint':
|
||||
'https://login.microsoftonline.com/common/discovery/v2.0/keys',
|
||||
'ipaidpscope': 'openid email',
|
||||
'ipaidpsub': 'email',
|
||||
},
|
||||
'okta': {
|
||||
'ipaidpauthendpoint':
|
||||
'https://${ipaidpbaseurl}/oauth2/v1/authorize',
|
||||
'ipaidpdevauthendpoint':
|
||||
'https://${ipaidpbaseurl}/oauth2/v1/device/authorize',
|
||||
'ipaidptokenendpoint':
|
||||
'https://${ipaidpbaseurl}/oauth2/v1/token',
|
||||
'ipaidpuserinfoendpoint':
|
||||
'https://${ipaidpbaseurl}/oauth2/v1/userinfo',
|
||||
'ipaidpscope': 'openid email',
|
||||
'ipaidpsub': 'email'},
|
||||
'keycloak': {
|
||||
'ipaidpauthendpoint':
|
||||
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
|
||||
'openid-connect/auth',
|
||||
'ipaidpdevauthendpoint':
|
||||
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
|
||||
'openid-connect/auth/device',
|
||||
'ipaidptokenendpoint':
|
||||
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
|
||||
'openid-connect/token',
|
||||
'ipaidpuserinfoendpoint':
|
||||
'https://${ipaidpbaseurl}/realms/${ipaidporg}/protocol/'
|
||||
'openid-connect/userinfo',
|
||||
'ipaidpscope': 'openid email',
|
||||
'ipaidpsub': 'email'},
|
||||
}
|
||||
|
||||
|
||||
def find_idp(module, name):
|
||||
"""Find if a idp with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("idp_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if idp name is not found.
|
||||
return None
|
||||
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(auth_uri, dev_auth_uri, token_uri, userinfo_uri, keys_uri,
|
||||
issuer_url, client_id, secret, scope, idp_user_id, organization,
|
||||
base_url):
|
||||
_args = {}
|
||||
if auth_uri is not None:
|
||||
_args["ipaidpauthendpoint"] = auth_uri
|
||||
if dev_auth_uri is not None:
|
||||
_args["ipaidpdevauthendpoint"] = dev_auth_uri
|
||||
if token_uri is not None:
|
||||
_args["ipaidptokenendpoint"] = token_uri
|
||||
if userinfo_uri is not None:
|
||||
_args["ipaidpuserinfoendpoint"] = userinfo_uri
|
||||
if keys_uri is not None:
|
||||
_args["ipaidpkeysendpoint"] = keys_uri
|
||||
if issuer_url is not None:
|
||||
_args["ipaidpissuerurl"] = issuer_url
|
||||
if client_id is not None:
|
||||
_args["ipaidpclientid"] = client_id
|
||||
if secret is not None:
|
||||
_args["ipaidpclientsecret"] = secret
|
||||
if scope is not None:
|
||||
_args["ipaidpscope"] = scope
|
||||
if idp_user_id is not None:
|
||||
_args["ipaidpsub"] = idp_user_id
|
||||
if organization is not None:
|
||||
_args["ipaidporg"] = organization
|
||||
if base_url is not None:
|
||||
_args["ipaidpbaseurl"] = base_url
|
||||
return _args
|
||||
|
||||
|
||||
# Copied and adapted from FreeIPA ipaserver/plugins/idp.py
|
||||
def convert_provider_to_endpoints(module, _args, provider):
|
||||
"""Convert provider option to auth-uri and token-uri,.."""
|
||||
if provider not in idp_providers:
|
||||
module.fail_json(msg="Provider '%s' is unknown" % provider)
|
||||
|
||||
# For each string in the template check if a variable
|
||||
# is required, it is provided as an option
|
||||
points = deepcopy(idp_providers[provider])
|
||||
_r = string.Template.pattern
|
||||
for (_k, _v) in points.items():
|
||||
# build list of variables to be replaced
|
||||
subs = list(chain.from_iterable(
|
||||
(filter(None, _s) for _s in _r.findall(_v))))
|
||||
if subs:
|
||||
for _s in subs:
|
||||
if _s not in _args:
|
||||
module.fail_json(msg="Parameter '%s' is missing" % _s)
|
||||
points[_k] = template_str(_v, _args)
|
||||
elif _k in _args:
|
||||
points[_k] = _args[_k]
|
||||
|
||||
_args.update(points)
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = IPAAnsibleModule(
|
||||
argument_spec=dict(
|
||||
# general
|
||||
name=dict(type="list", elements="str", required=True,
|
||||
aliases=["cn"]),
|
||||
# present
|
||||
auth_uri=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpauthendpoint"]),
|
||||
dev_auth_uri=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpdevauthendpoint"]),
|
||||
token_uri=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidptokenendpoint"]),
|
||||
userinfo_uri=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpuserinfoendpoint"]),
|
||||
keys_uri=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpkeysendpoint"]),
|
||||
issuer_url=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpissuerurl"]),
|
||||
client_id=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpclientid"]),
|
||||
secret=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpclientsecret"], no_log=True),
|
||||
scope=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpscope"]),
|
||||
idp_user_id=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpsub"]),
|
||||
provider=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpprovider"],
|
||||
choices=["google", "github", "microsoft", "okta",
|
||||
"keycloak"]),
|
||||
organization=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidporg"]),
|
||||
base_url=dict(required=False, type="str", default=None,
|
||||
aliases=["ipaidpbaseurl"]),
|
||||
rename=dict(required=False, type="str", default=None,
|
||||
aliases=["new_name"]),
|
||||
delete_continue=dict(required=False, type="bool", default=None,
|
||||
aliases=['continue']),
|
||||
# state
|
||||
state=dict(type="str", default="present",
|
||||
choices=["present", "absent", "renamed"]),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
# mutually_exclusive=[],
|
||||
# required_one_of=[]
|
||||
)
|
||||
|
||||
ansible_module._ansible_debug = True
|
||||
|
||||
# Get parameters
|
||||
|
||||
# general
|
||||
names = ansible_module.params_get("name")
|
||||
|
||||
# present
|
||||
auth_uri = ansible_module.params_get("auth_uri")
|
||||
dev_auth_uri = ansible_module.params_get("dev_auth_uri")
|
||||
token_uri = ansible_module.params_get("token_uri")
|
||||
userinfo_uri = ansible_module.params_get("userinfo_uri")
|
||||
keys_uri = ansible_module.params_get("keys_uri")
|
||||
issuer_url = ansible_module.params_get("issuer_url")
|
||||
client_id = ansible_module.params_get("client_id")
|
||||
secret = ansible_module.params_get("secret")
|
||||
scope = ansible_module.params_get("scope")
|
||||
idp_user_id = ansible_module.params_get("idp_user_id")
|
||||
provider = ansible_module.params_get("provider")
|
||||
organization = ansible_module.params_get("organization")
|
||||
base_url = ansible_module.params_get("base_url")
|
||||
rename = ansible_module.params_get("rename")
|
||||
|
||||
delete_continue = ansible_module.params_get("delete_continue")
|
||||
|
||||
# state
|
||||
state = ansible_module.params_get("state")
|
||||
|
||||
# Check parameters
|
||||
|
||||
invalid = []
|
||||
|
||||
if state == "present":
|
||||
if len(names) != 1:
|
||||
ansible_module.fail_json(
|
||||
msg="Only one idp can be added at a time.")
|
||||
if provider:
|
||||
if any([auth_uri, dev_auth_uri, token_uri, userinfo_uri,
|
||||
keys_uri]):
|
||||
ansible_module.fail_json(
|
||||
msg="Cannot specify both individual endpoints and IdP "
|
||||
"provider")
|
||||
if provider not in idp_providers:
|
||||
ansible_module.fail_json(
|
||||
msg="Provider '%s' is unknown" % provider)
|
||||
else:
|
||||
if not auth_uri:
|
||||
ansible_module.fail_json(
|
||||
msg="Parameter '%s' is missing" % "auth_uri")
|
||||
if not dev_auth_uri:
|
||||
ansible_module.fail_json(
|
||||
msg="Parameter '%s' is missing" % "dev_auth_uri")
|
||||
if not token_uri:
|
||||
ansible_module.fail_json(
|
||||
msg="Parameter '%s' is missing" % "token_uri")
|
||||
if not userinfo_uri:
|
||||
ansible_module.fail_json(
|
||||
msg="Parameter '%s' is missing" % "userinfo_uri")
|
||||
invalid = ["rename", "delete_continue"]
|
||||
else:
|
||||
# state renamed and absent
|
||||
invalid = ["auth_uri", "dev_auth_uri", "token_uri", "userinfo_uri",
|
||||
"keys_uri", "issuer_url", "client_id", "secret", "scope",
|
||||
"idp_user_id", "provider", "organization", "base_url"]
|
||||
|
||||
if state == "renamed":
|
||||
if len(names) != 1:
|
||||
ansible_module.fail_json(
|
||||
msg="Only one permission can be renamed at a time.")
|
||||
invalid += ["delete_continue"]
|
||||
|
||||
if state == "absent":
|
||||
if len(names) < 1:
|
||||
ansible_module.fail_json(msg="No name given.")
|
||||
invalid += ["rename"]
|
||||
|
||||
ansible_module.params_fail_used_invalid(invalid, state)
|
||||
|
||||
# Init
|
||||
|
||||
changed = False
|
||||
exit_args = {}
|
||||
|
||||
# Connect to IPA API
|
||||
with ansible_module.ipa_connect():
|
||||
|
||||
if not ansible_module.ipa_command_exists("idp_add"):
|
||||
ansible_module.fail_json(
|
||||
msg="Managing idp is not supported by your IPA version")
|
||||
|
||||
commands = []
|
||||
for name in names:
|
||||
# Make sure idp exists
|
||||
res_find = find_idp(ansible_module, name)
|
||||
|
||||
# Create command
|
||||
if state == "present":
|
||||
|
||||
# Generate args
|
||||
args = gen_args(auth_uri, dev_auth_uri, token_uri,
|
||||
userinfo_uri, keys_uri, issuer_url, client_id,
|
||||
secret, scope, idp_user_id, organization,
|
||||
base_url)
|
||||
|
||||
if provider is not None:
|
||||
convert_provider_to_endpoints(ansible_module, args,
|
||||
provider)
|
||||
|
||||
# Found the idp
|
||||
if res_find is not None:
|
||||
# The parameters ipaidpprovider, ipaidporg and
|
||||
# ipaidpbaseurl are only available for idp-add to create
|
||||
# then endpoints using provider, Therefore we have to
|
||||
# remove them from args.
|
||||
for arg in ["ipaidpprovider", "ipaidporg",
|
||||
"ipaidpbaseurl"]:
|
||||
if arg in args:
|
||||
del args[arg]
|
||||
|
||||
# For all settings is args, check if there are
|
||||
# different settings in the find result.
|
||||
# If yes: modify
|
||||
if not compare_args_ipa(ansible_module, args,
|
||||
res_find):
|
||||
commands.append([name, "idp_mod", args])
|
||||
else:
|
||||
commands.append([name, "idp_add", args])
|
||||
|
||||
elif state == "absent":
|
||||
if res_find is not None:
|
||||
_args = {}
|
||||
if delete_continue is not None:
|
||||
_args = {"continue": delete_continue}
|
||||
commands.append([name, "idp_del", _args])
|
||||
|
||||
elif state == "renamed":
|
||||
if not rename:
|
||||
ansible_module.fail_json(msg="No rename value given.")
|
||||
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(
|
||||
msg="No idp found to be renamed: '%s'" % (name))
|
||||
|
||||
if name != rename:
|
||||
commands.append(
|
||||
[name, "idp_mod", {"rename": rename}])
|
||||
|
||||
else:
|
||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||
|
||||
# Execute commands
|
||||
|
||||
changed = ansible_module.execute_ipa_commands(commands)
|
||||
|
||||
# Done
|
||||
|
||||
ansible_module.exit_json(changed=changed, **exit_args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -157,8 +157,7 @@ def find_idrange(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if idrange name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(
|
||||
|
||||
362
plugins/modules/ipaidview.py
Normal file
362
plugins/modules/ipaidview.py
Normal file
@@ -0,0 +1,362 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2023 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {
|
||||
"metadata_version": "1.0",
|
||||
"supported_by": "community",
|
||||
"status": ["preview"],
|
||||
}
|
||||
|
||||
DOCUMENTATION = """
|
||||
---
|
||||
module: ipaidview
|
||||
short_description: Manage FreeIPA idview
|
||||
description: Manage FreeIPA idview and idview host members
|
||||
extends_documentation_fragment:
|
||||
- ipamodule_base_docs
|
||||
options:
|
||||
name:
|
||||
description: The list of idview name strings.
|
||||
required: true
|
||||
type: list
|
||||
elements: str
|
||||
aliases: ["cn"]
|
||||
description:
|
||||
description: Description
|
||||
required: False
|
||||
type: str
|
||||
aliases: ["desc"]
|
||||
domain_resolution_order:
|
||||
description: |
|
||||
Colon-separated list of domains used for short name qualification
|
||||
required: False
|
||||
type: str
|
||||
aliases: ["ipadomainresolutionorder"]
|
||||
host:
|
||||
description: Hosts to apply the ID View to
|
||||
required: False
|
||||
type: list
|
||||
elements: str
|
||||
aliases: ["hosts"]
|
||||
rename:
|
||||
description: Rename the ID view object
|
||||
required: False
|
||||
type: str
|
||||
aliases: ["new_name"]
|
||||
delete_continue:
|
||||
description: |
|
||||
Continuous mode. Don't stop on errors.
|
||||
Valid only if `state` is `absent`.
|
||||
required: false
|
||||
type: bool
|
||||
aliases: ["continue"]
|
||||
action:
|
||||
description: Work on idview or member level.
|
||||
choices: ["idview", "member"]
|
||||
default: idview
|
||||
type: str
|
||||
state:
|
||||
description: The state to ensure.
|
||||
choices: ["present", "absent", "renamed"]
|
||||
default: present
|
||||
type: str
|
||||
author:
|
||||
- Thomas Woerner (@t-woerner)
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
# Ensure idview test_idview is present
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
|
||||
# name: Ensure host testhost.example.com is applied to idview test_idview
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
host: testhost.example.com
|
||||
action: member
|
||||
|
||||
# Ensure host testhost.example.com is not applied to idview test_idview
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
host: testhost.example.com
|
||||
action: member
|
||||
state: absent
|
||||
|
||||
# Ensure idview "test_idview" is present with domain_resolution_order for
|
||||
# "ad.example.com:ipa.example.com"
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
domain_resolution_order: "ad.example.com:ipa.example.com"
|
||||
|
||||
# Ensure idview test_idview is absent
|
||||
- ipaidview:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: test_idview
|
||||
state: absent
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
"""
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
|
||||
gen_intersection_list, ipalib_errors
|
||||
from ansible.module_utils import six
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
|
||||
def find_idview(module, name):
|
||||
"""Find if a idview with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("idview_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if idview name is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def valid_host(module, name):
|
||||
try:
|
||||
module.ipa_command("host_show", name, {})
|
||||
except ipalib_errors.NotFound:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def gen_args(description, domain_resolution_order):
|
||||
_args = {}
|
||||
if description is not None:
|
||||
_args["description"] = description
|
||||
if domain_resolution_order is not None:
|
||||
_args["ipadomainresolutionorder"] = domain_resolution_order
|
||||
return _args
|
||||
|
||||
|
||||
def gen_member_args(host):
|
||||
_args = {}
|
||||
if host is not None:
|
||||
_args["host"] = host
|
||||
return _args
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = IPAAnsibleModule(
|
||||
argument_spec=dict(
|
||||
# general
|
||||
name=dict(type="list", elements="str", required=True,
|
||||
aliases=["cn"]),
|
||||
# present
|
||||
description=dict(type="str", required=False, aliases=["desc"]),
|
||||
domain_resolution_order=dict(type="str", required=False,
|
||||
aliases=["ipadomainresolutionorder"]),
|
||||
host=dict(type="list", elements="str", required=False,
|
||||
aliases=["hosts"], default=None),
|
||||
rename=dict(type="str", required=False, aliases=["new_name"]),
|
||||
delete_continue=dict(type="bool", required=False,
|
||||
aliases=['continue'], default=None),
|
||||
# action
|
||||
action=dict(type="str", default="idview",
|
||||
choices=["member", "idview"]),
|
||||
# state
|
||||
state=dict(type="str", default="present",
|
||||
choices=["present", "absent", "renamed"]),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
ansible_module._ansible_debug = True
|
||||
|
||||
# Get parameters
|
||||
|
||||
# general
|
||||
names = ansible_module.params_get("name")
|
||||
|
||||
# present
|
||||
description = ansible_module.params_get("description")
|
||||
domain_resolution_order = ansible_module.params_get(
|
||||
"domain_resolution_order")
|
||||
host = ansible_module.params_get("host")
|
||||
rename = ansible_module.params_get("rename")
|
||||
|
||||
action = ansible_module.params_get("action")
|
||||
|
||||
# absent
|
||||
delete_continue = ansible_module.params_get("delete_continue")
|
||||
|
||||
# state
|
||||
state = ansible_module.params_get("state")
|
||||
|
||||
# Check parameters
|
||||
|
||||
invalid = []
|
||||
|
||||
if state == "present":
|
||||
if len(names) != 1:
|
||||
ansible_module.fail_json(
|
||||
msg="Only one idview can be added at a time.")
|
||||
invalid = ["delete_continue", "rename"]
|
||||
if action == "member":
|
||||
invalid += ["description", "domain_resolution_order"]
|
||||
|
||||
if state == "renamed":
|
||||
if len(names) != 1:
|
||||
ansible_module.fail_json(
|
||||
msg="Only one idoverridegroup can be renamed at a time.")
|
||||
if not rename:
|
||||
ansible_module.fail_json(
|
||||
msg="Rename is required for state: renamed.")
|
||||
if action == "member":
|
||||
ansible_module.fail_json(
|
||||
msg="Action member can not be used with state: renamed.")
|
||||
invalid = ["description", "domain_resolution_order", "host",
|
||||
"delete_continue"]
|
||||
|
||||
if state == "absent":
|
||||
if len(names) < 1:
|
||||
ansible_module.fail_json(msg="No name given.")
|
||||
invalid = ["description", "domain_resolution_order", "rename"]
|
||||
if action == "idview":
|
||||
invalid += ["host"]
|
||||
|
||||
ansible_module.params_fail_used_invalid(invalid, state, action)
|
||||
|
||||
# Init
|
||||
|
||||
changed = False
|
||||
exit_args = {}
|
||||
|
||||
# Connect to IPA API
|
||||
with ansible_module.ipa_connect():
|
||||
|
||||
commands = []
|
||||
for name in names:
|
||||
# Make sure idview exists
|
||||
res_find = find_idview(ansible_module, name)
|
||||
|
||||
# add/del lists
|
||||
host_add, host_del = [], []
|
||||
|
||||
# Create command
|
||||
if state == "present":
|
||||
|
||||
# Generate args
|
||||
args = gen_args(description, domain_resolution_order)
|
||||
|
||||
if action == "idview":
|
||||
# Found the idview
|
||||
if res_find is not None:
|
||||
# For all settings is args, check if there are
|
||||
# different settings in the find result.
|
||||
# If yes: modify
|
||||
if not compare_args_ipa(ansible_module, args,
|
||||
res_find):
|
||||
commands.append([name, "idview_mod", args])
|
||||
else:
|
||||
commands.append([name, "idview_add", args])
|
||||
res_find = {}
|
||||
|
||||
member_args = gen_member_args(host)
|
||||
if not compare_args_ipa(ansible_module, member_args,
|
||||
res_find):
|
||||
|
||||
# Generate addition and removal lists
|
||||
host_add, host_del = gen_add_del_lists(
|
||||
host, res_find.get("appliedtohosts"))
|
||||
|
||||
elif action == "member":
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(
|
||||
msg="No idview '%s'" % name)
|
||||
|
||||
# Reduce add lists for host
|
||||
# to new entries only that are not in res_find.
|
||||
if host is not None:
|
||||
host_add = gen_add_list(
|
||||
host, res_find.get("appliedtohosts"))
|
||||
|
||||
elif state == "absent":
|
||||
if action == "idview":
|
||||
if res_find is not None:
|
||||
commands.append(
|
||||
[name, "idview_del",
|
||||
{"continue": delete_continue or False}]
|
||||
)
|
||||
|
||||
elif action == "member":
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(
|
||||
msg="No idview '%s'" % name)
|
||||
|
||||
# Reduce del lists of member_host
|
||||
# to the entries only that are in res_find.
|
||||
if host is not None:
|
||||
host_del = gen_intersection_list(
|
||||
host, res_find.get("appliedtohosts"))
|
||||
|
||||
elif state == "renamed":
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(msg="No idview '%s'" % name)
|
||||
else:
|
||||
commands.append([name, 'idview_mod', {"rename": rename}])
|
||||
|
||||
else:
|
||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||
|
||||
# Member management
|
||||
|
||||
# Add members
|
||||
if host_add:
|
||||
for host in host_add:
|
||||
if not valid_host(ansible_module, host):
|
||||
ansible_module.fail_json("Invalid host '%s'" % host)
|
||||
commands.append([name, "idview_apply", {"host": host_add}])
|
||||
|
||||
# Remove members
|
||||
if host_del:
|
||||
# idview_unapply does not have the idview name (cn) as an arg.
|
||||
# It is removing the host from any idview it is applied to.
|
||||
# But as we create the intersection with the list of hosts of
|
||||
# the idview, we emulate the correct behaviour. But this means
|
||||
# that there is no general idview_unapply like in the cli.
|
||||
commands.append([None, "idview_unapply", {"host": host_del}])
|
||||
|
||||
# Execute commands
|
||||
|
||||
changed = ansible_module.execute_ipa_commands(commands)
|
||||
|
||||
# Done
|
||||
|
||||
ansible_module.exit_json(changed=changed, **exit_args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -86,8 +86,7 @@ def find_location(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if location name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(description):
|
||||
|
||||
@@ -164,8 +164,7 @@ def find_permission(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if permission name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(right, attrs, bindtype, subtree,
|
||||
|
||||
@@ -138,8 +138,7 @@ def find_privilege(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if privilege name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -143,8 +143,7 @@ def find_role(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if role name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(module):
|
||||
|
||||
@@ -123,8 +123,7 @@ def find_selfservice(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if selfservice name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(permission, attribute):
|
||||
|
||||
@@ -202,8 +202,7 @@ def find_server(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if server name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def server_role_status(module, name):
|
||||
@@ -218,8 +217,7 @@ def server_role_status(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if server name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"][0]
|
||||
return _result["result"][0]
|
||||
|
||||
|
||||
def gen_args(location, service_weight, no_members, delete_continue,
|
||||
|
||||
@@ -414,15 +414,15 @@ def gen_args(pac_type, auth_ind, skip_host_check, force, requires_pre_auth,
|
||||
if auth_ind is not None:
|
||||
_args['krbprincipalauthind'] = auth_ind
|
||||
if skip_host_check is not None:
|
||||
_args['skip_host_check'] = (skip_host_check)
|
||||
_args['skip_host_check'] = skip_host_check
|
||||
if force is not None:
|
||||
_args['force'] = (force)
|
||||
_args['force'] = force
|
||||
if requires_pre_auth is not None:
|
||||
_args['ipakrbrequirespreauth'] = (requires_pre_auth)
|
||||
_args['ipakrbrequirespreauth'] = requires_pre_auth
|
||||
if ok_as_delegate is not None:
|
||||
_args['ipakrbokasdelegate'] = (ok_as_delegate)
|
||||
_args['ipakrbokasdelegate'] = ok_as_delegate
|
||||
if ok_to_auth_as_delegate is not None:
|
||||
_args['ipakrboktoauthasdelegate'] = (ok_to_auth_as_delegate)
|
||||
_args['ipakrboktoauthasdelegate'] = ok_to_auth_as_delegate
|
||||
|
||||
return _args
|
||||
|
||||
@@ -433,9 +433,9 @@ def gen_args_smb(netbiosname, ok_as_delegate, ok_to_auth_as_delegate):
|
||||
if netbiosname is not None:
|
||||
_args['ipantflatname'] = netbiosname
|
||||
if ok_as_delegate is not None:
|
||||
_args['ipakrbokasdelegate'] = (ok_as_delegate)
|
||||
_args['ipakrbokasdelegate'] = ok_as_delegate
|
||||
if ok_to_auth_as_delegate is not None:
|
||||
_args['ipakrboktoauthasdelegate'] = (ok_to_auth_as_delegate)
|
||||
_args['ipakrboktoauthasdelegate'] = ok_to_auth_as_delegate
|
||||
|
||||
return _args
|
||||
|
||||
|
||||
@@ -145,8 +145,7 @@ def find_servicedelegationrule(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if servicedelegationrule name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def check_targets(module, targets):
|
||||
|
||||
@@ -121,8 +121,7 @@ def find_servicedelegationtarget(module, name):
|
||||
except Exception: # pylint: disable=broad-except
|
||||
# An exception is raised if servicedelegationtarget name is not found.
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
@@ -122,8 +122,7 @@ def find_sudocmdgroup(module, name):
|
||||
_result = module.ipa_command("sudocmdgroup_show", name, args)
|
||||
except ipalib_errors.NotFound:
|
||||
return None
|
||||
else:
|
||||
return _result["result"]
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(description, nomembers):
|
||||
|
||||
@@ -977,12 +977,14 @@ def main():
|
||||
changed = 'Archived data into' in result['summary']
|
||||
elif command == 'vault_retrieve':
|
||||
if 'result' not in result:
|
||||
# pylint: disable=W0012,broad-exception-raised
|
||||
raise Exception("No result obtained.")
|
||||
if "data" in result["result"]:
|
||||
data_return = exit_args.setdefault("vault", {})
|
||||
data_return["data"] = result["result"]["data"]
|
||||
else:
|
||||
if not datafile_out:
|
||||
# pylint: disable=W0012,broad-exception-raised
|
||||
raise Exception("No data retrieved.")
|
||||
changed = False
|
||||
else:
|
||||
@@ -993,7 +995,7 @@ def main():
|
||||
changed = True
|
||||
except ipalib_errors.EmptyModlist:
|
||||
result = {}
|
||||
except Exception as exception:
|
||||
except Exception as exception: # pylint: disable=broad-except
|
||||
ansible_module.fail_json(
|
||||
msg="%s: %s: %s" % (command, name, str(exception)))
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
-r requirements-tests.txt
|
||||
ipdb==0.13.4
|
||||
pre-commit==2.20.0
|
||||
flake8==5.0.3
|
||||
flake8-bugbear==22.10.27
|
||||
pylint==2.14.4
|
||||
wrapt == 1.14.0
|
||||
pydocstyle==6.0.0
|
||||
yamllint==1.28.0
|
||||
ansible-lint==6.6.1
|
||||
flake8==6.0.0
|
||||
flake8-bugbear
|
||||
pylint==2.17.2
|
||||
wrapt==1.14.1
|
||||
pydocstyle==6.3.0
|
||||
yamllint==1.32.0
|
||||
ansible-lint
|
||||
|
||||
@@ -33,6 +33,7 @@ Supported Distributions
|
||||
-----------------------
|
||||
|
||||
* RHEL/CentOS 7.6+
|
||||
* CentOS Stream 8+
|
||||
* Fedora 26+
|
||||
* Ubuntu 16.04 and 18.04
|
||||
|
||||
@@ -41,7 +42,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -6,7 +6,7 @@ galaxy_info:
|
||||
description: A role to backup and restore an IPA server
|
||||
company: Red Hat, Inc
|
||||
license: GPLv3
|
||||
min_ansible_version: "2.8"
|
||||
min_ansible_version: "2.13"
|
||||
platforms:
|
||||
- name: Fedora
|
||||
versions:
|
||||
|
||||
@@ -24,15 +24,17 @@ Supported Distributions
|
||||
-----------------------
|
||||
|
||||
* RHEL/CentOS 7.4+
|
||||
* CentOS Stream 8+
|
||||
* Fedora 26+
|
||||
* Ubuntu
|
||||
* Debian
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -132,7 +132,7 @@ def main():
|
||||
else:
|
||||
get_ca_certs(fstore, options, servers[0], basedn, realm)
|
||||
changed = True
|
||||
del os.environ['KRB5_CONFIG']
|
||||
os.environ.pop('KRB5_CONFIG', None)
|
||||
except errors.FileError as e:
|
||||
module.fail_json(msg='%s' % e)
|
||||
except Exception as e:
|
||||
|
||||
@@ -123,7 +123,7 @@ def temp_kdestroy(ccache_dir, ccache_name):
|
||||
"""Destroy temporary ticket and remove temporary ccache."""
|
||||
if ccache_name is not None:
|
||||
run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False)
|
||||
del os.environ['KRB5CCNAME']
|
||||
os.environ.pop('KRB5CCNAME', None)
|
||||
if ccache_dir is not None:
|
||||
shutil.rmtree(ccache_dir, ignore_errors=True)
|
||||
|
||||
|
||||
@@ -272,7 +272,7 @@ def main():
|
||||
get_ca_cert(fstore, options, servers[0], basedn)
|
||||
else:
|
||||
get_ca_certs(fstore, options, servers[0], basedn, realm)
|
||||
del os.environ['KRB5_CONFIG']
|
||||
os.environ.pop('KRB5_CONFIG', None)
|
||||
except errors.FileError as e:
|
||||
module.fail_json(msg='%s' % e)
|
||||
except Exception as e:
|
||||
|
||||
@@ -6,7 +6,7 @@ galaxy_info:
|
||||
description: A role to join a machine to an IPA domain
|
||||
company: Red Hat, Inc
|
||||
license: GPLv3
|
||||
min_ansible_version: "2.8"
|
||||
min_ansible_version: "2.13"
|
||||
platforms:
|
||||
- name: Fedora
|
||||
versions:
|
||||
|
||||
@@ -307,8 +307,7 @@ try:
|
||||
|
||||
else:
|
||||
# IPA version < 4.4
|
||||
|
||||
raise Exception("freeipa version '%s' is too old" % VERSION)
|
||||
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
|
||||
|
||||
except ImportError as _err:
|
||||
ANSIBLE_IPA_CLIENT_MODULE_IMPORT_ERROR = str(_err)
|
||||
|
||||
@@ -27,6 +27,7 @@ Supported Distributions
|
||||
-----------------------
|
||||
|
||||
* RHEL/CentOS 7.6+
|
||||
* CentOS Stream 8+
|
||||
* Fedora 26+
|
||||
* Ubuntu 16.04 and 18.04
|
||||
|
||||
@@ -35,7 +36,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -669,7 +669,7 @@ def main():
|
||||
raise errors.ACIError(info="Not authorized")
|
||||
|
||||
if installer._ccache is None:
|
||||
del os.environ['KRB5CCNAME']
|
||||
os.environ.pop('KRB5CCNAME', None)
|
||||
else:
|
||||
os.environ['KRB5CCNAME'] = installer._ccache
|
||||
|
||||
@@ -873,7 +873,7 @@ def main():
|
||||
if add_to_ipaservers:
|
||||
# use user's credentials when the server host is not ipaservers
|
||||
if installer._ccache is None:
|
||||
del os.environ['KRB5CCNAME']
|
||||
os.environ.pop('KRB5CCNAME', None)
|
||||
else:
|
||||
os.environ['KRB5CCNAME'] = installer._ccache
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ galaxy_info:
|
||||
description: A role to setup an IPA domain replica
|
||||
company: Red Hat, Inc
|
||||
license: GPLv3
|
||||
min_ansible_version: "2.8"
|
||||
min_ansible_version: "2.13"
|
||||
platforms:
|
||||
- name: Fedora
|
||||
versions:
|
||||
|
||||
@@ -171,8 +171,7 @@ try:
|
||||
|
||||
else:
|
||||
# IPA version < 4.6
|
||||
|
||||
raise Exception("freeipa version '%s' is too old" % VERSION)
|
||||
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
|
||||
|
||||
except ImportError as _err:
|
||||
ANSIBLE_IPA_REPLICA_MODULE_IMPORT_ERROR = str(_err)
|
||||
|
||||
@@ -24,6 +24,7 @@ Supported Distributions
|
||||
-----------------------
|
||||
|
||||
* RHEL/CentOS 7.6+
|
||||
* CentOS Stream 8+
|
||||
* Fedora 26+
|
||||
* Ubuntu 16.04 and 18.04
|
||||
|
||||
@@ -32,7 +33,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -108,7 +108,7 @@ def temp_kdestroy(ccache_dir, ccache_name):
|
||||
"""Destroy temporary ticket and remove temporary ccache."""
|
||||
if ccache_name is not None:
|
||||
run([paths.KDESTROY, '-c', ccache_name], raiseonerr=False)
|
||||
del os.environ['KRB5CCNAME']
|
||||
os.environ.pop('KRB5CCNAME', None)
|
||||
if ccache_dir is not None:
|
||||
shutil.rmtree(ccache_dir, ignore_errors=True)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ galaxy_info:
|
||||
description: A role to setup an iPA domain server
|
||||
company: Red Hat, Inc
|
||||
license: GPLv3
|
||||
min_ansible_version: "2.8"
|
||||
min_ansible_version: "2.13"
|
||||
platforms:
|
||||
- name: Fedora
|
||||
versions:
|
||||
|
||||
@@ -212,8 +212,7 @@ try:
|
||||
|
||||
else:
|
||||
# IPA version < 4.5
|
||||
|
||||
raise Exception("freeipa version '%s' is too old" % VERSION)
|
||||
raise RuntimeError("freeipa version '%s' is too old" % VERSION)
|
||||
|
||||
except ImportError as _err:
|
||||
ANSIBLE_IPA_SERVER_MODULE_IMPORT_ERROR = str(_err)
|
||||
|
||||
@@ -24,6 +24,7 @@ Supported Distributions
|
||||
-----------------------
|
||||
|
||||
* RHEL/CentOS 7.6+
|
||||
* CentOS Stream 8+
|
||||
* Fedora 26+
|
||||
|
||||
|
||||
@@ -31,7 +32,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.8+
|
||||
* Ansible version: 2.13+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user