mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-26 21:33:05 +00:00
ipauser: Support for External IdP attributes.
Add support for 'idp' and 'idp_user_id' to ipauser plugin. FreeIPA 4.10.0 is required for both attributes.
This commit is contained in:
@@ -445,6 +445,8 @@ Variable | Description | Required
|
||||
`employeenumber` | Employee Number | no
|
||||
`employeetype` | Employee Type | no
|
||||
`preferredlanguage` | Preferred Language | no
|
||||
`idp` \| `ipaidpconfiglink` | External IdP configuration | no
|
||||
`idp_user_id` \| `ipaidpsub` | A string that identifies the user at external IdP | no
|
||||
`certificate` | List of base-64 encoded user certificates. | no
|
||||
`certmapdata` | List of certificate mappings. Either `data` or `certificate` or `issuer` together with `subject` need to be specified. Only usable with IPA versions 4.5 and up. <br>Options: | no
|
||||
| `certificate` - Base-64 encoded user certificate, not usable with other certmapdata options. | no
|
||||
|
||||
12
playbooks/user/add-user-external-idp.yml
Normal file
12
playbooks/user/add-user-external-idp.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: Playbook to handle users
|
||||
hosts: ipaserver
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Create user associated with an external IdP
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: idpuser
|
||||
idp: keycloak
|
||||
idp_user_id: idpuser@exemple.com
|
||||
@@ -271,6 +271,16 @@ options:
|
||||
description: Preferred Language
|
||||
type: str
|
||||
required: false
|
||||
idp:
|
||||
description: External IdP configuration
|
||||
type: str
|
||||
required: false
|
||||
aliases: ["ipaidpconfiglink"]
|
||||
idp_user_id:
|
||||
description: A string that identifies the user at external IdP
|
||||
type: str
|
||||
required: false
|
||||
aliases: ["ipaidpsub"]
|
||||
certificate:
|
||||
description: List of base-64 encoded user certificates
|
||||
type: list
|
||||
@@ -528,6 +538,16 @@ options:
|
||||
description: Preferred Language
|
||||
type: str
|
||||
required: false
|
||||
idp:
|
||||
description: External IdP configuration
|
||||
type: str
|
||||
required: false
|
||||
aliases: ["ipaidpconfiglink"]
|
||||
idp_user_id:
|
||||
description: A string that identifies the user at external IdP
|
||||
type: str
|
||||
required: false
|
||||
aliases: ["ipaidpsub"]
|
||||
certificate:
|
||||
description: List of base-64 encoded user certificates
|
||||
type: list
|
||||
@@ -735,8 +755,8 @@ def gen_args(first, last, fullname, displayname, initials, homedir, gecos,
|
||||
mobile, pager, fax, orgunit, title, carlicense, sshpubkey,
|
||||
userauthtype, userclass, radius, radiususer, departmentnumber,
|
||||
employeenumber, employeetype, preferredlanguage, smb_logon_script,
|
||||
smb_profile_path, smb_home_dir, smb_home_drive, noprivate,
|
||||
nomembers):
|
||||
smb_profile_path, smb_home_dir, smb_home_drive, idp, idp_user_id,
|
||||
noprivate, nomembers):
|
||||
# principal, manager, certificate and certmapdata are handled not in here
|
||||
_args = {}
|
||||
if first is not None:
|
||||
@@ -809,6 +829,10 @@ def gen_args(first, last, fullname, displayname, initials, homedir, gecos,
|
||||
_args["employeetype"] = employeetype
|
||||
if preferredlanguage is not None:
|
||||
_args["preferredlanguage"] = preferredlanguage
|
||||
if idp is not None:
|
||||
_args["ipaidpconfiglink"] = idp
|
||||
if idp_user_id is not None:
|
||||
_args["ipaidpsub"] = idp_user_id
|
||||
if noprivate is not None:
|
||||
_args["noprivate"] = noprivate
|
||||
if nomembers is not None:
|
||||
@@ -833,6 +857,7 @@ def check_parameters( # pylint: disable=unused-argument
|
||||
employeenumber, employeetype, preferredlanguage, certificate,
|
||||
certmapdata, noprivate, nomembers, preserve, update_password,
|
||||
smb_logon_script, smb_profile_path, smb_home_dir, smb_home_drive,
|
||||
idp, ipa_user_id,
|
||||
):
|
||||
if state == "present" and action == "user":
|
||||
invalid = ["preserve"]
|
||||
@@ -846,7 +871,7 @@ def check_parameters( # pylint: disable=unused-argument
|
||||
"departmentnumber", "employeenumber", "employeetype",
|
||||
"preferredlanguage", "noprivate", "nomembers", "update_password",
|
||||
"gecos", "smb_logon_script", "smb_profile_path", "smb_home_dir",
|
||||
"smb_home_drive",
|
||||
"smb_home_drive", "idp", "idp_user_id"
|
||||
]
|
||||
|
||||
if state == "present" and action == "member":
|
||||
@@ -1069,6 +1094,9 @@ def main():
|
||||
elements='dict', required=False),
|
||||
noprivate=dict(type='bool', default=None),
|
||||
nomembers=dict(type='bool', default=None),
|
||||
idp=dict(type="str", default=None, aliases=['ipaidpconfiglink']),
|
||||
idp_user_id=dict(type="str", default=None,
|
||||
aliases=['ipaidpconfiglink']),
|
||||
)
|
||||
|
||||
ansible_module = IPAAnsibleModule(
|
||||
@@ -1171,6 +1199,8 @@ def main():
|
||||
smb_profile_path = ansible_module.params_get("smb_profile_path")
|
||||
smb_home_dir = ansible_module.params_get("smb_home_dir")
|
||||
smb_home_drive = ansible_module.params_get("smb_home_drive")
|
||||
idp = ansible_module.params_get("idp")
|
||||
idp_user_id = ansible_module.params_get("idp_user_id")
|
||||
certificate = ansible_module.params_get("certificate")
|
||||
certmapdata = ansible_module.params_get("certmapdata")
|
||||
noprivate = ansible_module.params_get("noprivate")
|
||||
@@ -1204,7 +1234,7 @@ def main():
|
||||
radiususer, departmentnumber, employeenumber, employeetype,
|
||||
preferredlanguage, certificate, certmapdata, noprivate, nomembers,
|
||||
preserve, update_password, smb_logon_script, smb_profile_path,
|
||||
smb_home_dir, smb_home_drive)
|
||||
smb_home_dir, smb_home_drive, idp, idp_user_id)
|
||||
certmapdata = convert_certmapdata(certmapdata)
|
||||
|
||||
# Use users if names is None
|
||||
@@ -1298,6 +1328,8 @@ def main():
|
||||
smb_profile_path = user.get("smb_profile_path")
|
||||
smb_home_dir = user.get("smb_home_dir")
|
||||
smb_home_drive = user.get("smb_home_drive")
|
||||
idp = user.get("idp")
|
||||
idp_user_id = user.get("idp_user_id")
|
||||
certificate = user.get("certificate")
|
||||
certmapdata = user.get("certmapdata")
|
||||
noprivate = user.get("noprivate")
|
||||
@@ -1314,7 +1346,7 @@ def main():
|
||||
employeetype, preferredlanguage, certificate,
|
||||
certmapdata, noprivate, nomembers, preserve,
|
||||
update_password, smb_logon_script, smb_profile_path,
|
||||
smb_home_dir, smb_home_drive)
|
||||
smb_home_dir, smb_home_drive, idp, idp_user_id)
|
||||
certmapdata = convert_certmapdata(certmapdata)
|
||||
|
||||
# Check API specific parameters
|
||||
@@ -1375,6 +1407,19 @@ def main():
|
||||
"smb_profile_path, and smb_home_drive is not supported "
|
||||
"by your IPA version")
|
||||
|
||||
# Check if IdP support is available
|
||||
require_idp = (
|
||||
idp is not None
|
||||
or idp_user_id is not None
|
||||
or userauthtype == "idp"
|
||||
)
|
||||
has_idp_support = ansible_module.ipa_command_param_exists(
|
||||
"user_add", "ipaidpconfiglink"
|
||||
)
|
||||
if require_idp and not has_idp_support:
|
||||
ansible_module.fail_json(
|
||||
msg="Your IPA version does not support External IdP.")
|
||||
|
||||
# Make sure user exists
|
||||
res_find = find_user(ansible_module, name)
|
||||
|
||||
@@ -1390,7 +1435,9 @@ def main():
|
||||
carlicense, sshpubkey, userauthtype, userclass, radius,
|
||||
radiususer, departmentnumber, employeenumber, employeetype,
|
||||
preferredlanguage, smb_logon_script, smb_profile_path,
|
||||
smb_home_dir, smb_home_drive, noprivate, nomembers)
|
||||
smb_home_dir, smb_home_drive, idp, idp_user_id, noprivate,
|
||||
nomembers,
|
||||
)
|
||||
|
||||
if action == "user":
|
||||
# Found the user
|
||||
|
||||
107
tests/user/test_user_idp_attrs.yml
Normal file
107
tests/user/test_user_idp_attrs.yml
Normal file
@@ -0,0 +1,107 @@
|
||||
---
|
||||
- name: Test user
|
||||
hosts: "{{ ipa_test_host | default('ipaserver') }}"
|
||||
become: false
|
||||
gather_facts: false
|
||||
module_defaults:
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
|
||||
tasks:
|
||||
- name: Include tasks ../env_freeipa_facts.yml
|
||||
ansible.builtin.include_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
# CLEANUP TEST ITEMS
|
||||
|
||||
- name: Ensure user idpuser is absent
|
||||
ipauser:
|
||||
name: idpuser
|
||||
state: absent
|
||||
|
||||
# CREATE TEST ITEMS
|
||||
- name: Run tests if FreeIPA 4.10.0+ is installed
|
||||
when: ipa_version is version('4.10.0', '>=')
|
||||
block:
|
||||
- name: Ensure IDP provider is present
|
||||
# TODO: Use an ansible-freeipa plugin instead of 'shell'
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
kinit -c test_krb5_cache admin <<< SomeADMINpassword
|
||||
KRB5CCNAME=test_krb5_cache ipa idp-add keycloak --provider keycloak \
|
||||
--org master \
|
||||
--base-url https://client.ipademo.local:8443/auth \
|
||||
--client-id ipa_oidc_client \
|
||||
--secret <<< $(echo -e "Secret123\nSecret123")
|
||||
kdestroy -c test_krb5_cache -q -A
|
||||
register: addidp
|
||||
failed_when:
|
||||
- '"Added Identity Provider" not in addidp.stdout'
|
||||
- '"already exists" not in addidp.stderr'
|
||||
|
||||
# TESTS
|
||||
|
||||
- name: Ensure user idpuser is present
|
||||
ipauser:
|
||||
name: idpuser
|
||||
first: IDP
|
||||
last: User
|
||||
userauthtype: idp
|
||||
idp: keycloak
|
||||
idp_user_id: "idpuser@ipademo.local"
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure user idpuser is present again
|
||||
ipauser:
|
||||
name: idpuser
|
||||
first: IDP
|
||||
last: User
|
||||
userauthtype: idp
|
||||
idp: keycloak
|
||||
idp_user_id: "idpuser@ipademo.local"
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Clear 'idp_user_id'
|
||||
ipauser:
|
||||
name: idpuser
|
||||
idp_user_id: ""
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Clear 'idp'
|
||||
ipauser:
|
||||
name: idpuser
|
||||
idp: ""
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure user idpuser is absent
|
||||
ipauser:
|
||||
name: idpuser
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure user idpuser is absent again
|
||||
ipauser:
|
||||
name: idpuser
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
|
||||
# CLEANUP TEST ITEMS
|
||||
- name: Ensure IDP provider is absent
|
||||
# TODO: Use an ansible-freeipa plugin instead of 'shell'
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
kinit -c test_krb5_cache admin <<< SomeADMINpassword
|
||||
ipa idp-del keycloak
|
||||
kdestroy -c test_krb5_cache -q -A
|
||||
always:
|
||||
- name: Ensure user idpuser is absent
|
||||
ipauser:
|
||||
name: idpuser
|
||||
state: absent
|
||||
Reference in New Issue
Block a user