From 536b7cb5f3abc422380c881a138f2fb6d26ed228 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Fri, 4 Jul 2025 18:14:48 -0300 Subject: [PATCH] ipauser: Add support for 'passkey' in 'user_auth_type' The value 'passkey' was missing as a valid value for user_auth_type attribute. Signed-off-by: Rafael Guterres Jeffman --- README-user.md | 2 +- plugins/modules/ipauser.py | 8 +++++--- tests/user/test_user.yml | 39 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/README-user.md b/README-user.md index f9ee2ae0..1c45a0bd 100644 --- a/README-user.md +++ b/README-user.md @@ -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 diff --git a/plugins/modules/ipauser.py b/plugins/modules/ipauser.py index d16d2c0c..7c57f996 100644 --- a/plugins/modules/ipauser.py +++ b/plugins/modules/ipauser.py @@ -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"], diff --git a/tests/user/test_user.yml b/tests/user/test_user.yml index daad3e74..67fb3165 100644 --- a/tests/user/test_user.yml +++ b/tests/user/test_user.yml @@ -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