mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-26 21:33:05 +00:00
Merge pull request #971 from rjeffman/pwpolicy_update_params
pwpolicy: Add support for password check and grace limit.
This commit is contained in:
@@ -87,6 +87,36 @@ Example playbook to ensure maxlife is set to 49 in global policy:
|
||||
maxlife: 49
|
||||
```
|
||||
|
||||
Example playbook to ensure password grace period is set to 3 in global policy:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to handle pwpolicies
|
||||
hosts: ipaserver
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
# Ensure maxlife is set to 49 in global policy
|
||||
- ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
gracelimit: 3
|
||||
```
|
||||
|
||||
Example playbook to ensure password grace period is set to unlimited in global policy:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to handle pwpolicies
|
||||
hosts: ipaserver
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
# Ensure maxlife is set to 49 in global policy
|
||||
- ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
gracelimit: -1
|
||||
```
|
||||
|
||||
|
||||
Variables
|
||||
=========
|
||||
@@ -107,6 +137,11 @@ Variable | Description | Required
|
||||
`maxfail` \| `krbpwdmaxfailure` | Consecutive failures before lockout. (int) | no
|
||||
`failinterval` \| `krbpwdfailurecountinterval` | Period after which failure count will be reset in seconds. (int) | no
|
||||
`lockouttime` \| `krbpwdlockoutduration` | Period for which lockout is enforced in seconds. (int) | no
|
||||
`maxrepeat` \| `ipapwdmaxrepeat` | Maximum number of same consecutive characters. Requires IPA 4.9+ (int) | no
|
||||
`maxsequence` \| `ipapwdmaxsequence` | The maximum length of monotonic character sequences (abcd). Requires IPA 4.9+ (int) | no
|
||||
`dictcheck` \| `ipapwdictcheck` | Check if the password is a dictionary word. Requires IPA 4.9+ (int) | no
|
||||
`usercheck` \| `ipapwdusercheck` | Check if the password contains the username. Requires IPA 4.9+ (int) | no
|
||||
`gracelimit` \| `passwordgracelimit` | Number of LDAP authentications allowed after expiration. Requires IPA 4.9.10 (int) | no
|
||||
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
|
||||
|
||||
|
||||
|
||||
11
playbooks/pwpolicy/pwpolicy_grace_limit.yml
Normal file
11
playbooks/pwpolicy/pwpolicy_grace_limit.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
- name: Playbook to manage password policy
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
gather_facts: no
|
||||
|
||||
tasks:
|
||||
- name: Set password policy grace limit.
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
gracelimit: 3
|
||||
14
playbooks/pwpolicy/pwpolicy_password_check.yml
Normal file
14
playbooks/pwpolicy/pwpolicy_password_check.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
- name: Playbook to manage password policy
|
||||
hosts: ipaserver
|
||||
become: no
|
||||
gather_facts: no
|
||||
|
||||
tasks:
|
||||
- name: Set password checking parameters.
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
maxrepeat: 2
|
||||
maxsequence: 3
|
||||
dictcheck: yes
|
||||
usercheck: yes
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
# Authors:
|
||||
# Thomas Woerner <twoerner@redhat.com>
|
||||
# Rafael Guterres Jeffman <rjeffman@redhat.com>
|
||||
#
|
||||
# Copyright (C) 2019-2022 Red Hat
|
||||
# see file 'COPYING' for use and warranty information
|
||||
@@ -88,6 +89,41 @@ options:
|
||||
type: int
|
||||
required: false
|
||||
aliases: ["krbpwdlockoutduration"]
|
||||
maxrepeat:
|
||||
description: >
|
||||
Maximum number of same consecutive characters.
|
||||
Requires IPA 4.9+
|
||||
type: int
|
||||
required: false
|
||||
aliases: ["ipapwdmaxrepeat"]
|
||||
maxsequence:
|
||||
description: >
|
||||
The maximum length of monotonic character sequences (abcd).
|
||||
Requires IPA 4.9+
|
||||
type: int
|
||||
required: false
|
||||
aliases: ["ipapwdmaxsequence"]
|
||||
dictcheck:
|
||||
description: >
|
||||
Check if the password is a dictionary word.
|
||||
Requires IPA 4.9+
|
||||
type: bool
|
||||
required: false
|
||||
aliases: ["ipapwdictcheck"]
|
||||
usercheck:
|
||||
description: >
|
||||
Check if the password contains the username.
|
||||
Requires IPA 4.9+
|
||||
type: bool
|
||||
required: false
|
||||
aliases: ["ipapwdusercheck"]
|
||||
gracelimit:
|
||||
description: >
|
||||
Number of LDAP authentications allowed after expiration.
|
||||
Requires IPA 4.10.1+
|
||||
type: int
|
||||
required: false
|
||||
aliases: ["passwordgracelimit"]
|
||||
state:
|
||||
description: State to ensure
|
||||
type: str
|
||||
@@ -95,6 +131,7 @@ options:
|
||||
choices: ["present", "absent"]
|
||||
author:
|
||||
- Thomas Woerner (@t-woerner)
|
||||
- Rafael Guterres Jeffman (@rjeffman)
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
@@ -135,7 +172,8 @@ def find_pwpolicy(module, name):
|
||||
|
||||
|
||||
def gen_args(maxlife, minlife, history, minclasses, minlength, priority,
|
||||
maxfail, failinterval, lockouttime):
|
||||
maxfail, failinterval, lockouttime, maxrepeat, maxsequence,
|
||||
dictcheck, usercheck, gracelimit):
|
||||
_args = {}
|
||||
if maxlife is not None:
|
||||
_args["krbmaxpwdlife"] = maxlife
|
||||
@@ -155,10 +193,47 @@ def gen_args(maxlife, minlife, history, minclasses, minlength, priority,
|
||||
_args["krbpwdfailurecountinterval"] = failinterval
|
||||
if lockouttime is not None:
|
||||
_args["krbpwdlockoutduration"] = lockouttime
|
||||
if maxrepeat is not None:
|
||||
_args["ipapwdmaxrepeat"] = maxrepeat
|
||||
if maxsequence is not None:
|
||||
_args["ipapwdmaxrsequence"] = maxsequence
|
||||
if dictcheck is not None:
|
||||
_args["ipapwddictcheck"] = dictcheck
|
||||
if usercheck is not None:
|
||||
_args["ipapwdusercheck"] = usercheck
|
||||
if gracelimit is not None:
|
||||
_args["passwordgracelimit"] = gracelimit
|
||||
|
||||
return _args
|
||||
|
||||
|
||||
def check_supported_params(
|
||||
module, maxrepeat, maxsequence, dictcheck, usercheck, gracelimit
|
||||
):
|
||||
# All password checking parameters were added by the same commit,
|
||||
# so we only need to test one of them.
|
||||
has_password_check = module.ipa_command_param_exists(
|
||||
"pwpolicy_add", "ipapwdmaxrepeat")
|
||||
# check if gracelimit is supported
|
||||
has_gracelimit = module.ipa_command_param_exists(
|
||||
"pwpolicy_add", "passwordgracelimit")
|
||||
|
||||
# If needed, report unsupported password checking paramteres
|
||||
if not has_password_check:
|
||||
check_password_params = [maxrepeat, maxsequence, dictcheck, usercheck]
|
||||
unsupported = [
|
||||
x for x in check_password_params if x is not None
|
||||
]
|
||||
if unsupported:
|
||||
module.fail_json(
|
||||
msg="Your IPA version does not support arguments: "
|
||||
"maxrepeat, maxsequence, dictcheck, usercheck.")
|
||||
|
||||
if gracelimit is not None and not has_gracelimit:
|
||||
module.fail_json(
|
||||
msg="Your IPA version does not support 'gracelimit'.")
|
||||
|
||||
|
||||
def main():
|
||||
ansible_module = IPAAnsibleModule(
|
||||
argument_spec=dict(
|
||||
@@ -183,6 +258,16 @@ def main():
|
||||
default=None),
|
||||
lockouttime=dict(type="int", aliases=["krbpwdlockoutduration"],
|
||||
default=None),
|
||||
maxrepeat=dict(type="int", aliases=["ipapwdmaxrepeat"],
|
||||
default=None),
|
||||
maxsequence=dict(type="int", aliases=["ipapwdmaxsequence"],
|
||||
default=None),
|
||||
dictcheck=dict(type="bool", aliases=["ipapwdictcheck"],
|
||||
default=None),
|
||||
usercheck=dict(type="bool", aliases=["ipapwusercheck"],
|
||||
default=None),
|
||||
gracelimit=dict(type="int", aliases=["passwordgracelimit"],
|
||||
default=None),
|
||||
# state
|
||||
state=dict(type="str", default="present",
|
||||
choices=["present", "absent"]),
|
||||
@@ -207,6 +292,11 @@ def main():
|
||||
maxfail = ansible_module.params_get("maxfail")
|
||||
failinterval = ansible_module.params_get("failinterval")
|
||||
lockouttime = ansible_module.params_get("lockouttime")
|
||||
maxrepeat = ansible_module.params_get("maxrepeat")
|
||||
maxsequence = ansible_module.params_get("maxsequence")
|
||||
dictcheck = ansible_module.params_get("dictcheck")
|
||||
usercheck = ansible_module.params_get("usercheck")
|
||||
gracelimit = ansible_module.params_get("gracelimit")
|
||||
|
||||
# state
|
||||
state = ansible_module.params_get("state")
|
||||
@@ -230,10 +320,16 @@ def main():
|
||||
msg="'global_policy' can not be made absent.")
|
||||
invalid = ["maxlife", "minlife", "history", "minclasses",
|
||||
"minlength", "priority", "maxfail", "failinterval",
|
||||
"lockouttime"]
|
||||
"lockouttime", "maxrepeat", "maxsequence", "dictcheck",
|
||||
"usercheck", "gracelimit"]
|
||||
|
||||
ansible_module.params_fail_used_invalid(invalid, state)
|
||||
|
||||
if gracelimit is not None:
|
||||
if gracelimit < -1:
|
||||
ansible_module.fail_json(
|
||||
msg="'gracelimit' must be no less than -1")
|
||||
|
||||
# Init
|
||||
|
||||
changed = False
|
||||
@@ -241,6 +337,11 @@ def main():
|
||||
|
||||
with ansible_module.ipa_connect():
|
||||
|
||||
check_supported_params(
|
||||
ansible_module, maxrepeat, maxsequence, dictcheck, usercheck,
|
||||
gracelimit
|
||||
)
|
||||
|
||||
commands = []
|
||||
|
||||
for name in names:
|
||||
@@ -252,7 +353,8 @@ def main():
|
||||
# Generate args
|
||||
args = gen_args(maxlife, minlife, history, minclasses,
|
||||
minlength, priority, maxfail, failinterval,
|
||||
lockouttime)
|
||||
lockouttime, maxrepeat, maxsequence, dictcheck,
|
||||
usercheck, gracelimit)
|
||||
|
||||
# Found the pwpolicy
|
||||
if res_find is not None:
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
gather_facts: false
|
||||
|
||||
tasks:
|
||||
- name: Setup FreeIPA test facts.
|
||||
import_tasks: ../env_freeipa_facts.yml
|
||||
|
||||
- name: Ensure maxlife of 90 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -117,3 +120,145 @@
|
||||
state: absent
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- block:
|
||||
- name: Ensure maxrepeat of 2 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
maxrepeat: 2
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure maxrepeat of 2 for global_policy, again
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
maxrepeat: 2
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure maxrepeat of 0 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
maxrepeat: 0
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure maxsequence of 4 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
maxrepeat: 4
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure maxsequence of 4 for global_policy, again
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
maxrepeat: 4
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure maxsequence of 0 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
maxrepeat: 0
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure dictcheck is set for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
dictcheck: yes
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure dictcheck is set for global_policy, again
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
dictcheck: yes
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure dictcheck is not set for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
dictcheck: no
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure usercheck is set for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
usercheck: yes
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure usercheck is set for global_policy, again
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
usercheck: yes
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure usercheck is not set for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
usercheck: no
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
when: ipa_version is version("4.9", ">=")
|
||||
|
||||
- block:
|
||||
- name: Ensure grace limit is set to 10 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
gracelimit: 10
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure grace limit is set to 0 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
gracelimit: 0
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure grace limit is set to 0 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
gracelimit: 0
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Ensure grace limit is set to 0 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
gracelimit: -1
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Ensure grace limit is not set to -2 for global_policy
|
||||
ipapwpolicy:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
gracelimit: -2
|
||||
register: result
|
||||
failed_when: not result.failed and "must be at least -1" not in result.msg
|
||||
|
||||
when: ipa_version is version("4.9.10", ">=")
|
||||
|
||||
Reference in New Issue
Block a user