win_user: use different method to validate credentials that does not rely on SMB/RPC (#43059)
* win_user: use different method to validate credentials that does not rely on SMB/RPC * Use Add-Type as SetLastError on .net reflection not working on 2012 R2
This commit is contained in:
parent
48ad90ac8e
commit
04431216e7
4 changed files with 570 additions and 436 deletions
2
changelogs/fragments/win_user-validate-fixes.yaml
Normal file
2
changelogs/fragments/win_user-validate-fixes.yaml
Normal file
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- win_user - Use LogonUser to validate the password as it does not rely on SMB/RPC to be available https://github.com/ansible/ansible/issues/24884
|
|
@ -8,6 +8,8 @@
|
|||
########
|
||||
$ADS_UF_PASSWD_CANT_CHANGE = 64
|
||||
$ADS_UF_DONT_EXPIRE_PASSWD = 65536
|
||||
$LOGON32_LOGON_NETWORK = 3
|
||||
$LOGON32_PROVIDER_DEFAULT = 0
|
||||
|
||||
$adsi = [ADSI]"WinNT://$env:COMPUTERNAME"
|
||||
|
||||
|
@ -38,9 +40,81 @@ function Get-Group($grp) {
|
|||
return
|
||||
}
|
||||
|
||||
Function Test-LocalCredential {
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingUserNameAndPassWordParams", "", Justification="We need to use the plaintext pass in the Win32 call, also the source isn't a secure string to using that is just a waste of time/code")]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "", Justification="See above")]
|
||||
param([String]$Username, [String]$Password)
|
||||
|
||||
$platform_util = @'
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ansible
|
||||
{
|
||||
public class WinUserPInvoke
|
||||
{
|
||||
[DllImport("advapi32.dll", SetLastError = true)]
|
||||
public static extern bool LogonUser(
|
||||
string lpszUsername,
|
||||
string lpszDomain,
|
||||
string lpszPassword,
|
||||
UInt32 dwLogonType,
|
||||
UInt32 dwLogonProvider,
|
||||
out IntPtr phToken);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool CloseHandle(
|
||||
IntPtr hObject);
|
||||
}
|
||||
}
|
||||
'@
|
||||
|
||||
$original_tmp = $env:TMP
|
||||
$original_temp = $env:TEMP
|
||||
$env:TMP = $_remote_tmp
|
||||
$env:TEMP = $_remote_tmp
|
||||
Add-Type -TypeDefinition $platform_util
|
||||
$env:TMP = $original_tmp
|
||||
$env:TEMP = $original_temp
|
||||
|
||||
$handle = [IntPtr]::Zero
|
||||
$logon_res = [Ansible.WinUserPInvoke]::LogonUser($Username, $null, $Password,
|
||||
$LOGON32_LOGON_NETWORK, $LOGON32_PROVIDER_DEFAULT, [Ref]$handle)
|
||||
|
||||
if ($logon_res) {
|
||||
$valid_credentials = $true
|
||||
[Ansible.WinUserPInvoke]::CloseHandle($handle) > $null
|
||||
} else {
|
||||
$err_code = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
# following errors indicate the creds are correct but the user was
|
||||
# unable to log on for other reasons, which we don't care about
|
||||
$success_codes = @(
|
||||
0x0000052F, # ERROR_ACCOUNT_RESTRICTION
|
||||
0x00000530, # ERROR_INVALID_LOGON_HOURS
|
||||
0x00000531, # ERROR_INVALID_WORKSTATION
|
||||
0x00000569 # ERROR_LOGON_TYPE_GRANTED
|
||||
)
|
||||
|
||||
if ($err_code -eq 0x0000052E) {
|
||||
# ERROR_LOGON_FAILURE - the user or pass was incorrect
|
||||
$valid_credentials = $false
|
||||
} elseif ($err_code -in $success_codes) {
|
||||
$valid_credentials = $true
|
||||
} else {
|
||||
# an unknown failure, raise an Exception for this
|
||||
$win32_exp = New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $err_code
|
||||
$err_msg = "LogonUserW failed: $($win32_exp.Message) (Win32ErrorCode: $err_code)"
|
||||
throw New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $err_code, $err_msg
|
||||
}
|
||||
}
|
||||
|
||||
return $valid_credentials
|
||||
}
|
||||
|
||||
########
|
||||
|
||||
$params = Parse-Args $args;
|
||||
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
|
||||
|
||||
$result = @{
|
||||
changed = $false
|
||||
|
@ -91,16 +165,16 @@ If ($state -eq 'present') {
|
|||
$result.changed = $true
|
||||
}
|
||||
ElseIf (($password -ne $null) -and ($update_password -eq 'always')) {
|
||||
[void][system.reflection.assembly]::LoadWithPartialName('System.DirectoryServices.AccountManagement')
|
||||
$host_name = [System.Net.Dns]::GetHostName()
|
||||
$pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Machine', $host_name
|
||||
|
||||
# ValidateCredentials will fail if either of these are true- just force update...
|
||||
If($user_obj.AccountDisabled -or $user_obj.PasswordExpired) {
|
||||
$password_match = $false
|
||||
}
|
||||
Else {
|
||||
$password_match = $pc.ValidateCredentials($username, $password)
|
||||
try {
|
||||
$password_match = Test-LocalCredential -Username $username -Password $password
|
||||
} catch [System.ComponentModel.Win32Exception] {
|
||||
Fail-Json -obj $result -message "Failed to validate the user's credentials: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
If (-not $password_match) {
|
||||
|
|
|
@ -1,431 +1,34 @@
|
|||
# test code for the win_user module
|
||||
# (c) 2014, Chris Church <chris@ninemoreminutes.com>
|
||||
---
|
||||
- name: create test group that has a network logon denied
|
||||
win_group:
|
||||
name: win_user-test
|
||||
state: present
|
||||
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible 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.
|
||||
#
|
||||
# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
- name: add test group to SeDenyNetworkLogonRight
|
||||
win_user_right:
|
||||
name: SeDenyNetworkLogonRight
|
||||
users:
|
||||
- win_user-test
|
||||
action: add
|
||||
|
||||
- name: remove existing test user if present
|
||||
win_user: name="{{ test_win_user_name }}" state="absent"
|
||||
register: win_user_remove_result
|
||||
- block:
|
||||
- name: run tests
|
||||
include_tasks: tests.yml
|
||||
|
||||
- name: check user removal result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_result.name"
|
||||
- "win_user_remove_result.state == 'absent'"
|
||||
always:
|
||||
- name: remove SeDenyNetworkLogonRight on test group
|
||||
win_user_right:
|
||||
name: SeDenyNetworkLogonRight
|
||||
users:
|
||||
- win_user-test
|
||||
action: remove
|
||||
|
||||
- name: try to remove test user again
|
||||
win_user: name="{{ test_win_user_name }}" state="absent"
|
||||
register: win_user_remove_result_again
|
||||
- name: remove test group
|
||||
win_group:
|
||||
name: win_user-test
|
||||
state: absent
|
||||
|
||||
- name: check user removal result again
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_result_again is not changed"
|
||||
- "win_user_remove_result_again.name"
|
||||
- "win_user_remove_result_again.msg"
|
||||
- "win_user_remove_result.state == 'absent'"
|
||||
|
||||
- name: test missing user with query state
|
||||
win_user: name="{{ test_win_user_name }}" state="query"
|
||||
register: win_user_missing_query_result
|
||||
|
||||
- name: check missing query result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_missing_query_result is not changed"
|
||||
- "win_user_missing_query_result.name"
|
||||
- "win_user_missing_query_result.msg"
|
||||
- "win_user_missing_query_result.state == 'absent'"
|
||||
|
||||
- name: test create user
|
||||
win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password }}" fullname="Test User" description="Test user account" groups="Guests"
|
||||
register: win_user_create_result
|
||||
|
||||
- name: check user creation result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_create_result is changed"
|
||||
- "win_user_create_result.name == '{{ test_win_user_name }}'"
|
||||
- "win_user_create_result.fullname == 'Test User'"
|
||||
- "win_user_create_result.description == 'Test user account'"
|
||||
- "win_user_create_result.path"
|
||||
- "win_user_create_result.state == 'present'"
|
||||
|
||||
- name: update user full name and description
|
||||
win_user: name="{{ test_win_user_name }}" fullname="Test Ansible User" description="Test user account created by Ansible" groups=""
|
||||
register: win_user_update_result
|
||||
|
||||
- name: check full name and description update result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_update_result is changed"
|
||||
- "win_user_update_result.fullname == 'Test Ansible User'"
|
||||
- "win_user_update_result.description == 'Test user account created by Ansible'"
|
||||
|
||||
- name: update user full name and description again with same values
|
||||
win_user: name="{{ test_win_user_name }}" fullname="Test Ansible User" description="Test user account created by Ansible"
|
||||
register: win_user_update_result_again
|
||||
|
||||
- name: check full name and description result again
|
||||
assert:
|
||||
that:
|
||||
- "win_user_update_result_again is not changed"
|
||||
- "win_user_update_result_again.fullname == 'Test Ansible User'"
|
||||
- "win_user_update_result_again.description == 'Test user account created by Ansible'"
|
||||
|
||||
- name: test again with no options or changes
|
||||
win_user: name="{{ test_win_user_name }}"
|
||||
register: win_user_nochange_result
|
||||
|
||||
- name: check no changes result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_nochange_result is not changed"
|
||||
|
||||
- name: test again with query state
|
||||
win_user: name="{{ test_win_user_name }}" state="query"
|
||||
register: win_user_query_result
|
||||
|
||||
- name: check query result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_query_result is not changed"
|
||||
- "win_user_query_result.state == 'present'"
|
||||
- "win_user_query_result.name == '{{ test_win_user_name }}'"
|
||||
- "win_user_query_result.fullname == 'Test Ansible User'"
|
||||
- "win_user_query_result.description == 'Test user account created by Ansible'"
|
||||
- "win_user_query_result.path"
|
||||
- "win_user_query_result.sid"
|
||||
- "win_user_query_result.groups == []"
|
||||
|
||||
- name: change user password
|
||||
win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password2 }}"
|
||||
register: win_user_password_result
|
||||
|
||||
- name: check password change result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_result is changed"
|
||||
|
||||
- name: change user password again to same value
|
||||
win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password2 }}"
|
||||
register: win_user_password_result_again
|
||||
|
||||
- name: check password change result again
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_result_again is not changed"
|
||||
|
||||
- name: check update_password=on_create for existing user
|
||||
win_user: name="{{ test_win_user_name }}" password="ThisP@ssW0rdShouldNotBeUsed" update_password=on_create
|
||||
register: win_user_nopasschange_result
|
||||
|
||||
- name: check password change with on_create flag result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_nopasschange_result is not changed"
|
||||
|
||||
- name: set password expired flag
|
||||
win_user: name="{{ test_win_user_name }}" password_expired=yes
|
||||
register: win_user_password_expired_result
|
||||
|
||||
- name: check password expired result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_expired_result is changed"
|
||||
- "win_user_password_expired_result.password_expired"
|
||||
|
||||
- name: set password when expired
|
||||
win_user: name="{{ test_win_user_name }}" password={{ test_win_user_password2 }} update_password=always
|
||||
register: win_user_can_set_password_on_expired
|
||||
|
||||
- name: check set password on expired result
|
||||
assert:
|
||||
that:
|
||||
- win_user_can_set_password_on_expired is changed
|
||||
|
||||
- name: set password expired flag again
|
||||
win_user: name="{{ test_win_user_name }}" password_expired=yes
|
||||
register: win_user_password_expired_result
|
||||
|
||||
- name: check password expired result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_expired_result is changed"
|
||||
- "win_user_password_expired_result.password_expired"
|
||||
|
||||
- name: clear password expired flag
|
||||
win_user: name="{{ test_win_user_name }}" password_expired=no
|
||||
register: win_user_clear_password_expired_result
|
||||
|
||||
- name: check clear password expired result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_clear_password_expired_result is changed"
|
||||
- "not win_user_clear_password_expired_result.password_expired"
|
||||
|
||||
- name: set password never expires flag
|
||||
win_user: name="{{ test_win_user_name }}" password_never_expires=yes
|
||||
register: win_user_password_never_expires_result
|
||||
|
||||
- name: check password never expires result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_never_expires_result is changed"
|
||||
- "win_user_password_never_expires_result.password_never_expires"
|
||||
|
||||
- name: clear password never expires flag
|
||||
win_user: name="{{ test_win_user_name }}" password_never_expires=no
|
||||
register: win_user_clear_password_never_expires_result
|
||||
|
||||
- name: check clear password never expires result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_clear_password_never_expires_result is changed"
|
||||
- "not win_user_clear_password_never_expires_result.password_never_expires"
|
||||
|
||||
- name: set user cannot change password flag
|
||||
win_user: name="{{ test_win_user_name }}" user_cannot_change_password=yes
|
||||
register: win_user_cannot_change_password_result
|
||||
|
||||
- name: check user cannot change password result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_cannot_change_password_result is changed"
|
||||
- "win_user_cannot_change_password_result.user_cannot_change_password"
|
||||
|
||||
- name: clear user cannot change password flag
|
||||
win_user: name="{{ test_win_user_name }}" user_cannot_change_password=no
|
||||
register: win_user_can_change_password_result
|
||||
|
||||
- name: check clear user cannot change password result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_can_change_password_result is changed"
|
||||
- "not win_user_can_change_password_result.user_cannot_change_password"
|
||||
|
||||
- name: set account disabled flag
|
||||
win_user: name="{{ test_win_user_name }}" account_disabled=true
|
||||
register: win_user_account_disabled_result
|
||||
|
||||
- name: check account disabled result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_account_disabled_result is changed"
|
||||
- "win_user_account_disabled_result.account_disabled"
|
||||
|
||||
- name: set password on disabled account
|
||||
win_user: name="{{ test_win_user_name }}" password={{ test_win_user_password2 }} update_password=always
|
||||
register: win_user_can_set_password_on_disabled
|
||||
|
||||
- name: check set password on disabled result
|
||||
assert:
|
||||
that:
|
||||
- win_user_can_set_password_on_disabled is changed
|
||||
- win_user_can_set_password_on_disabled.account_disabled
|
||||
|
||||
- name: clear account disabled flag
|
||||
win_user: name="{{ test_win_user_name }}" account_disabled=false
|
||||
register: win_user_clear_account_disabled_result
|
||||
|
||||
- name: check clear account disabled result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_clear_account_disabled_result is changed"
|
||||
- "not win_user_clear_account_disabled_result.account_disabled"
|
||||
|
||||
- name: attempt to set account locked flag
|
||||
win_user: name="{{ test_win_user_name }}" account_locked=yes
|
||||
register: win_user_set_account_locked_result
|
||||
ignore_errors: true
|
||||
|
||||
- name: verify that attempting to set account locked flag fails
|
||||
assert:
|
||||
that:
|
||||
- "win_user_set_account_locked_result is failed"
|
||||
- "win_user_set_account_locked_result is not changed"
|
||||
|
||||
- name: attempt to lockout test account
|
||||
script: lockout_user.ps1 "{{ test_win_user_name }}"
|
||||
|
||||
- name: get user to check if account locked flag is set
|
||||
win_user: name="{{ test_win_user_name }}" state="query"
|
||||
register: win_user_account_locked_result
|
||||
|
||||
- name: clear account locked flag if set
|
||||
win_user: name="{{ test_win_user_name }}" account_locked=no
|
||||
register: win_user_clear_account_locked_result
|
||||
when: "win_user_account_locked_result.account_locked"
|
||||
|
||||
- name: check clear account lockout result if account was locked
|
||||
assert:
|
||||
that:
|
||||
- "win_user_clear_account_locked_result is changed"
|
||||
- "not win_user_clear_account_locked_result.account_locked"
|
||||
when: "win_user_account_locked_result.account_locked"
|
||||
|
||||
- name: assign test user to a group
|
||||
win_user: name="{{ test_win_user_name }}" groups="Users"
|
||||
register: win_user_replace_groups_result
|
||||
|
||||
- name: check assign user to group result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_replace_groups_result is changed"
|
||||
- "win_user_replace_groups_result.groups|length == 1"
|
||||
- "win_user_replace_groups_result.groups[0]['name'] == 'Users'"
|
||||
|
||||
- name: assign test user to the same group
|
||||
- name: remove the test user
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups: ["Users"]
|
||||
register: win_user_replace_groups_again_result
|
||||
|
||||
- name: check assign user to group again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_replace_groups_again_result is not changed"
|
||||
|
||||
- name: add user to another group
|
||||
win_user: name="{{ test_win_user_name }}" groups="Power Users" groups_action="add"
|
||||
register: win_user_add_groups_result
|
||||
|
||||
- name: check add user to another group result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_add_groups_result is changed"
|
||||
- "win_user_add_groups_result.groups|length == 2"
|
||||
- "win_user_add_groups_result.groups[0]['name'] in ('Users', 'Power Users')"
|
||||
- "win_user_add_groups_result.groups[1]['name'] in ('Users', 'Power Users')"
|
||||
|
||||
- name: add user to another group again
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups: "Power Users"
|
||||
groups_action: add
|
||||
register: win_user_add_groups_again_result
|
||||
|
||||
- name: check add user to another group again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_add_groups_again_result is not changed"
|
||||
|
||||
- name: remove user from a group
|
||||
win_user: name="{{ test_win_user_name }}" groups="Users" groups_action="remove"
|
||||
register: win_user_remove_groups_result
|
||||
|
||||
- name: check remove user from group result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_groups_result is changed"
|
||||
- "win_user_remove_groups_result.groups|length == 1"
|
||||
- "win_user_remove_groups_result.groups[0]['name'] == 'Power Users'"
|
||||
|
||||
- name: remove user from a group again
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups:
|
||||
- "Users"
|
||||
groups_action: remove
|
||||
register: win_user_remove_groups_again_result
|
||||
|
||||
- name: check remove user from group again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_groups_again_result is not changed"
|
||||
|
||||
- name: reassign test user to multiple groups
|
||||
win_user: name="{{ test_win_user_name }}" groups="Users, Guests" groups_action="replace"
|
||||
register: win_user_reassign_groups_result
|
||||
|
||||
- name: check reassign user groups result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_reassign_groups_result is changed"
|
||||
- "win_user_reassign_groups_result.groups|length == 2"
|
||||
- "win_user_reassign_groups_result.groups[0]['name'] in ('Users', 'Guests')"
|
||||
- "win_user_reassign_groups_result.groups[1]['name'] in ('Users', 'Guests')"
|
||||
|
||||
- name: reassign test user to multiple groups again
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups:
|
||||
- "Users"
|
||||
- "Guests"
|
||||
groups_action: replace
|
||||
register: win_user_reassign_groups_again_result
|
||||
|
||||
- name: check reassign user groups again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_reassign_groups_again_result is not changed"
|
||||
|
||||
- name: remove user from all groups
|
||||
win_user: name="{{ test_win_user_name }}" groups=""
|
||||
register: win_user_remove_all_groups_result
|
||||
|
||||
- name: check remove user from all groups result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_all_groups_result is changed"
|
||||
- "win_user_remove_all_groups_result.groups|length == 0"
|
||||
|
||||
- name: remove user from all groups again
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups: []
|
||||
register: win_user_remove_all_groups_again_result
|
||||
|
||||
- name: check remove user from all groups again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_all_groups_again_result is not changed"
|
||||
|
||||
- name: assign user to invalid group
|
||||
win_user: name="{{ test_win_user_name }}" groups="Userz"
|
||||
register: win_user_invalid_group_result
|
||||
ignore_errors: true
|
||||
|
||||
- name: check invalid group result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_invalid_group_result is failed"
|
||||
- "win_user_invalid_group_result.msg"
|
||||
- win_user_invalid_group_result.msg is match("group 'Userz' not found")
|
||||
|
||||
- name: remove test user when finished
|
||||
win_user: name="{{ test_win_user_name }}" state="absent"
|
||||
register: win_user_final_remove_result
|
||||
|
||||
- name: check final user removal result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_final_remove_result is changed"
|
||||
- "win_user_final_remove_result.name"
|
||||
- "win_user_final_remove_result.msg"
|
||||
- "win_user_final_remove_result.state == 'absent'"
|
||||
|
||||
- name: test removed user with query state
|
||||
win_user: name="{{ test_win_user_name }}" state="query"
|
||||
register: win_user_removed_query_result
|
||||
|
||||
- name: check removed query result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_removed_query_result is not changed"
|
||||
- "win_user_removed_query_result.name"
|
||||
- "win_user_removed_query_result.msg"
|
||||
- "win_user_removed_query_result.state == 'absent'"
|
||||
name: '{{ test_win_user_name }}'
|
||||
state: absent
|
||||
|
|
455
test/integration/targets/win_user/tasks/tests.yml
Normal file
455
test/integration/targets/win_user/tasks/tests.yml
Normal file
|
@ -0,0 +1,455 @@
|
|||
# test code for the win_user module
|
||||
# (c) 2014, Chris Church <chris@ninemoreminutes.com>
|
||||
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible 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.
|
||||
#
|
||||
# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
- name: remove existing test user if present
|
||||
win_user: name="{{ test_win_user_name }}" state="absent"
|
||||
register: win_user_remove_result
|
||||
|
||||
- name: check user removal result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_result.name"
|
||||
- "win_user_remove_result.state == 'absent'"
|
||||
|
||||
- name: try to remove test user again
|
||||
win_user: name="{{ test_win_user_name }}" state="absent"
|
||||
register: win_user_remove_result_again
|
||||
|
||||
- name: check user removal result again
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_result_again is not changed"
|
||||
- "win_user_remove_result_again.name"
|
||||
- "win_user_remove_result_again.msg"
|
||||
- "win_user_remove_result.state == 'absent'"
|
||||
|
||||
- name: test missing user with query state
|
||||
win_user: name="{{ test_win_user_name }}" state="query"
|
||||
register: win_user_missing_query_result
|
||||
|
||||
- name: check missing query result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_missing_query_result is not changed"
|
||||
- "win_user_missing_query_result.name"
|
||||
- "win_user_missing_query_result.msg"
|
||||
- "win_user_missing_query_result.state == 'absent'"
|
||||
|
||||
- name: test create user
|
||||
win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password }}" fullname="Test User" description="Test user account" groups="Guests"
|
||||
register: win_user_create_result
|
||||
|
||||
- name: check user creation result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_create_result is changed"
|
||||
- "win_user_create_result.name == '{{ test_win_user_name }}'"
|
||||
- "win_user_create_result.fullname == 'Test User'"
|
||||
- "win_user_create_result.description == 'Test user account'"
|
||||
- "win_user_create_result.path"
|
||||
- "win_user_create_result.state == 'present'"
|
||||
|
||||
- name: update user full name and description
|
||||
win_user: name="{{ test_win_user_name }}" fullname="Test Ansible User" description="Test user account created by Ansible" groups=""
|
||||
register: win_user_update_result
|
||||
|
||||
- name: check full name and description update result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_update_result is changed"
|
||||
- "win_user_update_result.fullname == 'Test Ansible User'"
|
||||
- "win_user_update_result.description == 'Test user account created by Ansible'"
|
||||
|
||||
- name: update user full name and description again with same values
|
||||
win_user: name="{{ test_win_user_name }}" fullname="Test Ansible User" description="Test user account created by Ansible"
|
||||
register: win_user_update_result_again
|
||||
|
||||
- name: check full name and description result again
|
||||
assert:
|
||||
that:
|
||||
- "win_user_update_result_again is not changed"
|
||||
- "win_user_update_result_again.fullname == 'Test Ansible User'"
|
||||
- "win_user_update_result_again.description == 'Test user account created by Ansible'"
|
||||
|
||||
- name: test again with no options or changes
|
||||
win_user: name="{{ test_win_user_name }}"
|
||||
register: win_user_nochange_result
|
||||
|
||||
- name: check no changes result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_nochange_result is not changed"
|
||||
|
||||
- name: test again with query state
|
||||
win_user: name="{{ test_win_user_name }}" state="query"
|
||||
register: win_user_query_result
|
||||
|
||||
- name: check query result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_query_result is not changed"
|
||||
- "win_user_query_result.state == 'present'"
|
||||
- "win_user_query_result.name == '{{ test_win_user_name }}'"
|
||||
- "win_user_query_result.fullname == 'Test Ansible User'"
|
||||
- "win_user_query_result.description == 'Test user account created by Ansible'"
|
||||
- "win_user_query_result.path"
|
||||
- "win_user_query_result.sid"
|
||||
- "win_user_query_result.groups == []"
|
||||
|
||||
- name: change user password
|
||||
win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password2 }}"
|
||||
register: win_user_password_result
|
||||
|
||||
- name: check password change result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_result is changed"
|
||||
|
||||
- name: change user password again to same value
|
||||
win_user: name="{{ test_win_user_name }}" password="{{ test_win_user_password2 }}"
|
||||
register: win_user_password_result_again
|
||||
|
||||
- name: check password change result again
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_result_again is not changed"
|
||||
|
||||
- name: check update_password=on_create for existing user
|
||||
win_user: name="{{ test_win_user_name }}" password="ThisP@ssW0rdShouldNotBeUsed" update_password=on_create
|
||||
register: win_user_nopasschange_result
|
||||
|
||||
- name: check password change with on_create flag result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_nopasschange_result is not changed"
|
||||
|
||||
- name: set password expired flag
|
||||
win_user: name="{{ test_win_user_name }}" password_expired=yes
|
||||
register: win_user_password_expired_result
|
||||
|
||||
- name: check password expired result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_expired_result is changed"
|
||||
- "win_user_password_expired_result.password_expired"
|
||||
|
||||
- name: set password when expired
|
||||
win_user: name="{{ test_win_user_name }}" password={{ test_win_user_password2 }} update_password=always
|
||||
register: win_user_can_set_password_on_expired
|
||||
|
||||
- name: check set password on expired result
|
||||
assert:
|
||||
that:
|
||||
- win_user_can_set_password_on_expired is changed
|
||||
|
||||
- name: set password expired flag again
|
||||
win_user: name="{{ test_win_user_name }}" password_expired=yes
|
||||
register: win_user_password_expired_result
|
||||
|
||||
- name: check password expired result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_expired_result is changed"
|
||||
- "win_user_password_expired_result.password_expired"
|
||||
|
||||
- name: clear password expired flag
|
||||
win_user: name="{{ test_win_user_name }}" password_expired=no
|
||||
register: win_user_clear_password_expired_result
|
||||
|
||||
- name: check clear password expired result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_clear_password_expired_result is changed"
|
||||
- "not win_user_clear_password_expired_result.password_expired"
|
||||
|
||||
- name: set password never expires flag
|
||||
win_user: name="{{ test_win_user_name }}" password_never_expires=yes
|
||||
register: win_user_password_never_expires_result
|
||||
|
||||
- name: check password never expires result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_password_never_expires_result is changed"
|
||||
- "win_user_password_never_expires_result.password_never_expires"
|
||||
|
||||
- name: clear password never expires flag
|
||||
win_user: name="{{ test_win_user_name }}" password_never_expires=no
|
||||
register: win_user_clear_password_never_expires_result
|
||||
|
||||
- name: check clear password never expires result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_clear_password_never_expires_result is changed"
|
||||
- "not win_user_clear_password_never_expires_result.password_never_expires"
|
||||
|
||||
- name: set user cannot change password flag
|
||||
win_user: name="{{ test_win_user_name }}" user_cannot_change_password=yes
|
||||
register: win_user_cannot_change_password_result
|
||||
|
||||
- name: check user cannot change password result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_cannot_change_password_result is changed"
|
||||
- "win_user_cannot_change_password_result.user_cannot_change_password"
|
||||
|
||||
- name: clear user cannot change password flag
|
||||
win_user: name="{{ test_win_user_name }}" user_cannot_change_password=no
|
||||
register: win_user_can_change_password_result
|
||||
|
||||
- name: check clear user cannot change password result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_can_change_password_result is changed"
|
||||
- "not win_user_can_change_password_result.user_cannot_change_password"
|
||||
|
||||
- name: set account disabled flag
|
||||
win_user: name="{{ test_win_user_name }}" account_disabled=true
|
||||
register: win_user_account_disabled_result
|
||||
|
||||
- name: check account disabled result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_account_disabled_result is changed"
|
||||
- "win_user_account_disabled_result.account_disabled"
|
||||
|
||||
- name: set password on disabled account
|
||||
win_user: name="{{ test_win_user_name }}" password={{ test_win_user_password2 }} update_password=always
|
||||
register: win_user_can_set_password_on_disabled
|
||||
|
||||
- name: check set password on disabled result
|
||||
assert:
|
||||
that:
|
||||
- win_user_can_set_password_on_disabled is changed
|
||||
- win_user_can_set_password_on_disabled.account_disabled
|
||||
|
||||
- name: clear account disabled flag
|
||||
win_user: name="{{ test_win_user_name }}" account_disabled=false
|
||||
register: win_user_clear_account_disabled_result
|
||||
|
||||
- name: check clear account disabled result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_clear_account_disabled_result is changed"
|
||||
- "not win_user_clear_account_disabled_result.account_disabled"
|
||||
|
||||
- name: attempt to set account locked flag
|
||||
win_user: name="{{ test_win_user_name }}" account_locked=yes
|
||||
register: win_user_set_account_locked_result
|
||||
ignore_errors: true
|
||||
|
||||
- name: verify that attempting to set account locked flag fails
|
||||
assert:
|
||||
that:
|
||||
- "win_user_set_account_locked_result is failed"
|
||||
- "win_user_set_account_locked_result is not changed"
|
||||
|
||||
- name: attempt to lockout test account
|
||||
script: lockout_user.ps1 "{{ test_win_user_name }}"
|
||||
|
||||
- name: get user to check if account locked flag is set
|
||||
win_user: name="{{ test_win_user_name }}" state="query"
|
||||
register: win_user_account_locked_result
|
||||
|
||||
- name: clear account locked flag if set
|
||||
win_user: name="{{ test_win_user_name }}" account_locked=no
|
||||
register: win_user_clear_account_locked_result
|
||||
when: "win_user_account_locked_result.account_locked"
|
||||
|
||||
- name: check clear account lockout result if account was locked
|
||||
assert:
|
||||
that:
|
||||
- "win_user_clear_account_locked_result is changed"
|
||||
- "not win_user_clear_account_locked_result.account_locked"
|
||||
when: "win_user_account_locked_result.account_locked"
|
||||
|
||||
- name: assign test user to a group
|
||||
win_user: name="{{ test_win_user_name }}" groups="Users"
|
||||
register: win_user_replace_groups_result
|
||||
|
||||
- name: check assign user to group result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_replace_groups_result is changed"
|
||||
- "win_user_replace_groups_result.groups|length == 1"
|
||||
- "win_user_replace_groups_result.groups[0]['name'] == 'Users'"
|
||||
|
||||
- name: assign test user to the same group
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups: ["Users"]
|
||||
register: win_user_replace_groups_again_result
|
||||
|
||||
- name: check assign user to group again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_replace_groups_again_result is not changed"
|
||||
|
||||
- name: add user to another group
|
||||
win_user: name="{{ test_win_user_name }}" groups="Power Users" groups_action="add"
|
||||
register: win_user_add_groups_result
|
||||
|
||||
- name: check add user to another group result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_add_groups_result is changed"
|
||||
- "win_user_add_groups_result.groups|length == 2"
|
||||
- "win_user_add_groups_result.groups[0]['name'] in ('Users', 'Power Users')"
|
||||
- "win_user_add_groups_result.groups[1]['name'] in ('Users', 'Power Users')"
|
||||
|
||||
- name: add user to another group again
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups: "Power Users"
|
||||
groups_action: add
|
||||
register: win_user_add_groups_again_result
|
||||
|
||||
- name: check add user to another group again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_add_groups_again_result is not changed"
|
||||
|
||||
- name: remove user from a group
|
||||
win_user: name="{{ test_win_user_name }}" groups="Users" groups_action="remove"
|
||||
register: win_user_remove_groups_result
|
||||
|
||||
- name: check remove user from group result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_groups_result is changed"
|
||||
- "win_user_remove_groups_result.groups|length == 1"
|
||||
- "win_user_remove_groups_result.groups[0]['name'] == 'Power Users'"
|
||||
|
||||
- name: remove user from a group again
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups:
|
||||
- "Users"
|
||||
groups_action: remove
|
||||
register: win_user_remove_groups_again_result
|
||||
|
||||
- name: check remove user from group again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_groups_again_result is not changed"
|
||||
|
||||
- name: reassign test user to multiple groups
|
||||
win_user: name="{{ test_win_user_name }}" groups="Users, Guests" groups_action="replace"
|
||||
register: win_user_reassign_groups_result
|
||||
|
||||
- name: check reassign user groups result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_reassign_groups_result is changed"
|
||||
- "win_user_reassign_groups_result.groups|length == 2"
|
||||
- "win_user_reassign_groups_result.groups[0]['name'] in ('Users', 'Guests')"
|
||||
- "win_user_reassign_groups_result.groups[1]['name'] in ('Users', 'Guests')"
|
||||
|
||||
- name: reassign test user to multiple groups again
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups:
|
||||
- "Users"
|
||||
- "Guests"
|
||||
groups_action: replace
|
||||
register: win_user_reassign_groups_again_result
|
||||
|
||||
- name: check reassign user groups again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_reassign_groups_again_result is not changed"
|
||||
|
||||
- name: remove user from all groups
|
||||
win_user: name="{{ test_win_user_name }}" groups=""
|
||||
register: win_user_remove_all_groups_result
|
||||
|
||||
- name: check remove user from all groups result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_all_groups_result is changed"
|
||||
- "win_user_remove_all_groups_result.groups|length == 0"
|
||||
|
||||
- name: remove user from all groups again
|
||||
win_user:
|
||||
name: "{{ test_win_user_name }}"
|
||||
groups: []
|
||||
register: win_user_remove_all_groups_again_result
|
||||
|
||||
- name: check remove user from all groups again result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_remove_all_groups_again_result is not changed"
|
||||
|
||||
- name: assign user to invalid group
|
||||
win_user: name="{{ test_win_user_name }}" groups="Userz"
|
||||
register: win_user_invalid_group_result
|
||||
ignore_errors: true
|
||||
|
||||
- name: check invalid group result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_invalid_group_result is failed"
|
||||
- "win_user_invalid_group_result.msg"
|
||||
- win_user_invalid_group_result.msg is match("group 'Userz' not found")
|
||||
|
||||
- name: remove test user when finished
|
||||
win_user: name="{{ test_win_user_name }}" state="absent"
|
||||
register: win_user_final_remove_result
|
||||
|
||||
- name: check final user removal result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_final_remove_result is changed"
|
||||
- "win_user_final_remove_result.name"
|
||||
- "win_user_final_remove_result.msg"
|
||||
- "win_user_final_remove_result.state == 'absent'"
|
||||
|
||||
- name: test removed user with query state
|
||||
win_user: name="{{ test_win_user_name }}" state="query"
|
||||
register: win_user_removed_query_result
|
||||
|
||||
- name: check removed query result
|
||||
assert:
|
||||
that:
|
||||
- "win_user_removed_query_result is not changed"
|
||||
- "win_user_removed_query_result.name"
|
||||
- "win_user_removed_query_result.msg"
|
||||
- "win_user_removed_query_result.state == 'absent'"
|
||||
|
||||
# Tests the Test-Credential path where LogonUser fails if the user does not
|
||||
# have the right for a network logon
|
||||
- name: add new user that has the right SeDenyNetworkLogonRight
|
||||
win_user:
|
||||
name: '{{ test_win_user_name }}'
|
||||
password: '{{ test_win_user_password2 }}'
|
||||
state: present
|
||||
groups:
|
||||
- win_user-test
|
||||
|
||||
- name: add new user that has the right SeDenyNetworkLogonRight (idempotent)
|
||||
win_user:
|
||||
name: '{{ test_win_user_name }}'
|
||||
password: '{{ test_win_user_password2 }}'
|
||||
state: present
|
||||
groups:
|
||||
- win_user-test
|
||||
register: deny_network_idempotent
|
||||
|
||||
- name: assert add new user that has the right SeDenyNetworkLogonRight (idempotent)
|
||||
assert:
|
||||
that:
|
||||
- not deny_network_idempotent is changed
|
Loading…
Reference in a new issue