mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-26 21:33:05 +00:00
Merge pull request #1372 from rjeffman/passkey_support
Add support for passkey
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -454,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)
|
||||
|
||||
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
|
||||
@@ -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.
|
||||
@@ -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",
|
||||
|
||||
@@ -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"],
|
||||
|
||||
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()
|
||||
@@ -74,7 +74,7 @@ options:
|
||||
type: list
|
||||
elements: str
|
||||
required: false
|
||||
choices: ["otp", "radius", "pkinit", "hardened", "idp", ""]
|
||||
choices: ["otp", "radius", "pkinit", "hardened", "idp", "passkey", ""]
|
||||
aliases: ["krbprincipalauthind"]
|
||||
skip_host_check:
|
||||
description: Skip checking if host object exists.
|
||||
@@ -192,7 +192,7 @@ options:
|
||||
type: list
|
||||
elements: str
|
||||
required: false
|
||||
choices: ["otp", "radius", "pkinit", "hardened", "idp", ""]
|
||||
choices: ["otp", "radius", "pkinit", "hardened", "idp", "passkey", ""]
|
||||
aliases: ["krbprincipalauthind"]
|
||||
skip_host_check:
|
||||
description: Skip checking if host object exists.
|
||||
@@ -560,7 +560,7 @@ def init_ansible_module():
|
||||
auth_ind=dict(type="list", elements="str",
|
||||
aliases=["krbprincipalauthind"],
|
||||
choices=["otp", "radius", "pkinit", "hardened", "idp",
|
||||
""]),
|
||||
"passkey", ""]),
|
||||
skip_host_check=dict(type="bool"),
|
||||
force=dict(type="bool"),
|
||||
requires_pre_auth=dict(
|
||||
|
||||
@@ -208,7 +208,8 @@ options:
|
||||
Use empty string to reset userauthtype to the initial value.
|
||||
type: list
|
||||
elements: str
|
||||
choices: ["password", "radius", "otp", "pkinit", "hardened", "idp", ""]
|
||||
choices: ["password", "radius", "otp", "pkinit", "hardened", "idp",
|
||||
"passkey", ""]
|
||||
required: false
|
||||
aliases: ["ipauserauthtype"]
|
||||
userclass:
|
||||
@@ -480,7 +481,8 @@ options:
|
||||
Use empty string to reset userauthtype to the initial value.
|
||||
type: list
|
||||
elements: str
|
||||
choices: ["password", "radius", "otp", "pkinit", "hardened", "idp", ""]
|
||||
choices: ["password", "radius", "otp", "pkinit", "hardened", "idp",
|
||||
"passkey", ""]
|
||||
required: false
|
||||
aliases: ["ipauserauthtype"]
|
||||
userclass:
|
||||
@@ -1070,7 +1072,7 @@ def main():
|
||||
userauthtype=dict(type='list', elements="str",
|
||||
aliases=["ipauserauthtype"], default=None,
|
||||
choices=["password", "radius", "otp", "pkinit",
|
||||
"hardened", "idp", ""]),
|
||||
"hardened", "idp", "passkey", ""]),
|
||||
userclass=dict(type="list", elements="str", aliases=["class"],
|
||||
default=None),
|
||||
radius=dict(type="str", aliases=["ipatokenradiusconfiglink"],
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
gather_facts: no
|
||||
|
||||
tasks:
|
||||
- name: Include tasks ../env_freeipa_facts.yml
|
||||
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
# GET CURRENT CONFIG
|
||||
|
||||
@@ -80,6 +82,36 @@
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure config with user_auth_type passkey
|
||||
ipaconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
user_auth_type:
|
||||
- passkey
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
when: passkey_is_supported
|
||||
|
||||
- name: Ensure config with user_auth_type passkey, again
|
||||
ipaconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
user_auth_type:
|
||||
- passkey
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
when: passkey_is_supported
|
||||
|
||||
- name: Check if correct message is given if passkey is not supported.
|
||||
ipaconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
user_auth_type:
|
||||
- passkey
|
||||
register: result
|
||||
failed_when: not result.failed or "'passkey' is not supported" not in result.msg
|
||||
when: not passkey_is_supported
|
||||
|
||||
- name: Ensure config with empty user_auth_type
|
||||
ipaconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -138,6 +170,6 @@
|
||||
ipaconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
pac_type: '{{ previousconfig.config.pac_type }}'
|
||||
user_auth_type: '{{ previousconfig.config.user_auth_type }}'
|
||||
configstring: '{{ previousconfig.config.configstring }}'
|
||||
pac_type: '{{ previousconfig.config.pac_type | default("") }}'
|
||||
user_auth_type: '{{ previousconfig.config.user_auth_type | default("") }}'
|
||||
configstring: '{{ previousconfig.config.configstring | default("") }}'
|
||||
|
||||
@@ -38,12 +38,24 @@
|
||||
krb5ccname: "__check_ipa_host_is_client_or_server__"
|
||||
register: check_ad_support
|
||||
|
||||
- name: Verify if passkey tests are possible
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
echo SomeADMINpassword | kinit -c {{ krb5ccname }} admin > /dev/null
|
||||
RESULT=$(KRB5CCNAME={{ krb5ccname }} ipa command-find passkey | grep "Number of entries returned")
|
||||
kdestroy -A -c {{ krb5ccname }} > /dev/null
|
||||
echo $RESULT
|
||||
vars:
|
||||
krb5ccname: "__check_ipa_host_is_client_or_server__"
|
||||
register: check_passkey_support
|
||||
|
||||
- name: Set FreeIPA facts.
|
||||
ansible.builtin.set_fact:
|
||||
ipa_version: "{{ ipa_cmd_version.stdout_lines[0] }}"
|
||||
ipa_api_version: "{{ ipa_cmd_version.stdout_lines[1] }}"
|
||||
ipa_host_is_client: "{{ (check_client.stdout_lines[-1] == 'CLIENT') | bool }}"
|
||||
trust_test_is_supported: "{{ 'AD trust agent' in check_ad_support.stdout }}"
|
||||
passkey_is_supported: "{{ 'Number of entries returned 0' not in check_passkey_support.stdout }}"
|
||||
|
||||
- name: Ensure ipaserver_domain is set
|
||||
when: ipaserver_domain is not defined
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
gather_facts: yes
|
||||
|
||||
tasks:
|
||||
- name: Include FreeIPA facts.
|
||||
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
- name: Get Domain from server name
|
||||
ansible.builtin.set_fact:
|
||||
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] | join('.') }}"
|
||||
@@ -58,6 +61,39 @@
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure host "{{ host1_fqdn }}" present with auth_ind passkey
|
||||
ipahost:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: "{{ host1_fqdn }}"
|
||||
auth_ind:
|
||||
- passkey
|
||||
register: result
|
||||
when: passkey_is_supported
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure host "{{ host1_fqdn }}" present with auth_ind passkey, again
|
||||
ipahost:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: "{{ host1_fqdn }}"
|
||||
auth_ind:
|
||||
- passkey
|
||||
register: result
|
||||
when: passkey_is_supported
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Check if correct message is given if passkey is not supported.
|
||||
ipahost:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: "{{ host1_fqdn }}"
|
||||
auth_ind:
|
||||
- passkey
|
||||
register: result
|
||||
when: not passkey_is_supported
|
||||
failed_when: not result.failed or "'passkey' is not supported" not in result.msg
|
||||
|
||||
- name: Ensure host "{{ host1_fqdn }}" present with empty auth_ind
|
||||
ipahost:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
67
tests/passkeyconfig/test_passkeyconfig.yml
Normal file
67
tests/passkeyconfig/test_passkeyconfig.yml
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
- name: Test passkeyconfig
|
||||
hosts: "{{ ipa_test_host | default('ipaserver') }}"
|
||||
# It is normally not needed to set "become" to "true" for a module test.
|
||||
# Only set it to true if it is needed to execute commands as root.
|
||||
become: false
|
||||
# Enable "gather_facts" only if "ansible_facts" variable needs to be used.
|
||||
gather_facts: false
|
||||
module_defaults:
|
||||
ipapasskeyconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
|
||||
tasks:
|
||||
|
||||
- name: Include FreeIPA facts.
|
||||
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
- name: Run tests only if passkey is supported
|
||||
when: passkey_is_supported
|
||||
block:
|
||||
# TESTS
|
||||
|
||||
- name: Get current passkeyconfig
|
||||
ipapasskeyconfig:
|
||||
register: result_initial
|
||||
failed_when: result_initial.failed
|
||||
|
||||
- name: Ensure require_user_verification is set to false
|
||||
ipapasskeyconfig:
|
||||
require_user_verification: false
|
||||
register: result
|
||||
failed_when: result.failed
|
||||
|
||||
- name: Ensure require_user_verification is set to false again
|
||||
ipapasskeyconfig:
|
||||
require_user_verification: false
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Verify require_user_verification is false
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- result.passkeyconfig.require_user_verification == false
|
||||
|
||||
- name: Ensure require_user_verification is set to true
|
||||
ipapasskeyconfig:
|
||||
require_user_verification: true
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure require_user_verification is set to true again
|
||||
ipapasskeyconfig:
|
||||
require_user_verification: true
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Verify require_user_verification is true
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- result.passkeyconfig.require_user_verification == true
|
||||
|
||||
# CLEANUP: Restore original configuration
|
||||
- name: Restore original passkeyconfig
|
||||
ipapasskeyconfig:
|
||||
require_user_verification: "{{ result_initial.passkeyconfig.require_user_verification }}"
|
||||
when: result_initial.passkeyconfig is defined and result_initial.passkeyconfig.require_user_verification is defined
|
||||
40
tests/passkeyconfig/test_passkeyconfig_client_context.yml
Normal file
40
tests/passkeyconfig/test_passkeyconfig_client_context.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
- name: Test passkeyconfig
|
||||
hosts: ipaclients, ipaserver
|
||||
# It is normally not needed to set "become" to "true" for a module test.
|
||||
# Only set it to true if it is needed to execute commands as root.
|
||||
become: false
|
||||
# Enable "gather_facts" only if "ansible_facts" variable needs to be used.
|
||||
gather_facts: false
|
||||
|
||||
tasks:
|
||||
- name: Include FreeIPA facts.
|
||||
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
# Test will only be executed if host is not a server.
|
||||
- name: Execute with server context in the client.
|
||||
ipapasskeyconfig:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: server
|
||||
require_user_verification: false
|
||||
register: result
|
||||
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
|
||||
when: ipa_host_is_client and passkey_is_supported
|
||||
|
||||
# Import basic module tests, and execute with ipa_context set to 'client'.
|
||||
# If ipaclients is set, it will be executed using the client, if not,
|
||||
# ipaserver will be used.
|
||||
#
|
||||
# With this setup, tests can be executed against an IPA client, against
|
||||
# an IPA server using "client" context, and ensure that tests are executed
|
||||
# in upstream CI.
|
||||
|
||||
- name: Test passkeyconfig using client context, in client host.
|
||||
import_playbook: test_passkeyconfig.yml
|
||||
when: groups['ipaclients'] and passkey_is_supported
|
||||
vars:
|
||||
ipa_test_host: ipaclients
|
||||
|
||||
- name: Test passkeyconfig using client context, in server host.
|
||||
import_playbook: test_passkeyconfig.yml
|
||||
when: passkey_is_supported and (groups['ipaclients'] is not defined or not groups['ipaclients'])
|
||||
@@ -5,6 +5,8 @@
|
||||
gather_facts: yes
|
||||
|
||||
tasks:
|
||||
- name: Include tasks ../env_freeipa_facts.yml
|
||||
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
# CLEANUP TEST ITEMS
|
||||
|
||||
@@ -83,6 +85,37 @@
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with auth_ind passkey
|
||||
ipaservice:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "test-service/{{ ansible_facts['fqdn'] }}"
|
||||
auth_ind:
|
||||
- passkey
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
when: passkey_is_supported
|
||||
|
||||
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with auth_ind passkey, again
|
||||
ipaservice:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: "test-service/{{ ansible_facts['fqdn'] }}"
|
||||
auth_ind:
|
||||
- passkey
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
when: passkey_is_supported
|
||||
|
||||
- name: Check if correct message is given if passkey is not supported.
|
||||
ipaservice:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: "test-service/{{ ansible_facts['fqdn'] }}"
|
||||
auth_ind:
|
||||
- passkey
|
||||
register: result
|
||||
failed_when: not result.failed or "'passkey' is not supported" not in result.msg
|
||||
when: not passkey_is_supported
|
||||
|
||||
- name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with empty auth_ind
|
||||
ipaservice:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
gather_facts: false
|
||||
|
||||
tasks:
|
||||
- name: Include FreeIPA facts.
|
||||
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
- name: Remove test users
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -392,6 +395,42 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure user pinky with userauthtype passkey exists
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
first: pinky
|
||||
last: user
|
||||
userauthtype: passkey
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
when: passkey_is_supported
|
||||
|
||||
- name: Ensure user pinky with userauthtype passkey exists, again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
first: pinky
|
||||
last: user
|
||||
userauthtype: passkey
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
when: passkey_is_supported
|
||||
|
||||
- name: Check if correct message is given if passkey is not supported.
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
first: pinky
|
||||
last: user
|
||||
userauthtype: passkey
|
||||
register: result
|
||||
when: not passkey_is_supported
|
||||
failed_when: not result.failed or "'passkey' is not supported" not in result.msg
|
||||
|
||||
- name: User pinky absent and preserved for future exclusion.
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
|
||||
Reference in New Issue
Block a user