mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-27 13:53:06 +00:00
Compare commits
139 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62fd1551eb | ||
|
|
a24e90ad0c | ||
|
|
0b9718b3ec | ||
|
|
226b8c4d75 | ||
|
|
2f34e1ac6a | ||
|
|
e4ea7c8983 | ||
|
|
b3f024869c | ||
|
|
355438cea9 | ||
|
|
30b72422d9 | ||
|
|
10a84429e2 | ||
|
|
bf384ab1aa | ||
|
|
536b7cb5f3 | ||
|
|
17b100baec | ||
|
|
1488fb7b5e | ||
|
|
a733c031b0 | ||
|
|
ff1a026ef4 | ||
|
|
fa5d056e72 | ||
|
|
e0e3cb041e | ||
|
|
b54aaf127d | ||
|
|
4e16126b29 | ||
|
|
ed62c2f1bf | ||
|
|
dc9b0ce4e8 | ||
|
|
aa3bf1f015 | ||
|
|
f0aa531b28 | ||
|
|
6407fd8b2e | ||
|
|
2a1be13d3e | ||
|
|
2afca1fa5e | ||
|
|
2a40e42b0c | ||
|
|
8a33941188 | ||
|
|
0aef995bbe | ||
|
|
e75efb7a13 | ||
|
|
ed44344519 | ||
|
|
b186a1f28f | ||
|
|
d307635c38 | ||
|
|
74f3817531 | ||
|
|
97378c38cf | ||
|
|
6f15cd093a | ||
|
|
52f7f7848e | ||
|
|
fdd45cc475 | ||
|
|
a1cad32a46 | ||
|
|
7036fa3e1b | ||
|
|
95d935f185 | ||
|
|
dd3bc4fcdd | ||
|
|
c405229553 | ||
|
|
3fa3bf0822 | ||
|
|
7cef44c01d | ||
|
|
cd7d19bfeb | ||
|
|
0e748d372a | ||
|
|
e24340447d | ||
|
|
092ad81d03 | ||
|
|
4d22e917df | ||
|
|
a04a357b6a | ||
|
|
2081a1a8dd | ||
|
|
d1dfdc38c9 | ||
|
|
9fc1b043c1 | ||
|
|
bdf1efde80 | ||
|
|
513d5ee46b | ||
|
|
cd440a2049 | ||
|
|
e2317f304c | ||
|
|
7a23c668fc | ||
|
|
91d818b334 | ||
|
|
902d8b7238 | ||
|
|
d553f9a0b1 | ||
|
|
9cfe835b03 | ||
|
|
668830fc94 | ||
|
|
5ae39ec9de | ||
|
|
3f59332d99 | ||
|
|
30c405cb36 | ||
|
|
7275bbf6a3 | ||
|
|
6df89ad7db | ||
|
|
c5fa54f2cf | ||
|
|
8e3102270d | ||
|
|
89cfb5f4c4 | ||
|
|
5fb22581bb | ||
|
|
6976ef57eb | ||
|
|
0d9b164358 | ||
|
|
8b03e4d007 | ||
|
|
ef73a85320 | ||
|
|
5b3a4729f0 | ||
|
|
7245339934 | ||
|
|
638422e113 | ||
|
|
432376524c | ||
|
|
86701caf8b | ||
|
|
d1857c18ac | ||
|
|
edbdd3af79 | ||
|
|
2d3da2d72c | ||
|
|
329c16f742 | ||
|
|
66c0be06d0 | ||
|
|
f04c90f4db | ||
|
|
dfa4bcb68f | ||
|
|
b1328ba7d5 | ||
|
|
fe58f3a8ba | ||
|
|
4dc6192640 | ||
|
|
e9435410b2 | ||
|
|
de6a0429a0 | ||
|
|
40d85f83e4 | ||
|
|
678927f35c | ||
|
|
f0e6d0c89f | ||
|
|
c095c24950 | ||
|
|
34dc75802c | ||
|
|
feb33e4e3a | ||
|
|
3c50a8121f | ||
|
|
e8688d4cf5 | ||
|
|
d540be425a | ||
|
|
c1d7ed1df6 | ||
|
|
0fc8ddf450 | ||
|
|
012f0deb00 | ||
|
|
f27b0e3011 | ||
|
|
8b4b22dd00 | ||
|
|
91c4b83311 | ||
|
|
6925503a10 | ||
|
|
0da0b22ae7 | ||
|
|
f5f454915c | ||
|
|
8581b79eba | ||
|
|
a9602431ce | ||
|
|
9195494f37 | ||
|
|
81abf6889b | ||
|
|
81906edec6 | ||
|
|
5071653db3 | ||
|
|
df4ec30a51 | ||
|
|
73160a037b | ||
|
|
b7ed9ecfd5 | ||
|
|
a4f608854d | ||
|
|
8e6c5e566d | ||
|
|
431dc8667a | ||
|
|
bc16ccaef7 | ||
|
|
227c95e62e | ||
|
|
5abb515c92 | ||
|
|
1c4b50fa51 | ||
|
|
8fc2de1673 | ||
|
|
8d74fe34ef | ||
|
|
87ad46f7a4 | ||
|
|
4c3f4e6f7d | ||
|
|
489f4d5784 | ||
|
|
29fc03c625 | ||
|
|
651337541a | ||
|
|
e61b8db66c | ||
|
|
2dc1deeb87 | ||
|
|
82a53b9ae4 |
18
.github/workflows/docs.yml
vendored
18
.github/workflows/docs.yml
vendored
@@ -5,7 +5,7 @@ on:
|
||||
- pull_request
|
||||
jobs:
|
||||
check_docs_oldest_supported:
|
||||
name: Check Ansible Documentation with ansible-core 2.13.
|
||||
name: Check Ansible Documentation with ansible-core 2.16.
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
@@ -14,15 +14,15 @@ jobs:
|
||||
- uses: actions/setup-python@v5.1.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install Ansible 2.13
|
||||
- name: Install Ansible 2.16
|
||||
run: |
|
||||
python -m pip install "ansible-core >=2.13,<2.14"
|
||||
python -m pip install "ansible-core >=2.16,<2.17"
|
||||
- name: Run ansible-doc-test
|
||||
run: |
|
||||
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
|
||||
|
||||
check_docs_previous:
|
||||
name: Check Ansible Documentation with ansible-core 2.14.
|
||||
name: Check Ansible Documentation with ansible-core 2.18.
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
@@ -31,15 +31,15 @@ jobs:
|
||||
- uses: actions/setup-python@v5.1.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install Ansible 2.14
|
||||
- name: Install Ansible 2.18
|
||||
run: |
|
||||
python -m pip install "ansible-core >=2.14,<2.15"
|
||||
python -m pip install "ansible-core >=2.18,<2.19"
|
||||
- name: Run ansible-doc-test
|
||||
run: |
|
||||
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
|
||||
|
||||
check_docs_current:
|
||||
name: Check Ansible Documentation with ansible-core 2.15.
|
||||
name: Check Ansible Documentation with ansible-core 2.19.
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.1
|
||||
@@ -48,9 +48,9 @@ jobs:
|
||||
- uses: actions/setup-python@v5.1.0
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install Ansible 2.15
|
||||
- name: Install Ansible 2.20
|
||||
run: |
|
||||
python -m pip install "ansible-core >=2.15,<2.16"
|
||||
python -m pip install "ansible-core <2.20"
|
||||
- name: Run ansible-doc-test
|
||||
run: |
|
||||
ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
|
||||
|
||||
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
@@ -13,12 +13,12 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v5.1.0
|
||||
with:
|
||||
python-version: "3.x"
|
||||
python-version: "3.13"
|
||||
- name: Run ansible-lint
|
||||
run: |
|
||||
pip install "ansible-core>=2.16,<2.17" 'ansible-lint==6.22'
|
||||
utils/build-galaxy-release.sh -ki
|
||||
cd .galaxy-build
|
||||
utils/build-collection.sh -ki rpm
|
||||
cd .collection-build
|
||||
ansible-lint --profile production --exclude tests/integration/ --exclude tests/unit/ --parseable --nocolor
|
||||
|
||||
yamllint:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
repos:
|
||||
- repo: https://github.com/ansible/ansible-lint.git
|
||||
rev: v24.5.0
|
||||
rev: v25.9.2
|
||||
hooks:
|
||||
- id: ansible-lint
|
||||
always_run: false
|
||||
@@ -21,16 +21,16 @@ repos:
|
||||
--parseable
|
||||
--nocolor
|
||||
- repo: https://github.com/adrienverge/yamllint.git
|
||||
rev: v1.35.1
|
||||
rev: v1.37.1
|
||||
hooks:
|
||||
- id: yamllint
|
||||
files: \.(yaml|yml)$
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 7.0.0
|
||||
rev: 7.3.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
- repo: https://github.com/pycqa/pylint
|
||||
rev: v3.2.2
|
||||
rev: v4.0.2
|
||||
hooks:
|
||||
- id: pylint
|
||||
args:
|
||||
|
||||
@@ -20,4 +20,9 @@ rules:
|
||||
max: 160
|
||||
# Disabled rules
|
||||
indentation: disable
|
||||
comments: disable
|
||||
comments:
|
||||
min-spaces-from-content: 1
|
||||
comments-indentation: disable
|
||||
octal-values:
|
||||
forbid-implicit-octal: true
|
||||
forbid-explicit-octal: true
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**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.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**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.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**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.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
* Some tool to generate a certificate signing request (CSR) might be needed, like `openssl`.
|
||||
|
||||
**Node**
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
@@ -145,7 +145,7 @@ Variable | Description | Required
|
||||
`selinuxusermaporder` \| `ipaselinuxusermaporder`| Set ordered list in increasing priority of SELinux users | no
|
||||
`selinuxusermapdefault`\| `ipaselinuxusermapdefault` | Set default SELinux user when no match is found in SELinux map rule | no
|
||||
`pac_type` \| `ipakrbauthzdata` | set default types of PAC supported for services (choices: `MS-PAC`, `PAD`, `nfs:NONE`). Use `""` to clear this variable. | no
|
||||
`user_auth_type` \| `ipauserauthtype` | set default types of supported user authentication (choices: `password`, `radius`, `otp`, `pkinit`, `hardened`, `idp`, `disabled`, `""`). An additional check ensures that only types can be used that are supported by the IPA version. Use `""` to clear this variable. | no
|
||||
`user_auth_type` \| `ipauserauthtype` | set default types of supported user authentication (choices: `password`, `radius`, `otp`, `pkinit`, `hardened`, `idp`, `passkey`, `disabled`, `""`). An additional check ensures that only types can be used that are supported by the IPA version. Use `""` to clear this variable. | no
|
||||
`domain_resolution_order` \| `ipadomainresolutionorder` | Set list of domains used for short name qualification | no
|
||||
`ca_renewal_master_server` \| `ipacarenewalmasterserver`| Renewal master for IPA certificate authority. | no
|
||||
`enable_sid` | New users and groups automatically get a SID assigned. Cannot be deactivated once activated. Requires IPA 4.9.8+. (bool) | no
|
||||
|
||||
@@ -23,7 +23,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**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.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -23,7 +23,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
|
||||
**Node**
|
||||
|
||||
@@ -8,8 +8,12 @@ The group module allows to ensure presence and absence of groups and members of
|
||||
|
||||
The group module is as compatible as possible to the Ansible upstream `ipa_group` module, but additionally offers to add users to a group and also to remove users from a group.
|
||||
|
||||
## Note
|
||||
Ensuring presence (adding) of several groups with mixed types (`external`, `nonposix` and `posix`) requires a fix in FreeIPA. The module implements a workaround to automatically use `client` context if the fix is not present in the target node FreeIPA and if more than one group is provided to the task using the `groups` parameter. If `ipaapi_context` is forced to be `server`, the module will fail in this case.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
* Ensuring presence (adding) of several groups with mixed types (`external`, `nonposix` and `posix`) requires a fix in FreeIPA. The module implements a workaround to automatically use `client` context if the fix is not present in the target node FreeIPA and if more than one group is provided to the task using the `groups` parameter. If `ipaapi_context` is forced to be `server`, the module will fail in this case.
|
||||
* Using `externalmember` or `idoverrideuser` is only supported with `ipaapi_context: server`. With 'client' context, module execution will fail.
|
||||
|
||||
|
||||
Features
|
||||
@@ -29,7 +33,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
@@ -213,7 +217,7 @@ Example playbook to add members from a trusted realm to an external group:
|
||||
---
|
||||
- name: Playbook to handle groups.
|
||||
hosts: ipaserver
|
||||
|
||||
|
||||
tasks:
|
||||
- name: Create an external group and add members from a trust to it.
|
||||
ipagroup:
|
||||
@@ -276,6 +280,7 @@ Example playbook to ensure groups are absent:
|
||||
state: absent
|
||||
```
|
||||
|
||||
|
||||
Variables
|
||||
=========
|
||||
|
||||
@@ -299,8 +304,8 @@ Variable | Description | Required
|
||||
`service` | List of service name strings assigned to this group. Only usable with IPA versions 4.7 and up. | no
|
||||
`membermanager_user` | List of member manager users assigned to this group. Only usable with IPA versions 4.8.4 and up. | no
|
||||
`membermanager_group` | List of member manager groups assigned to this group. Only usable with IPA versions 4.8.4 and up. | no
|
||||
`externalmember` \| `ipaexternalmember` \| `external_member`| List of members of a trusted domain in DOM\\name or name@domain form. | no
|
||||
`idoverrideuser` | List of user ID overrides to manage. Only usable with IPA versions 4.8.7 and up.| no
|
||||
`externalmember` \| `ipaexternalmember` \| `external_member`| List of members of a trusted domain in DOM\\name or name@domain form. Requires "server" context. | no
|
||||
`idoverrideuser` | List of user ID overrides to manage. Only usable with IPA versions 4.8.7 and up. Requires "server" context. | no
|
||||
`rename` \| `new_name` | Rename the user object to the new name string. Only usable with `state: renamed`. | no
|
||||
`action` | Work on group or member level. It can be on of `member` or `group` and defaults to `group`. | no
|
||||
`state` | The state to ensure. It can be one of `present`, `absent` or `renamed`, default: `present`. | yes
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
@@ -354,7 +354,7 @@ Variable | Description | Required
|
||||
`mac_address` \| `macaddress` | List of hardware MAC addresses. | no
|
||||
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys | no
|
||||
`userclass` \| `class` | Host category (semantics placed on this attribute are for local interpretation) | no
|
||||
`auth_ind` \| `krbprincipalauthind` | Defines an allow list for Authentication Indicators. Use 'otp' to allow OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA authentications. Use empty string to reset auth_ind to the initial value. Other values may be used for custom configurations. An additional check ensures that only types can be used that are supported by the IPA version. Choices: ["radius", "otp", "pkinit", "hardened", "idp", ""] | no
|
||||
`auth_ind` \| `krbprincipalauthind` | Defines an allow list for Authentication Indicators. Use 'otp' to allow OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA authentications. Use empty string to reset auth_ind to the initial value. Other values may be used for custom configurations. An additional check ensures that only types can be used that are supported by the IPA version. Choices: ["radius", "otp", "pkinit", "hardened", "idp", "passkey", ""] | no
|
||||
`requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service (bool) | no
|
||||
`ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service (bool) | no
|
||||
`ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client (bool) | no
|
||||
|
||||
@@ -26,7 +26,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -29,7 +29,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -29,7 +29,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -37,7 +37,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
@@ -68,23 +68,6 @@ Example playbook to ensure a local domain idrange is present:
|
||||
name: local_domain_id_range
|
||||
base_id: 150000
|
||||
range_size: 200000
|
||||
```
|
||||
|
||||
Example playbook to ensure a local domain idrange is present, with RID and secondary RID base values:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA idrange.
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Ensure local idrange is present
|
||||
ipaidrange:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: local_domain_id_range
|
||||
base_id: 150000000
|
||||
range_size: 200000
|
||||
rid_base: 1000000
|
||||
secondary_rid_base: 200000000
|
||||
```
|
||||
@@ -172,8 +155,8 @@ Variable | Description | Required
|
||||
`name` \| `cn` | The list of idrange name strings. | yes
|
||||
`base_id` \| `ipabaseid` | First Posix ID of the range. (int) | yes, if `state: present`
|
||||
`range_size` \| `ipaidrangesize` | Number of IDs in the range. (int) | yes, if `state: present`
|
||||
`rid_base` \| `ipabaserid` | First RID of the corresponding RID range. (int) | no
|
||||
`secondary_rid_base` \| `ipasecondarybaserid` | First RID of the secondary RID range. (int) | no
|
||||
`rid_base` \| `ipabaserid` | First RID of the corresponding RID range. (int) | yes, if `idrange_type: ipa-local` and `state: present` |
|
||||
`secondary_rid_base` \| `ipasecondarybaserid` | First RID of the secondary RID range. (int) | yes, if `idrange_type: ipa-local` and `state: present` |
|
||||
`dom_sid` \| `ipanttrusteddomainsid` | Domain SID of the trusted domain. | no
|
||||
`idrange_type` \| `iparangetype` | ID range type, one of `ipa-ad-trust`, `ipa-ad-trust-posix`, `ipa-local`. Only valid if idrange does not exist. | no
|
||||
`dom_name` \| `ipanttrusteddomainname` | Name of the trusted domain. Can only be used when `ipaapi_context: server`. | no
|
||||
|
||||
@@ -29,7 +29,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
88
README-passkeyconfig.md
Normal file
88
README-passkeyconfig.md
Normal file
@@ -0,0 +1,88 @@
|
||||
Passkeyconfig module
|
||||
============
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The passkeyconfig module allows to manage FreeIPA passkey configuration settings.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Passkeyconfig management
|
||||
|
||||
|
||||
Supported FreeIPA Versions
|
||||
--------------------------
|
||||
|
||||
FreeIPA versions 4.4.0 and up are supported by the ipapasskeyconfig module.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Example inventory file
|
||||
|
||||
```ini
|
||||
[ipaserver]
|
||||
ipaserver.test.local
|
||||
```
|
||||
|
||||
|
||||
By default, user verification for passkey authentication is turned on (`true`). Example playbook to ensure that the requirement for user verification for passkey authentication is turned off:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA passkeyconfig.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure require_user_verification is false
|
||||
ipapasskeyconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
require_user_verification: false
|
||||
```
|
||||
|
||||
|
||||
Example playbook to get current passkeyconfig:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to get IPA passkeyconfig.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Retrieve current passkey configuration
|
||||
ipapasskeyconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
```
|
||||
|
||||
|
||||
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
|
||||
`require_user_verification` \| `iparequireuserverification` | Require user verification for passkey authentication. (bool) | no
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
Rafael Guterres Jeffman
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
@@ -230,6 +230,8 @@ Example playbook to ensure that different members are not associated with a role
|
||||
- User Administrators
|
||||
service:
|
||||
- service01
|
||||
sysaccount:
|
||||
- my-app
|
||||
action: member
|
||||
state: absent
|
||||
```
|
||||
@@ -253,7 +255,8 @@ Variable | Description | Required
|
||||
`host` | List of hosts to be assigned or not assigned to the role. | no
|
||||
`hostgroup` | List of hostgroups to be assigned or not assigned to the role. | no
|
||||
`service` | List of services to be assigned or not assigned to the role. | no
|
||||
`action` | Work on role or member level. It can be on of `member` or `role` and defaults to `role`. | no
|
||||
`sysaccount` | List of sysaccounts to be assigned or not assigned to the role. | no
|
||||
`action` | Work on role or member level. It can be one of `member` or `role` and defaults to `role`. | no
|
||||
`state` | The state to ensure. It can be one of `present`, `absent`, default: `present`. | no
|
||||
|
||||
|
||||
@@ -261,3 +264,4 @@ Authors
|
||||
=======
|
||||
|
||||
Rafael Jeffman
|
||||
Thomas Woerner
|
||||
|
||||
@@ -23,7 +23,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -25,7 +25,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FReeIPA version (see above)
|
||||
@@ -361,7 +361,7 @@ Variable | Description | Required
|
||||
-------- | ----------- | --------
|
||||
`certificate` \| `usercertificate` | Base-64 encoded service certificate. | no
|
||||
`pac_type` \| `ipakrbauthzdata` | Supported PAC type. It can be one of `MS-PAC`, `PAD`, or `NONE`. Use empty string to reset pac_type to the initial value. | no
|
||||
`auth_ind` \| `krbprincipalauthind` | Defines an allow list for Authentication Indicators. It can be any of `otp`, `radius`, `pkinit`, `hardened`, `idp` or `""`. An additional check ensures that only types can be used that are supported by the IPA version. Use empty string to reset auth_ind to the initial value. | no
|
||||
`auth_ind` \| `krbprincipalauthind` | Defines an allow list for Authentication Indicators. It can be any of `otp`, `radius`, `pkinit`, `hardened`, `idp`, `passkey` or `""`. An additional check ensures that only types can be used that are supported by the IPA version. Use empty string to reset auth_ind to the initial value. | no
|
||||
`requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service. Default to true. (bool) | no
|
||||
`ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service. Default to false. (bool) | no
|
||||
`ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client. Default to false. (bool) | no
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
196
README-sysaccount.md
Normal file
196
README-sysaccount.md
Normal file
@@ -0,0 +1,196 @@
|
||||
Sysaccount module
|
||||
============
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
The sysaccount module allows to ensure presence and absence of system accounts.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Sysaccount management
|
||||
|
||||
|
||||
Supported FreeIPA Versions
|
||||
--------------------------
|
||||
|
||||
FreeIPA versions 4.4.0 and up are supported by the ipasysaccount module.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Example inventory file
|
||||
|
||||
```ini
|
||||
[ipaserver]
|
||||
ipaserver.test.local
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure sysaccount "my-app" is present with random password:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA sysaccount.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure sysaccount "my-app" is present with random password
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
random: true
|
||||
register: result
|
||||
|
||||
- name: Print generated random password
|
||||
debug:
|
||||
var: result.sysaccount.randompassword
|
||||
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure sysaccount "my-app" is present with given password:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA sysaccount.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure sysaccount "my-app" is present with given password
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
password: SomeAPPpassword
|
||||
```
|
||||
|
||||
|
||||
Example playbook to make sure sysaccount "my-app" is absent:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA sysaccount.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure sysaccount "my-app" is absent
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
state: absent
|
||||
```
|
||||
|
||||
Example playbook to ensure existing sysaccount my-app is privileged
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA sysaccount.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure existing sysaccount my-app is privileged
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
privileged: true
|
||||
```
|
||||
|
||||
Example playbook to ensure existing sysaccount my-app is not privileged
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA sysaccount.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure existing sysaccount my-app is not privileged
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
privileged: false
|
||||
```
|
||||
|
||||
Example playbook to ensure existing sysaccount my-app is disabled
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA sysaccount.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure existing sysaccount my-app is disabled
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
state: disabled
|
||||
```
|
||||
|
||||
Example playbook to ensure existing sysaccount my-app is enabled
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to manage IPA sysaccount.
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure existing sysaccount my-app is enabled
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
state: enabled
|
||||
```
|
||||
|
||||
|
||||
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` \| `login` | The list of sysaccount name strings - internally uid. (list of strings) | yes
|
||||
`description` | A description for the sysaccount. (string) | no
|
||||
`privileged` | Allow password updates without reset. This flag is not replicated. It is needed to set privileged on all servers, where it is needed. (bool) | no
|
||||
`random` | Generate a random user password. (bool) | no
|
||||
`password` \| `userpassword` | Set the password. (string) | no
|
||||
`update_password` | Set password for a sysaccount in present state only on creation or always. It can be one of `always` or `on_create` and defaults to `always`. | no
|
||||
`state` | The state to ensure. It can be one of `present`, `absent`, 'enabled', 'disabled', default: `present`. | no
|
||||
|
||||
|
||||
Return Values
|
||||
=============
|
||||
|
||||
There are only return values if a random passwords has been generated.
|
||||
|
||||
Variable | Description | Returned When
|
||||
-------- | ----------- | -------------
|
||||
`sysaccount` | Sysaccount dict (dict) <br>Options: | Always
|
||||
| `randompassword` - The generated random password | If random is yes and sysaccount did not exist or update_password is yes
|
||||
|
||||
|
||||
|
||||
Authors
|
||||
=======
|
||||
|
||||
Thomas Woerner
|
||||
@@ -22,7 +22,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
@@ -21,7 +21,7 @@ Requirements
|
||||
|
||||
**Controller**
|
||||
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
@@ -452,7 +452,7 @@ Variable | Description | Required
|
||||
`manager` | List of manager user names. | no
|
||||
`carlicense` | List of car licenses. | no
|
||||
`sshpubkey` \| `ipasshpubkey` | List of SSH public keys. | no
|
||||
`userauthtype` \| `ipauserauthtype` | List of supported user authentication types. Choices: `password`, `radius`, `otp`, `pkinit`, `hardened`, `idp` and `""`. An additional check ensures that only types can be used that are supported by the IPA version. Use empty string to reset userauthtype to the initial value. | no
|
||||
`userauthtype` \| `ipauserauthtype` | List of supported user authentication types. Choices: `password`, `radius`, `otp`, `pkinit`, `hardened`, `idp`, `passkey` and `""`. An additional check ensures that only types can be used that are supported by the IPA version. Use empty string to reset userauthtype to the initial value. | no
|
||||
`userclass` | User category. (semantics placed on this attribute are for local interpretation). | no
|
||||
`radius` | RADIUS proxy configuration | no
|
||||
`radiususer` | RADIUS proxy username | no
|
||||
|
||||
@@ -24,7 +24,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
|
||||
10
README.md
10
README.md
@@ -38,6 +38,7 @@ Features
|
||||
* Modules for idview management
|
||||
* Modules for location management
|
||||
* Modules for netgroup management
|
||||
* Modules for passkeyconfig management
|
||||
* Modules for permission management
|
||||
* Modules for privilege management
|
||||
* Modules for pwpolicy management
|
||||
@@ -50,6 +51,7 @@ Features
|
||||
* Modules for sudocmd management
|
||||
* Modules for sudocmdgroup management
|
||||
* Modules for sudorule management
|
||||
* Modules for sysaccount management
|
||||
* Modules for topology management
|
||||
* Modules for trust management
|
||||
* Modules for user management
|
||||
@@ -66,7 +68,7 @@ Supported Distributions
|
||||
-----------------------
|
||||
|
||||
* RHEL/CentOS 7.4+
|
||||
* Fedora 26+
|
||||
* Fedora 40+
|
||||
* Ubuntu
|
||||
* Debian 10+ (ipaclient only, no server or replica!)
|
||||
|
||||
@@ -74,7 +76,7 @@ Requirements
|
||||
------------
|
||||
|
||||
**Controller**
|
||||
* Ansible version: 2.15+
|
||||
* Ansible version: 2.14+
|
||||
|
||||
**Node**
|
||||
* Supported FreeIPA version (see above)
|
||||
@@ -125,7 +127,7 @@ ansible-freeipa/plugins/module_utils to ~/.ansible/plugins/
|
||||
|
||||
**RPM package**
|
||||
|
||||
There are RPM packages available for Fedora 29+. These are installing the roles and modules into the global Ansible directories for `roles`, `plugins/modules` and `plugins/module_utils` in the `/usr/share/ansible` directory. Therefore is it possible to use the roles and modules without adapting the names like it is done in the example playbooks.
|
||||
There are RPM packages available for Fedora. These are installing the roles and modules into the global Ansible directories for `roles`, `plugins/modules` and `plugins/module_utils` in the `/usr/share/ansible` directory. Therefore is it possible to use the roles and modules without adapting the names like it is done in the example playbooks.
|
||||
|
||||
**Ansible Galaxy**
|
||||
|
||||
@@ -453,6 +455,7 @@ Modules in plugin/modules
|
||||
* [idview](README-idview.md)
|
||||
* [ipalocation](README-location.md)
|
||||
* [ipanetgroup](README-netgroup.md)
|
||||
* [ipapasskeyconfig](README-passkeyconfig.md)
|
||||
* [ipapermission](README-permission.md)
|
||||
* [ipaprivilege](README-privilege.md)
|
||||
* [ipapwpolicy](README-pwpolicy.md)
|
||||
@@ -465,6 +468,7 @@ Modules in plugin/modules
|
||||
* [ipasudocmd](README-sudocmd.md)
|
||||
* [ipasudocmdgroup](README-sudocmdgroup.md)
|
||||
* [ipasudorule](README-sudorule.md)
|
||||
* [ipasysaccount](README-sysaccount.md)
|
||||
* [ipatopologysegment](README-topology.md)
|
||||
* [ipatopologysuffix](README-topology.md)
|
||||
* [ipatrust](README-trust.md)
|
||||
|
||||
@@ -3,13 +3,13 @@ trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-20.04'
|
||||
vmImage: 'ubuntu-24.04'
|
||||
|
||||
variables:
|
||||
ansible_version: "-core >=2.16,<2.17"
|
||||
ansible_version: "-core >=2.18,<2.19"
|
||||
ansible_latest: "-core"
|
||||
ansible_minimum: "-core <2.16"
|
||||
distros: "fedora-latest,c9s,fedora-rawhide"
|
||||
distros: "fedora-latest,c9s,c10s,fedora-rawhide"
|
||||
|
||||
stages:
|
||||
|
||||
@@ -36,7 +36,7 @@ stages:
|
||||
# Supported distros
|
||||
|
||||
- ${{ each distro in split(variables.distros, ',') }}:
|
||||
- stage: ${{ replace(distro, '-', '_') }}_ansible_2_16
|
||||
- stage: ${{ replace(distro, '-', '_') }}_ansible_2_18
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/group_tests.yml
|
||||
@@ -49,7 +49,7 @@ stages:
|
||||
|
||||
# Galaxy on Fedora
|
||||
|
||||
- stage: galaxy_fedora_latest_ansible_2_16
|
||||
- stage: galaxy_fedora_latest_ansible_2_18
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/group_tests.yml
|
||||
|
||||
@@ -12,7 +12,7 @@ trigger: none
|
||||
pool:
|
||||
vmImage: 'ubuntu-24.04'
|
||||
|
||||
variables: { distros: "fedora-latest,fedora-rawhide,c9s" }
|
||||
variables: { distros: "fedora-latest,fedora-rawhide,c9s,c10s" }
|
||||
|
||||
stages:
|
||||
|
||||
|
||||
@@ -10,15 +10,26 @@ schedules:
|
||||
trigger: none
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-20.04'
|
||||
vmImage: 'ubuntu-24.04'
|
||||
|
||||
parameters:
|
||||
# Not really a parameter, but variables cannot be arrays or dicts
|
||||
# This maps the distro LATEST version to the avaiable ansible-core
|
||||
# version of the latest released compose.
|
||||
- name: "distro_ansible_map"
|
||||
type: object
|
||||
default:
|
||||
- { distro: "c8s", ansible_version: "<2.17", version_name: "2.16" }
|
||||
# c9s should use 2.14, but this version has an invalid certificate
|
||||
# and so is unsuable against ansible-galaxy.
|
||||
- { distro: "c9s", ansible_version: "<2.17", version_name: "2.16" }
|
||||
- { distro: "c10s", ansible_version: "<2.17", version_name: "2.16" }
|
||||
|
||||
variables:
|
||||
# We need to have two sets, as c8s is not supported by all ansible versions
|
||||
recent_distros: "fedora-latest,fedora-rawhide,c9s"
|
||||
distros: "fedora-latest,fedora-rawhide,c9s,c8s"
|
||||
distros: "fedora-latest,c10s,c9s,fedora-rawhide"
|
||||
ansible_version: "-core >=2.18,<2.19"
|
||||
ansible_latest: "-core"
|
||||
ansible_minimum: "-core <2.16"
|
||||
ansible_version: "-core >=2.16,<2.17"
|
||||
|
||||
stages:
|
||||
|
||||
@@ -38,7 +49,7 @@ stages:
|
||||
|
||||
# Latest ansible
|
||||
|
||||
- ${{ each distro in split(variables.recent_distros, ',') }}:
|
||||
- ${{ each distro in split(variables.distros, ',') }}:
|
||||
- stage: ${{ replace(distro, '-', '_') }}_ansible_latest
|
||||
dependsOn: []
|
||||
jobs:
|
||||
@@ -50,30 +61,44 @@ stages:
|
||||
skip_git_test: true
|
||||
test_galaxy: false
|
||||
|
||||
# Selected ansible-core version
|
||||
# Galaxy with Latest ansible
|
||||
|
||||
- ${{ each distro in split(variables.distros, ',') }}:
|
||||
- stage: ${{ replace(distro, '-', '_') }}_ansible_2_16
|
||||
- stage: galaxy_${{ replace(distro, '-', '_') }}_ansible_latest
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/group_tests.yml
|
||||
parameters:
|
||||
build_number: $(Build.BuildNumber)
|
||||
distro: ${{ distro }}
|
||||
ansible_version: ${{ variables.ansible_version }}
|
||||
ansible_version: ${{ variables.ansible_latest }}
|
||||
skip_git_test: true
|
||||
test_galaxy: true
|
||||
|
||||
# Test with pinned ansible version for the distro
|
||||
|
||||
- ${{ each config in parameters.distro_ansible_map }}:
|
||||
- stage: ${{ config.distro }}_distro_ansible_${{ replace(config.version_name, '.', '_') }}
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/group_tests.yml
|
||||
parameters:
|
||||
build_number: $(Build.BuildNumber)
|
||||
distro: ${{ config.distro }}
|
||||
ansible_version: -core${{ config.ansible_version }}
|
||||
skip_git_test: true
|
||||
test_galaxy: false
|
||||
|
||||
# Galaxy collection with selected ansible-core version
|
||||
# Test Galaxy collection with pinned ansible version for the distro
|
||||
|
||||
- ${{ each distro in split(variables.distros, ',') }}:
|
||||
- stage: galaxy_${{ replace(distro, '-', '_') }}_asible_2_16
|
||||
- ${{ each config in parameters.distro_ansible_map }}:
|
||||
- stage: galaxy_${{ config.distro }}_distro_ansible_${{ replace(config.version_name, '.', '_') }}
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/group_tests.yml
|
||||
parameters:
|
||||
build_number: $(Build.BuildNumber)
|
||||
distro: ${{ distro }}
|
||||
ansible_version: ${{ variables.ansible_version }}
|
||||
distro: ${{ config.distro }}
|
||||
ansible_version: -core${{ config.ansible_version }}
|
||||
skip_git_test: true
|
||||
test_galaxy: true
|
||||
|
||||
@@ -3,18 +3,31 @@ trigger:
|
||||
- master
|
||||
|
||||
pool:
|
||||
vmImage: 'ubuntu-20.04'
|
||||
vmImage: 'ubuntu-24.04'
|
||||
|
||||
parameters:
|
||||
# Not really a parameter, but variables cannot be arrays or dicts
|
||||
# This maps the distro LATEST version to the avaiable ansible-core
|
||||
# version of the latest released compose.
|
||||
- name: "distro_ansible_map"
|
||||
type: object
|
||||
default:
|
||||
- { distro: "c8s", ansible_version: "<2.17", version_name: "2.16" }
|
||||
# c9s should use 2.14, but this version has an invalid certificate
|
||||
# and so is unsuable against ansible-galaxy.
|
||||
- { distro: "c9s", ansible_version: "<2.17", version_name: "2.16" }
|
||||
- { distro: "c10s", ansible_version: "<2.17", version_name: "2.16" }
|
||||
|
||||
variables:
|
||||
distros: "fedora-latest,c9s,c8s,fedora-rawhide"
|
||||
ansible_version: "-core >=2.15,<2.16"
|
||||
distros: "fedora-latest,c10s,c9s,fedora-rawhide"
|
||||
ansible_version: "-core >=2.18,<2.19"
|
||||
|
||||
stages:
|
||||
|
||||
# Test with repository in all distros
|
||||
# Test with repository in all "current" distros
|
||||
|
||||
- ${{ each distro in split(variables.distros, ',') }}:
|
||||
- stage: ${{ replace(distro, '-', '_') }}_ansible_2_16
|
||||
- stage: ${{ replace(distro, '-', '_') }}_ansible_2_18
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/run_tests.yml
|
||||
@@ -27,7 +40,7 @@ stages:
|
||||
|
||||
# Galaxy on Fedora
|
||||
|
||||
- stage: galaxy_fedora_latest_ansible_2_16
|
||||
- stage: galaxy_fedora_latest_ansible_2_18
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/run_tests.yml
|
||||
@@ -37,3 +50,18 @@ stages:
|
||||
ansible_version: ${{ variables.ansible_version }}
|
||||
skip_git_test: false
|
||||
test_galaxy: true
|
||||
|
||||
|
||||
# Test with pinned ansible version for the distro
|
||||
|
||||
- ${{ each config in parameters.distro_ansible_map }}:
|
||||
- stage: ${{ config.distro }}_distro_ansible_${{ replace(config.version_name, '.', '_') }}
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- template: templates/run_tests.yml
|
||||
parameters:
|
||||
build_number: $(Build.BuildNumber)
|
||||
distro: ${{ config.distro }}
|
||||
ansible_version: -core${{ config.ansible_version }}
|
||||
skip_git_test: false
|
||||
test_galaxy: false
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
- script: ansible-galaxy collection install containers.podman
|
||||
displayName: Install Ansible Galaxy collections
|
||||
|
||||
- script: infra/image/build.sh -p -s ${{ parameters.distro }}
|
||||
- script: infra/image/build.sh -s ${{ parameters.distro }}
|
||||
displayName: Build ${{ parameters.distro }} base image
|
||||
env:
|
||||
ANSIBLE_ROLES_PATH: "${PWD}/roles"
|
||||
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
|
||||
- script: |
|
||||
git fetch --unshallow
|
||||
utils/build-galaxy-release.sh -i
|
||||
utils/build-collection.sh -i rpm
|
||||
retryCountOnTaskFailure: 5
|
||||
displayName: Build Galaxy release
|
||||
condition: ${{ parameters.test_galaxy }}
|
||||
|
||||
21
infra/azure/templates/variables_c10s.yaml
Normal file
21
infra/azure/templates/variables_c10s.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# Variables must be defined as comma separated lists.
|
||||
# For easier management of items to enable/disable,
|
||||
# use one test/module on each line, followed by a comma.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# ipa_disabled_modules: >-
|
||||
# dnsconfig,
|
||||
# group,
|
||||
# hostgroup
|
||||
#
|
||||
# If no variables are set, set "empty: true" as at least
|
||||
# one item is needed in the set.
|
||||
---
|
||||
variables:
|
||||
empty: true
|
||||
# ipa_enabled_modules: >-
|
||||
# ipa_enabled_tests: >-
|
||||
# ipa_disabled_modules: >-
|
||||
# ipa_disabled_tests: >-
|
||||
@@ -15,7 +15,7 @@ valid_distro() {
|
||||
usage() {
|
||||
local prog="${0##*/}"
|
||||
cat << EOF
|
||||
usage: ${prog} [-h] [-p] [-n HOSTNAME] [-s] distro
|
||||
usage: ${prog} [-h] [-n HOSTNAME] [-s] distro
|
||||
${prog} build a container image to test ansible-freeipa.
|
||||
EOF
|
||||
}
|
||||
@@ -41,14 +41,14 @@ cpus="2"
|
||||
memory="3g"
|
||||
quayname="quay.io/ansible-freeipa/upstream-tests"
|
||||
deploy_server="N"
|
||||
privileged=""
|
||||
deploy_capabilities="SYS_ADMIN,SYSLOG"
|
||||
capabilities=""
|
||||
|
||||
while getopts ":hn:ps" option
|
||||
while getopts ":hn:s" option
|
||||
do
|
||||
case "${option}" in
|
||||
h) help && exit 0 ;;
|
||||
n) hostname="${OPTARG}" ;;
|
||||
p) privileged="privileged" ;;
|
||||
s) deploy_server="Y" ;;
|
||||
*) die -u "Invalid option: ${option}" ;;
|
||||
esac
|
||||
@@ -66,6 +66,8 @@ container_check
|
||||
|
||||
if [ "${deploy_server}" == "Y" ]
|
||||
then
|
||||
capabilities="${deploy_capabilities}"
|
||||
|
||||
[ -n "$(command -v "ansible-playbook")" ] || die "ansible-playbook is required to install FreeIPA."
|
||||
|
||||
deploy_playbook="${TOPDIR}/playbooks/install-server.yml"
|
||||
@@ -89,7 +91,7 @@ container_create "${name}" "${tag}" \
|
||||
"hostname=${hostname}" \
|
||||
"memory=${memory}" \
|
||||
"cpus=${cpus}" \
|
||||
"${privileged}"
|
||||
"${capabilities:+capabilities=$capabilities}"
|
||||
container_commit "${name}" "${quayname}:${tag}"
|
||||
|
||||
if [ "${deploy_server}" == "Y" ]
|
||||
@@ -117,13 +119,6 @@ then
|
||||
deployed=true
|
||||
fi
|
||||
echo
|
||||
|
||||
if $deployed; then
|
||||
log info "= Enabling services ="
|
||||
container_exec "${name}" systemctl enable fixnet
|
||||
container_exec "${name}" systemctl enable fixipaip
|
||||
echo
|
||||
fi
|
||||
|
||||
container_stop "${name}"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM quay.io/centos/centos:stream10-development
|
||||
FROM quay.io/centos/centos:stream10
|
||||
ENV container=podman
|
||||
|
||||
RUN rm -fv /var/cache/dnf/metadata_lock.pid; \
|
||||
@@ -9,7 +9,8 @@ dnf --assumeyes install \
|
||||
bash \
|
||||
systemd \
|
||||
procps-ng \
|
||||
iproute; \
|
||||
iproute \
|
||||
hostname; \
|
||||
rm -rf /var/cache/dnf/;
|
||||
|
||||
RUN (cd /lib/systemd/system/; \
|
||||
@@ -30,6 +31,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ dnf --assumeyes install \
|
||||
bash \
|
||||
systemd \
|
||||
procps-ng \
|
||||
hostname \
|
||||
iproute; \
|
||||
dnf clean all; \
|
||||
rm -rf /var/cache/dnf/;
|
||||
@@ -34,6 +35,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ dnf --assumeyes install \
|
||||
bash \
|
||||
systemd \
|
||||
procps-ng \
|
||||
hostname \
|
||||
iproute; \
|
||||
rm -rf /var/cache/dnf/;
|
||||
|
||||
@@ -30,6 +31,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ dnf --assumeyes install \
|
||||
bash \
|
||||
systemd \
|
||||
procps-ng \
|
||||
hostname \
|
||||
iproute; \
|
||||
dnf clean all; \
|
||||
rm -rf /var/cache/dnf/;
|
||||
@@ -33,6 +34,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ dnf --assumeyes install \
|
||||
bash \
|
||||
systemd \
|
||||
procps-ng \
|
||||
hostname \
|
||||
iproute; \
|
||||
dnf clean all; \
|
||||
rm -rf /var/cache/dnf/;
|
||||
@@ -33,6 +34,8 @@ COPY system-service/fixipaip.sh /root/
|
||||
COPY system-service/fixnet.service /etc/systemd/system/
|
||||
COPY system-service/fixipaip.service /etc/systemd/system/
|
||||
RUN chmod +x /root/fixnet.sh /root/fixipaip.sh
|
||||
RUN systemctl enable fixnet.service
|
||||
RUN systemctl enable fixipaip.service
|
||||
|
||||
STOPSIGNAL RTMIN+3
|
||||
|
||||
|
||||
@@ -4,13 +4,20 @@
|
||||
SCRIPTDIR="$(dirname -- "$(readlink -f "${BASH_SOURCE[0]}")")"
|
||||
TOPDIR="$(readlink -f "${SCRIPTDIR}/../..")"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. "${SCRIPTDIR}/shdefaults"
|
||||
|
||||
# shellcheck disable=SC1091
|
||||
. "${TOPDIR}/utils/shfun"
|
||||
|
||||
container_create() {
|
||||
local name=${1}
|
||||
local image=${2}
|
||||
shift 2
|
||||
declare -a extra_opts=()
|
||||
declare -a extra_opts
|
||||
readarray -t extra_opts < \
|
||||
<(sed -e "s/-/--cap-drop=/g" -e "s/+/--cap-add=/g" \
|
||||
<<< "$(printf '%s\n' "${CAP_DEFAULTS[@]}")")
|
||||
for opt in "$@"
|
||||
do
|
||||
[ -z "${opt}" ] && continue
|
||||
@@ -18,7 +25,8 @@ container_create() {
|
||||
hostname=*) extra_opts+=("--${opt}") ;;
|
||||
cpus=*) extra_opts+=("--${opt}") ;;
|
||||
memory=*) extra_opts+=("--${opt}") ;;
|
||||
privileged) extra_opts+=("--${opt}") ;;
|
||||
capabilities=*) extra_opts+=("--cap-add=${opt##*=}") ;;
|
||||
volume=*) extra_opts+=("--volume=${opt##*=}") ;;
|
||||
*) log error "container_create: Invalid option: ${opt}" ;;
|
||||
esac
|
||||
done
|
||||
@@ -47,6 +55,19 @@ container_start() {
|
||||
|
||||
log info "= Starting ${name} ="
|
||||
podman start "${name}"
|
||||
# Add host entry to /etc/hosts
|
||||
ip=$(podman inspect "${name}" --format "{{.NetworkSettings.IPAddress}}")
|
||||
hostname=$(podman inspect "${name}" --format "{{.Config.Hostname}}")
|
||||
if [ -n "${ip}" ] && [ -n "${hostname}" ]; then
|
||||
cmd=$(cat <<EOF
|
||||
sed -i -E "/\s+${hostname}(\s|$)/d" /etc/hosts
|
||||
echo -e "$ip\t${hostname} ${hostname%%.*}" >> /etc/hosts
|
||||
EOF
|
||||
)
|
||||
podman exec "${name}" bash -c "$cmd"
|
||||
fi
|
||||
# Ensure /etc/shadow is readable
|
||||
podman exec "${name}" bash -c "chmod u+r /etc/shadow"
|
||||
echo
|
||||
}
|
||||
|
||||
@@ -175,3 +196,54 @@ container_image_list() {
|
||||
container_check() {
|
||||
[ -n "$(command -v "podman")" ] || die "podman is required."
|
||||
}
|
||||
|
||||
container_copy() {
|
||||
local name="${1}"
|
||||
local source="${2}"
|
||||
local destination="${3}"
|
||||
|
||||
log info "= Copying ${source} to ${name}:${destination} ="
|
||||
podman cp "${source}" "${name}:${destination}"
|
||||
echo
|
||||
}
|
||||
|
||||
container_fetch() {
|
||||
local name="${1}"
|
||||
local source="${2}"
|
||||
local destination="${3}"
|
||||
|
||||
log info "= Copying ${name}:${source} to ${destination} ="
|
||||
podman cp "${name}:${source}" "${destination}"
|
||||
echo
|
||||
}
|
||||
|
||||
container_tee() {
|
||||
local name=${1}
|
||||
local destination=${2}
|
||||
tmpfile=$(mktemp /tmp/container-temp.XXXXXX)
|
||||
|
||||
log info "= Creating ${name}:${destination} from stdin ="
|
||||
cat - > "${tmpfile}"
|
||||
podman cp "${tmpfile}" "${name}:${destination}"
|
||||
rm "${tmpfile}"
|
||||
echo
|
||||
}
|
||||
|
||||
container_save() {
|
||||
local name=${1}
|
||||
|
||||
archive="${name}.tar"
|
||||
log info "= Saving ${name} to ${archive} ="
|
||||
# podman is not able to overwrite the archive
|
||||
[ -f "${archive}" ] && rm "${archive}"
|
||||
podman save -o "${archive}" "${name}"
|
||||
echo
|
||||
}
|
||||
|
||||
container_load() {
|
||||
local name=${1}
|
||||
|
||||
image_name=$(podman load -q -i "${name}" | sed -e "s/^Loaded image: //")
|
||||
image=$(podman image list -q "${image_name}")
|
||||
echo "$image"
|
||||
}
|
||||
|
||||
11
infra/image/shdefaults
Normal file
11
infra/image/shdefaults
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash -eu
|
||||
# This file is meant to be source'd by other scripts
|
||||
|
||||
# Set default capabilities options for freeipa containers.
|
||||
# Use +CAP to add the capability and -CAP to drop the capability.
|
||||
CAP_DEFAULTS=(
|
||||
"+DAC_READ_SEARCH" # Required for SSSD
|
||||
"+SYS_PTRACE" # Required for debugging
|
||||
"+SYS_ADMIN" # Required to make dbus-brokder for systemd 258 work
|
||||
# Should be "+AUDIT_WRITE", "+SETUID", "+SETGID"
|
||||
)
|
||||
@@ -1,6 +1,7 @@
|
||||
[Unit]
|
||||
Description=Fix IPA server IP in IPA Server
|
||||
After=ipa.service
|
||||
PartOf=ipa.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
@@ -9,4 +10,4 @@ StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
WantedBy=ipa.service
|
||||
|
||||
@@ -50,9 +50,9 @@ if [ -z "${FORWARDER}" ] || [ "${FORWARDER}" == "127.0.0.1" ]; then
|
||||
fi
|
||||
|
||||
echo "Fix IPA:"
|
||||
echo " HOSTNAME: '${HOSTNAME}'"
|
||||
echo " IP: '${IP}'"
|
||||
echo " PTR: '${PTR}'"
|
||||
echo " HOSTNAME: '${HOSTNAME}'"
|
||||
echo " IP: '${IP}'"
|
||||
echo " PTR: '${PTR}'"
|
||||
echo " FORWARDER: '${FORWARDER}'"
|
||||
|
||||
ZONES=$(ipa -e in_server=true dnszone-find --name-from-ip="${HOSTNAME}." \
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
[Unit]
|
||||
Description=Fix server IP in IPA Server
|
||||
Wants=network.target
|
||||
After=network.target
|
||||
Before=ipa.service
|
||||
Description=Fix /etc/hosts and with local DNS also /etc/resolv.conf
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
@@ -11,4 +8,4 @@ StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=ipa.service
|
||||
WantedBy=container-ipa.target
|
||||
|
||||
@@ -39,26 +39,35 @@ if [ -z "${IP}" ] || ! valid_ipv4 "${IP}" ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DOMAIN=${HOSTNAME#*.}
|
||||
|
||||
echo "Fix NET:"
|
||||
echo " HOSTNAME: '${HOSTNAME}'"
|
||||
echo " IP: '${IP}'"
|
||||
echo " DOMAIN: '${DOMAIN}'"
|
||||
echo " IP: '${IP}'"
|
||||
echo
|
||||
|
||||
if grep -qE "^[^(#\s*)][0-9\.]+\s$HOSTNAME(\s|$)" /etc/hosts
|
||||
then
|
||||
sed -i.bak -e "s/.*${HOSTNAME}/${IP}\t${HOSTNAME}/" /etc/hosts
|
||||
else
|
||||
echo -e "$IP\t${HOSTNAME} ${HOSTNAME%%.*}" >> /etc/hosts
|
||||
fi
|
||||
# /etc/hosts
|
||||
|
||||
cp -a /etc/resolv.conf /etc/resolv.conf.fixnet
|
||||
cat > /etc/resolv.conf <<EOF
|
||||
search ${HOSTNAME#*.}
|
||||
nameserver 127.0.0.1
|
||||
EOF
|
||||
sed -i -E "/\s+${HOSTNAME}(\s|$)/d" /etc/hosts
|
||||
echo -e "$IP\t${HOSTNAME} ${HOSTNAME%%.*}" >> /etc/hosts
|
||||
|
||||
echo "/etc/hosts:"
|
||||
cat "/etc/hosts"
|
||||
|
||||
# /etc/resolv.conf
|
||||
|
||||
# If bind is not installed, exit
|
||||
[ -f "/etc/named.conf" ] || exit 0
|
||||
# If dyndb is not enabled for bind, exit
|
||||
grep -q '^dyndb "ipa"' "/etc/named.conf" || exit 0
|
||||
|
||||
cp -a /etc/resolv.conf /etc/resolv.conf.fixnet
|
||||
cat > /etc/resolv.conf <<EOF
|
||||
search ${DOMAIN}
|
||||
nameserver 127.0.0.1
|
||||
EOF
|
||||
|
||||
echo
|
||||
echo "/etc/resolv.conf:"
|
||||
cat "/etc/resolv.conf"
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
requires_ansible: ">=2.15.0"
|
||||
requires_ansible: ">=2.14.0"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
- ip_address: 8.8.8.8
|
||||
- ip_address: 8.8.4.4
|
||||
port: 52
|
||||
#serial: 1234
|
||||
# serial: 1234
|
||||
refresh: 3600
|
||||
retry: 900
|
||||
expire: 1209600
|
||||
|
||||
10
playbooks/passkeyconfig/passkeyconfig-present.yml
Normal file
10
playbooks/passkeyconfig/passkeyconfig-present.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
- name: Passkeyconfig example
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
|
||||
tasks:
|
||||
- name: Set passkeyconfig require_user_verification to false
|
||||
ipapasskeyconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
require_user_verification: false
|
||||
14
playbooks/passkeyconfig/passkeyconfig-retrieve.yml
Normal file
14
playbooks/passkeyconfig/passkeyconfig-retrieve.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
- name: Passkeyconfig get current configuration example
|
||||
hosts: ipaserver
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Get current passkey configuration
|
||||
ipapasskeyconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
register: result
|
||||
|
||||
- name: Display current passkey configuration
|
||||
ansible.builtin.debug:
|
||||
var: result.passkeyconfig
|
||||
11
playbooks/sysaccount/sysaccount-absent.yml
Normal file
11
playbooks/sysaccount/sysaccount-absent.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Sysaccount example
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure sysaccount my-app is absent
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
state: absent
|
||||
11
playbooks/sysaccount/sysaccount-disabled.yml
Normal file
11
playbooks/sysaccount/sysaccount-disabled.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Sysaccount example
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure sysaccount my-app is disabled
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
state: disabled
|
||||
11
playbooks/sysaccount/sysaccount-enabled.yml
Normal file
11
playbooks/sysaccount/sysaccount-enabled.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Sysaccount example
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure sysaccount my-app is enabled
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
state: enabled
|
||||
11
playbooks/sysaccount/sysaccount-present.yml
Normal file
11
playbooks/sysaccount/sysaccount-present.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Sysaccount example
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure sysaccount my-app is present with random password
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
random: true
|
||||
11
playbooks/sysaccount/sysaccount-privileged.yml
Normal file
11
playbooks/sysaccount/sysaccount-privileged.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Sysaccount example
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure sysaccount my-app is privileged
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
privileged: true
|
||||
11
playbooks/sysaccount/sysaccount-unprivileged.yml
Normal file
11
playbooks/sysaccount/sysaccount-unprivileged.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Sysaccount example
|
||||
hosts: ipaserver
|
||||
become: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure sysaccount my-app is not privileged
|
||||
ipasysaccount:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: my-app
|
||||
privileged: false
|
||||
@@ -11,7 +11,7 @@
|
||||
dest: "{{ ansible_facts['env'].HOME }}/password.txt"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: 0600
|
||||
mode: "0600"
|
||||
- name: Ensure symmetric vault exists with password from file.
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
dest: "{{ ansible_facts['env'].HOME }}/public.pem"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: 0600
|
||||
mode: "0600"
|
||||
- name: Ensure asymmetric vault exists with public key from file.
|
||||
ipavault:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
|
||||
@@ -107,7 +107,7 @@ from ansible.plugins.inventory import BaseInventoryPlugin
|
||||
from ansible.module_utils.six.moves.urllib.parse import quote
|
||||
|
||||
|
||||
class InventoryModule(BaseInventoryPlugin):
|
||||
class InventoryModule(BaseInventoryPlugin): # pylint: disable=R0901
|
||||
|
||||
NAME = 'freeipa'
|
||||
|
||||
|
||||
@@ -589,6 +589,20 @@ def ensure_fqdn(name, domain):
|
||||
return name
|
||||
|
||||
|
||||
def convert_to_sid(items):
|
||||
"""Convert all items to SID, if possible."""
|
||||
def get_sid(data):
|
||||
try:
|
||||
return get_trusted_domain_object_sid(data)
|
||||
except ipalib_errors.NotFound:
|
||||
return data
|
||||
if items is None:
|
||||
return None
|
||||
if not isinstance(items, (list, tuple)):
|
||||
items = [items]
|
||||
return [get_sid(item) for item in items]
|
||||
|
||||
|
||||
def api_get_realm():
|
||||
return api.env.realm
|
||||
|
||||
@@ -903,6 +917,13 @@ def get_trusted_domain_sid_from_name(dom_name):
|
||||
return unicode(sid) if sid is not None else None
|
||||
|
||||
|
||||
def get_trusted_domain_object_sid(object_name):
|
||||
"""Given an object name, returns de object SID."""
|
||||
domain_validator = __get_domain_validator()
|
||||
sid = domain_validator.get_trusted_domain_object_sid(object_name)
|
||||
return unicode(sid) if sid is not None else None
|
||||
|
||||
|
||||
class IPAParamMapping(Mapping):
|
||||
"""
|
||||
Provides IPA API mapping to playbook parameters or computed values.
|
||||
|
||||
@@ -106,7 +106,7 @@ RETURN = '''
|
||||
'''
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import (
|
||||
IPAAnsibleModule, compare_args_ipa
|
||||
IPAAnsibleModule, compare_args_ipa, ipalib_errors
|
||||
)
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ class AutomountMap(IPAAnsibleModule):
|
||||
location,
|
||||
{"automountmapname": name, "all": True}
|
||||
)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
return None
|
||||
return response["result"]
|
||||
|
||||
@@ -132,7 +132,7 @@ class AutomountMap(IPAAnsibleModule):
|
||||
"""Check if 'name' is an indirect map for 'parentmap'."""
|
||||
try:
|
||||
maps = self.ipa_command("automountmap_find", location, {})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
return []
|
||||
|
||||
result = []
|
||||
|
||||
@@ -487,6 +487,8 @@ def main():
|
||||
|
||||
# revoked
|
||||
reason = ansible_module.params_get("revocation_reason")
|
||||
if reason is not None:
|
||||
reason = get_revocation_reason(ansible_module, reason)
|
||||
|
||||
# general
|
||||
serial_number = ansible_module.params.get("serial_number")
|
||||
@@ -521,6 +523,9 @@ def main():
|
||||
invalid.append("revocation_reason")
|
||||
if state == "revoked":
|
||||
invalid.extend(["certificate_out", "chain"])
|
||||
# Reason 8 (revomeFromCRL) is the same as release hold
|
||||
if reason == 8:
|
||||
state = "released"
|
||||
elif state == "held":
|
||||
reason = 6 # certificateHold
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ options:
|
||||
type: list
|
||||
elements: str
|
||||
choices: ["password", "radius", "otp", "pkinit", "hardened", "idp",
|
||||
"disabled", ""]
|
||||
"passkey", "disabled", ""]
|
||||
aliases: ["ipauserauthtype"]
|
||||
ca_renewal_master_server:
|
||||
description: Renewal master for IPA certificate authority.
|
||||
@@ -356,7 +356,7 @@ def config_show(module):
|
||||
def get_netbios_name(module):
|
||||
try:
|
||||
_result = module.ipa_command_no_name("trustconfig_show", {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
return None
|
||||
return _result["result"]["ipantflatname"][0]
|
||||
|
||||
@@ -426,7 +426,7 @@ def main():
|
||||
user_auth_type=dict(type="list", elements="str", required=False,
|
||||
choices=["password", "radius", "otp",
|
||||
"pkinit", "hardened", "idp",
|
||||
"disabled", ""],
|
||||
"passkey", "disabled", ""],
|
||||
aliases=["ipauserauthtype"]),
|
||||
ca_renewal_master_server=dict(type="str", required=False),
|
||||
domain_resolution_order=dict(type="list", elements="str",
|
||||
|
||||
@@ -124,14 +124,14 @@ RETURN = """
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa
|
||||
IPAAnsibleModule, compare_args_ipa, ipalib_errors
|
||||
|
||||
|
||||
def find_delegation(module, name):
|
||||
"""Find if a delegation with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("delegation_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if delegation name is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
|
||||
@@ -1454,11 +1454,13 @@ def define_commands_for_present_state(module, zone_name, entry, res_find):
|
||||
# Create reverse records for existing records
|
||||
for ipv in ['a', 'aaaa']:
|
||||
record = '%srecord' % ipv
|
||||
if record in args and ('%s_extra_create_reverse' % ipv) in args:
|
||||
if (
|
||||
record in args
|
||||
and args.pop('%s_extra_create_reverse' % ipv, False)
|
||||
):
|
||||
cmds = create_reverse_ip_record(
|
||||
module, zone_name, name, args[record])
|
||||
_commands.extend(cmds)
|
||||
del args['%s_extra_create_reverse' % ipv]
|
||||
for record, fields in _RECORD_PARTS.items():
|
||||
part_fields = [f for f in fields if f in args]
|
||||
if part_fields:
|
||||
@@ -1620,7 +1622,6 @@ def main():
|
||||
commands.extend(cmds)
|
||||
|
||||
# Execute commands
|
||||
|
||||
changed = ansible_module.execute_ipa_commands(
|
||||
commands, exception_handler=exception_handler)
|
||||
|
||||
|
||||
@@ -113,13 +113,14 @@ options:
|
||||
externalmember:
|
||||
description:
|
||||
- List of members of a trusted domain in DOM\\name or name@domain form.
|
||||
Requires "server" context.
|
||||
required: false
|
||||
type: list
|
||||
elements: str
|
||||
aliases: ["ipaexternalmember", "external_member"]
|
||||
idoverrideuser:
|
||||
description:
|
||||
- User ID overrides to add
|
||||
- User ID overrides to add. Requires "server" context.
|
||||
required: false
|
||||
type: list
|
||||
elements: str
|
||||
@@ -188,13 +189,14 @@ options:
|
||||
externalmember:
|
||||
description:
|
||||
- List of members of a trusted domain in DOM\\name or name@domain form.
|
||||
Requires "server" context.
|
||||
required: false
|
||||
type: list
|
||||
elements: str
|
||||
aliases: ["ipaexternalmember", "external_member"]
|
||||
idoverrideuser:
|
||||
description:
|
||||
- User ID overrides to add
|
||||
- User ID overrides to add. Requires "server" context.
|
||||
required: false
|
||||
type: list
|
||||
elements: str
|
||||
@@ -297,6 +299,7 @@ EXAMPLES = """
|
||||
posix: yes
|
||||
|
||||
# Create an external group and add members from a trust to it.
|
||||
# Module will fail if running under 'client' context.
|
||||
- ipagroup:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: extgroup
|
||||
@@ -327,7 +330,8 @@ RETURN = """
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
|
||||
gen_add_list, gen_intersection_list, api_check_param
|
||||
gen_add_list, gen_intersection_list, api_check_param, \
|
||||
convert_to_sid
|
||||
from ansible.module_utils import six
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
@@ -562,21 +566,29 @@ def main():
|
||||
# The simple solution is to switch to client context for ensuring
|
||||
# several groups simply if the user was not explicitly asking for
|
||||
# the server context no matter if mixed types are used.
|
||||
context = None
|
||||
context = ansible_module.params_get("ipaapi_context")
|
||||
if state == "present" and groups is not None and len(groups) > 1 \
|
||||
and not FIX_6741_DEEPCOPY_OBJECTCLASSES:
|
||||
_context = ansible_module.params_get("ipaapi_context")
|
||||
if _context is None:
|
||||
if context is None:
|
||||
context = "client"
|
||||
ansible_module.debug(
|
||||
"Switching to client context due to an unfixed issue in "
|
||||
"your IPA version: https://pagure.io/freeipa/issue/9349")
|
||||
elif _context == "server":
|
||||
elif context == "server":
|
||||
ansible_module.fail_json(
|
||||
msg="Ensuring several groups with server context is not "
|
||||
"supported by your IPA version: "
|
||||
"https://pagure.io/freeipa/issue/9349")
|
||||
|
||||
if (
|
||||
(externalmember is not None
|
||||
or idoverrideuser is not None)
|
||||
and context == "client"
|
||||
):
|
||||
ansible_module.fail_json(
|
||||
msg="Cannot use externalmember in client context."
|
||||
)
|
||||
|
||||
# Use groups if names is None
|
||||
if groups is not None:
|
||||
names = groups
|
||||
@@ -676,6 +688,23 @@ def main():
|
||||
# Make sure group exists
|
||||
res_find = find_group(ansible_module, name)
|
||||
|
||||
# external members must de handled as SID
|
||||
externalmember = convert_to_sid(externalmember)
|
||||
|
||||
# idoverrides need to be compared through SID
|
||||
idoverrideuser_sid = convert_to_sid(idoverrideuser)
|
||||
res_idoverrideuser_sid = convert_to_sid(
|
||||
(res_find or {}).get("member_idoverrideuser", []))
|
||||
idoverride_set = dict(
|
||||
list(zip(idoverrideuser_sid or [], idoverrideuser or [])) +
|
||||
list(
|
||||
zip(
|
||||
res_idoverrideuser_sid or [],
|
||||
(res_find or {}).get("member_idoverrideuser", [])
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
user_add, user_del = [], []
|
||||
group_add, group_del = [], []
|
||||
service_add, service_del = [], []
|
||||
@@ -723,11 +752,12 @@ def main():
|
||||
res_find = {}
|
||||
|
||||
# if we just created/modified the group, update res_find
|
||||
res_find.setdefault("objectclass", [])
|
||||
classes = list(res_find.setdefault("objectclass", []))
|
||||
if external and not is_external_group(res_find):
|
||||
res_find["objectclass"].append("ipaexternalgroup")
|
||||
classes.append("ipaexternalgroup")
|
||||
if posix and not is_posix_group(res_find):
|
||||
res_find["objectclass"].append("posixgroup")
|
||||
classes.append("posixgroup")
|
||||
res_find["objectclass"] = classes
|
||||
|
||||
member_args = gen_member_args(
|
||||
user, group, service, externalmember, idoverrideuser
|
||||
@@ -746,13 +776,25 @@ def main():
|
||||
|
||||
(externalmember_add,
|
||||
externalmember_del) = gen_add_del_lists(
|
||||
externalmember, res_find.get("member_external"))
|
||||
externalmember, (
|
||||
list(res_find.get("member_external", []))
|
||||
+ list(res_find.get("ipaexternalmember", []))
|
||||
)
|
||||
)
|
||||
|
||||
# There are multiple ways to name an AD User, and any
|
||||
# can be used in idoverrides, so we create the add/del
|
||||
# lists based on SID, and then use the given user name
|
||||
# to the idoverride.
|
||||
(idoverrides_add,
|
||||
idoverrides_del) = gen_add_del_lists(
|
||||
idoverrideuser,
|
||||
res_find.get("member_idoverrideuser")
|
||||
)
|
||||
idoverrideuser_sid, res_idoverrideuser_sid)
|
||||
idoverrides_add = [
|
||||
idoverride_set[sid] for sid in set(idoverrides_add)
|
||||
]
|
||||
idoverrides_del = [
|
||||
idoverride_set[sid] for sid in set(idoverrides_del)
|
||||
]
|
||||
|
||||
membermanager_user_add, membermanager_user_del = \
|
||||
gen_add_del_lists(
|
||||
@@ -780,9 +822,16 @@ def main():
|
||||
service_add = gen_add_list(
|
||||
service, res_find.get("member_service"))
|
||||
externalmember_add = gen_add_list(
|
||||
externalmember, res_find.get("member_external"))
|
||||
externalmember, (
|
||||
list(res_find.get("member_external", []))
|
||||
+ list(res_find.get("ipaexternalmember", []))
|
||||
)
|
||||
)
|
||||
idoverrides_add = gen_add_list(
|
||||
idoverrideuser, res_find.get("member_idoverrideuser"))
|
||||
idoverrideuser_sid, res_idoverrideuser_sid)
|
||||
idoverrides_add = [
|
||||
idoverride_set[sid] for sid in set(idoverrides_add)
|
||||
]
|
||||
|
||||
membermanager_user_add = gen_add_list(
|
||||
membermanager_user,
|
||||
@@ -815,9 +864,16 @@ def main():
|
||||
service_del = gen_intersection_list(
|
||||
service, res_find.get("member_service"))
|
||||
externalmember_del = gen_intersection_list(
|
||||
externalmember, res_find.get("member_external"))
|
||||
externalmember, (
|
||||
list(res_find.get("member_external", []))
|
||||
+ list(res_find.get("ipaexternalmember", []))
|
||||
)
|
||||
)
|
||||
idoverrides_del = gen_intersection_list(
|
||||
idoverrideuser, res_find.get("member_idoverrideuser"))
|
||||
idoverrideuser_sid, res_idoverrideuser_sid)
|
||||
idoverrides_del = [
|
||||
idoverride_set[sid] for sid in set(idoverrides_del)
|
||||
]
|
||||
|
||||
membermanager_user_del = gen_intersection_list(
|
||||
membermanager_user, res_find.get("membermanager_user"))
|
||||
@@ -860,7 +916,7 @@ def main():
|
||||
if len(externalmember_del) > 0:
|
||||
del_member_args["ipaexternalmember"] = \
|
||||
externalmember_del
|
||||
elif externalmember or external:
|
||||
elif externalmember:
|
||||
ansible_module.fail_json(
|
||||
msg="Cannot add external members to a "
|
||||
"non-external group."
|
||||
|
||||
@@ -184,7 +184,7 @@ options:
|
||||
type: list
|
||||
elements: str
|
||||
aliases: ["krbprincipalauthind"]
|
||||
choices: ["radius", "otp", "pkinit", "hardened", "idp", ""]
|
||||
choices: ["radius", "otp", "pkinit", "hardened", "idp", "passkey", ""]
|
||||
required: false
|
||||
requires_pre_auth:
|
||||
description: Pre-authentication is required for the service
|
||||
@@ -356,7 +356,7 @@ options:
|
||||
type: list
|
||||
elements: str
|
||||
aliases: ["krbprincipalauthind"]
|
||||
choices: ["radius", "otp", "pkinit", "hardened", "idp", ""]
|
||||
choices: ["radius", "otp", "pkinit", "hardened", "idp", "passkey", ""]
|
||||
required: false
|
||||
requires_pre_auth:
|
||||
description: Pre-authentication is required for the service
|
||||
@@ -758,7 +758,7 @@ def main():
|
||||
auth_ind=dict(type='list', elements="str",
|
||||
aliases=["krbprincipalauthind"], default=None,
|
||||
choices=["radius", "otp", "pkinit", "hardened", "idp",
|
||||
""]),
|
||||
"passkey", ""]),
|
||||
requires_pre_auth=dict(type="bool", aliases=["ipakrbrequirespreauth"],
|
||||
default=None),
|
||||
ok_as_delegate=dict(type="bool", aliases=["ipakrbokasdelegate"],
|
||||
|
||||
@@ -155,7 +155,7 @@ RETURN = """
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa
|
||||
IPAAnsibleModule, compare_args_ipa, ipalib_errors
|
||||
from ansible.module_utils import six
|
||||
|
||||
if six.PY3:
|
||||
@@ -168,7 +168,7 @@ def find_idoverridegroup(module, idview, anchor):
|
||||
_result = module.ipa_command("idoverridegroup_show", idview,
|
||||
{"ipaanchoruuid": anchor,
|
||||
"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if idoverridegroup anchor is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
|
||||
@@ -315,7 +315,8 @@ 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, convert_input_certificates
|
||||
gen_intersection_list, encode_certificate, convert_input_certificates, \
|
||||
ipalib_errors
|
||||
from ansible.module_utils import six
|
||||
|
||||
if six.PY3:
|
||||
@@ -328,7 +329,7 @@ def find_idoverrideuser(module, idview, anchor):
|
||||
_result = module.ipa_command("idoverrideuser_show", idview,
|
||||
{"ipaanchoruuid": anchor,
|
||||
"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if idoverrideuser anchor is not found.
|
||||
return None
|
||||
|
||||
|
||||
@@ -184,7 +184,8 @@ RETURN = """
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, template_str, urlparse
|
||||
IPAAnsibleModule, compare_args_ipa, template_str, urlparse, \
|
||||
ipalib_errors
|
||||
from ansible.module_utils import six
|
||||
from copy import deepcopy
|
||||
import string
|
||||
@@ -269,7 +270,7 @@ 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
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if idp name is not found.
|
||||
return None
|
||||
|
||||
|
||||
@@ -143,7 +143,8 @@ RETURN = """
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, get_trusted_domain_sid_from_name
|
||||
IPAAnsibleModule, compare_args_ipa, get_trusted_domain_sid_from_name, \
|
||||
ipalib_errors
|
||||
from ansible.module_utils import six
|
||||
|
||||
if six.PY3:
|
||||
@@ -154,7 +155,7 @@ def find_idrange(module, name):
|
||||
"""Find if a idrange with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("idrange_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if idrange name is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
@@ -280,6 +281,14 @@ def main():
|
||||
|
||||
# Connect to IPA API
|
||||
with ansible_module.ipa_connect():
|
||||
# set required fields
|
||||
required = ["base_id", "range_size"]
|
||||
requires_baserid = (
|
||||
ansible_module.ipa_command_param_exists("config_mod", "enable_sid")
|
||||
and idrange_type in [None, "ipa-local"]
|
||||
)
|
||||
if requires_baserid:
|
||||
required.extend(["rid_base", "secondary_rid_base"])
|
||||
|
||||
commands = []
|
||||
for name in names:
|
||||
@@ -320,6 +329,18 @@ def main():
|
||||
del args["iparangetype"]
|
||||
commands.append([name, "idrange_mod", args])
|
||||
else:
|
||||
# Check if required parameters were given
|
||||
missing_params = [
|
||||
pname for pname in required
|
||||
if ansible_module.params_get(pname) is None
|
||||
]
|
||||
if missing_params:
|
||||
ansible_module.fail_json(
|
||||
msg=(
|
||||
"Missing required parameters: %s"
|
||||
% (", ".join(missing_params))
|
||||
)
|
||||
)
|
||||
commands.append([name, "idrange_add", args])
|
||||
|
||||
elif state == "absent":
|
||||
|
||||
@@ -138,7 +138,7 @@ 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
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if idview name is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
|
||||
@@ -76,14 +76,14 @@ RETURN = """
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa
|
||||
IPAAnsibleModule, compare_args_ipa, ipalib_errors
|
||||
|
||||
|
||||
def find_location(module, name):
|
||||
"""Find if a location with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("location_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if location name is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
|
||||
174
plugins/modules/ipapasskeyconfig.py
Normal file
174
plugins/modules/ipapasskeyconfig.py
Normal file
@@ -0,0 +1,174 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Authors:
|
||||
# Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2025 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: ipapasskeyconfig
|
||||
short_description: Manage FreeIPA passkeyconfig
|
||||
description: Manage FreeIPA passkeyconfig
|
||||
extends_documentation_fragment:
|
||||
- ipamodule_base_docs
|
||||
options:
|
||||
require_user_verification:
|
||||
description: Require user verification for passkey authentication
|
||||
required: false
|
||||
type: bool
|
||||
default: true
|
||||
aliases: ["iparequireuserverification"]
|
||||
author:
|
||||
- Rafael Guterres Jeffman (@rjeffman)
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
# Set passkeyconfig
|
||||
- ipapasskeyconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
require_user_verification: false
|
||||
|
||||
# Get current passkeyconfig
|
||||
- ipapasskeyconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
passkeyconfig:
|
||||
description: Dict of passkeyconfig settings
|
||||
returned: always
|
||||
type: dict
|
||||
contains:
|
||||
require_user_verification:
|
||||
description: Require user verification for passkey authentication
|
||||
type: bool
|
||||
returned: always
|
||||
"""
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, ipalib_errors
|
||||
from ansible.module_utils import six
|
||||
|
||||
if six.PY3:
|
||||
unicode = str
|
||||
|
||||
|
||||
def find_passkeyconfig(module):
|
||||
"""Find the current passkeyconfig settings."""
|
||||
try:
|
||||
_result = module.ipa_command_no_name(
|
||||
"passkeyconfig_show", {"all": True})
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if passkeyconfig is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
|
||||
|
||||
def gen_args(require_user_verification):
|
||||
_args = {}
|
||||
if require_user_verification is not None:
|
||||
_args["iparequireuserverification"] = require_user_verification
|
||||
return _args
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = IPAAnsibleModule(
|
||||
argument_spec=dict(
|
||||
# passkeyconfig
|
||||
require_user_verification=dict(
|
||||
required=False, type='bool',
|
||||
aliases=["iparequireuserverification"],
|
||||
default=None
|
||||
),
|
||||
),
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
ansible_module._ansible_debug = True
|
||||
|
||||
# Get parameters
|
||||
require_user_verification = (
|
||||
ansible_module.params_get("require_user_verification")
|
||||
)
|
||||
|
||||
# Init
|
||||
changed = False
|
||||
exit_args = {}
|
||||
|
||||
# Connect to IPA API
|
||||
with ansible_module.ipa_connect():
|
||||
|
||||
if not ansible_module.ipa_command_exists("passkeyconfig_show"):
|
||||
msg = "Managing passkeyconfig is not supported by your IPA version"
|
||||
ansible_module.fail_json(msg=msg)
|
||||
|
||||
result = find_passkeyconfig(ansible_module)
|
||||
|
||||
if result is None:
|
||||
ansible_module.fail_json(msg="Could not retrieve passkeyconfig")
|
||||
|
||||
if require_user_verification is not None:
|
||||
# Generate args
|
||||
args = gen_args(require_user_verification)
|
||||
|
||||
# Check if there are different settings in the find result.
|
||||
# If yes: modify
|
||||
if not compare_args_ipa(ansible_module, args, result):
|
||||
changed = True
|
||||
if not ansible_module.check_mode:
|
||||
try:
|
||||
ansible_module.ipa_command_no_name(
|
||||
"passkeyconfig_mod", args)
|
||||
except ipalib_errors.EmptyModlist:
|
||||
changed = False
|
||||
except Exception as e:
|
||||
ansible_module.fail_json(
|
||||
msg="passkeyconfig_mod failed: %s" % str(e))
|
||||
else:
|
||||
# No parameters provided, just return current config
|
||||
pass
|
||||
|
||||
# Get updated config if changes were made
|
||||
if changed:
|
||||
result = find_passkeyconfig(ansible_module)
|
||||
|
||||
# Prepare exit args
|
||||
exit_args["passkeyconfig"] = {}
|
||||
if result:
|
||||
# Map IPA API field to module parameter
|
||||
if "iparequireuserverification" in result:
|
||||
exit_args["passkeyconfig"]["require_user_verification"] = \
|
||||
result["iparequireuserverification"][0]
|
||||
|
||||
# Done
|
||||
ansible_module.exit_json(changed=changed, **exit_args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -154,14 +154,14 @@ RETURN = """
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, to_text
|
||||
IPAAnsibleModule, compare_args_ipa, to_text, ipalib_errors
|
||||
|
||||
|
||||
def find_permission(module, name):
|
||||
"""Find if a permission with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("permission_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if permission name is not found.
|
||||
return None
|
||||
_res = _result["result"]
|
||||
|
||||
@@ -124,7 +124,7 @@ RETURN = """
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \
|
||||
gen_intersection_list
|
||||
gen_intersection_list, ipalib_errors
|
||||
from ansible.module_utils import six
|
||||
|
||||
if six.PY3:
|
||||
@@ -135,7 +135,7 @@ def find_privilege(module, name):
|
||||
"""Find if a privilege with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("privilege_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if privilege name is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
|
||||
@@ -85,6 +85,11 @@ options:
|
||||
type: list
|
||||
elements: str
|
||||
required: false
|
||||
sysaccount:
|
||||
description: List of sysaccounts.
|
||||
type: list
|
||||
elements: str
|
||||
required: false
|
||||
action:
|
||||
description: Work on role or member level.
|
||||
type: str
|
||||
@@ -129,7 +134,7 @@ EXAMPLES = """
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, gen_add_del_lists, compare_args_ipa, \
|
||||
gen_intersection_list, ensure_fqdn
|
||||
gen_intersection_list, ensure_fqdn, ipalib_errors
|
||||
from ansible.module_utils import six
|
||||
|
||||
if six.PY3:
|
||||
@@ -140,7 +145,7 @@ def find_role(module, name):
|
||||
"""Find if a role with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("role_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if role name is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
@@ -177,7 +182,7 @@ def check_parameters(module):
|
||||
"description",
|
||||
"user", "group",
|
||||
"host", "hostgroup",
|
||||
"service",
|
||||
"service", "sysaccount",
|
||||
"privilege",
|
||||
]
|
||||
|
||||
@@ -225,7 +230,7 @@ def ensure_absent_state(module, name, action, res_find):
|
||||
{"privilege": del_list}])
|
||||
|
||||
member_args = {}
|
||||
for key in ['user', 'group', 'hostgroup']:
|
||||
for key in ['user', 'group', 'hostgroup', 'sysaccount']:
|
||||
_members = module.params_get_lowercase(key)
|
||||
if _members:
|
||||
del_list = gen_intersection_list(
|
||||
@@ -335,7 +340,7 @@ def ensure_role_with_members_is_present(module, name, res_find, action):
|
||||
add_members = {}
|
||||
del_members = {}
|
||||
|
||||
for key in ["user", "group", "hostgroup"]:
|
||||
for key in ["user", "group", "hostgroup", "sysaccount"]:
|
||||
_members = module.params_get_lowercase(key)
|
||||
if _members is not None:
|
||||
add_list, del_list = gen_add_del_lists(
|
||||
@@ -437,6 +442,8 @@ def create_module():
|
||||
default=None),
|
||||
service=dict(required=False, type='list', elements="str",
|
||||
default=None),
|
||||
sysaccount=dict(required=False, type='list', elements="str",
|
||||
default=None),
|
||||
|
||||
# state
|
||||
action=dict(type="str", default="role",
|
||||
@@ -467,8 +474,15 @@ def main():
|
||||
state = ansible_module.params_get("state")
|
||||
action = ansible_module.params_get("action")
|
||||
names = ansible_module.params_get("name")
|
||||
sysaccount = ansible_module.params_get("sysaccount")
|
||||
commands = []
|
||||
|
||||
has_sysaccount_member = ansible_module.ipa_command_param_exists(
|
||||
"role_add_member", "sysaccount")
|
||||
if not has_sysaccount_member and sysaccount is not None:
|
||||
ansible_module.fail_json(
|
||||
msg="sysaccount members are not supported by your IPA version")
|
||||
|
||||
for name in names:
|
||||
cmds = role_commands_for_name(ansible_module, state, action, name)
|
||||
commands.extend(cmds)
|
||||
|
||||
@@ -113,14 +113,14 @@ RETURN = """
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa
|
||||
IPAAnsibleModule, compare_args_ipa, ipalib_errors
|
||||
|
||||
|
||||
def find_selfservice(module, name):
|
||||
"""Find if a selfservice with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("selfservice_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if selfservice name is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
|
||||
@@ -192,14 +192,14 @@ RETURN = """
|
||||
|
||||
|
||||
from ansible.module_utils.ansible_freeipa_module import \
|
||||
IPAAnsibleModule, compare_args_ipa, DNSName
|
||||
IPAAnsibleModule, compare_args_ipa, DNSName, ipalib_errors
|
||||
|
||||
|
||||
def find_server(module, name):
|
||||
"""Find if a server with the given name already exist."""
|
||||
try:
|
||||
_result = module.ipa_command("server_show", name, {"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if server name is not found.
|
||||
return None
|
||||
return _result["result"]
|
||||
@@ -214,7 +214,7 @@ def server_role_status(module, name):
|
||||
"include_master": True,
|
||||
"raw": True,
|
||||
"all": True})
|
||||
except Exception: # pylint: disable=broad-except
|
||||
except ipalib_errors.NotFound:
|
||||
# An exception is raised if server name is not found.
|
||||
return None
|
||||
return _result["result"][0]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user