forked from ansible/ansible
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added powershell SID utils for shared common code (ansible#27091)
* Added powershell SID utils for shared common code * rebased from upstream and fixed up module util after change
- Loading branch information
Showing
3 changed files
with
159 additions
and
0 deletions.
There are no files selected for viewing
85 changes: 85 additions & 0 deletions
85
lib/ansible/module_utils/powershell/Ansible.ModuleUtils.SID.psm1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
# Copyright (c) 2017 Ansible Project | ||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) | ||
|
||
Function Convert-FromSID($sid) { | ||
# Converts a SID to a Down-Level Logon name in the form of DOMAIN\UserName | ||
# If the SID is for a local user or group then DOMAIN would be the server | ||
# name. | ||
|
||
$account_object = New-Object System.Security.Principal.SecurityIdentifier($sid) | ||
try { | ||
$nt_account = $account_object.Translate([System.Security.Principal.NTAccount]) | ||
} catch { | ||
Fail-Json -obj @{} -message "failed to convert sid '$sid' to a logon name: $($_.Exception.Message)" | ||
} | ||
|
||
return $nt_account.Value | ||
} | ||
|
||
Function Convert-ToSID($account_name) { | ||
# Converts an account name to a SID, it can take in the following forms | ||
# UPN: | ||
# principal@domain (Domain users only) | ||
# Down-Level Login Name | ||
# DOMAIN\principal (Domain) | ||
# SERVERNAME\principal (Local) | ||
# .\principal (Local) | ||
# NT AUTHORITY\SYSTEM (Local Service Accounts) | ||
# Login Name | ||
# principal (Local/Local Service Accounts) | ||
|
||
if ($account_name -like "*\*") { | ||
$account_name_split = $account_name -split "\\" | ||
if ($account_name_split[0] -eq ".") { | ||
$domain = $env:COMPUTERNAME | ||
} else { | ||
$domain = $account_name_split[0] | ||
} | ||
$username = $account_name_split[1] | ||
} elseif ($account_name -like "*@*") { | ||
$account_name_split = $account_name -split "@" | ||
$domain = $account_name_split[1] | ||
$username = $account_name_split[0] | ||
} else { | ||
$domain = $null | ||
$username = $account_name | ||
} | ||
|
||
if ($domain) { | ||
# searching for a local group with the servername prefixed will fail, | ||
# need to check for this situation and only use NTAccount(String) | ||
if ($domain -eq $env:COMPUTERNAME) { | ||
$adsi = [ADSI]("WinNT://$env:COMPUTERNAME,computer") | ||
$group = $adsi.psbase.children | Where-Object { $_.schemaClassName -eq "group" -and $_.Name -eq $username } | ||
} else { | ||
$group = $null | ||
} | ||
if ($group) { | ||
$account = New-Object System.Security.Principal.NTAccount($username) | ||
} else { | ||
$account = New-Object System.Security.Principal.NTAccount($domain, $username) | ||
} | ||
} else { | ||
# when in a domain NTAccount(String) will favour domain lookups check | ||
# if username is a local user and explictly search on the localhost for | ||
# that account | ||
$adsi = [ADSI]("WinNT://$env:COMPUTERNAME,computer") | ||
$user = $adsi.psbase.children | Where-Object { $_.schemaClassName -eq "user" -and $_.Name -eq $username } | ||
if ($user) { | ||
$account = New-Object System.Security.Principal.NTAccount($env:COMPUTERNAME, $username) | ||
} else { | ||
$account = New-Object System.Security.Principal.NTAccount($username) | ||
} | ||
} | ||
|
||
try { | ||
$account_sid = $account.Translate([System.Security.Principal.SecurityIdentifier]) | ||
} catch { | ||
Fail-Json @{} "account_name $account_name is not a valid account, cannot get SID: $($_.Exception.Message)" | ||
} | ||
|
||
return $account_sid.Value | ||
} | ||
|
||
# this line must stay at the bottom to ensure all defined module parts are exported | ||
Export-ModuleMember -Alias * -Function * -Cmdlet * |
66 changes: 66 additions & 0 deletions
66
test/integration/targets/win_module_utils/library/sid_utils_test.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#!powershell | ||
|
||
#Requires -Module Ansible.ModuleUtils.Legacy | ||
#Requires -Module Ansible.ModuleUtils.SID | ||
|
||
Function Assert-Equals($actual, $expected) { | ||
if ($actual -ne $expected) { | ||
Fail-Json @{} "actual != expected`nActual: $actual`nExpected: $expected" | ||
} | ||
} | ||
|
||
Function Get-ComputerSID() { | ||
# this is sort off cheating but I can't see any better way of getting this SID | ||
$admin_sid = Convert-ToSID -account_name "$env:COMPUTERNAME\Administrator" | ||
|
||
return $admin_sid.Substring(0, $admin_sid.Length - 4) | ||
} | ||
|
||
$local_sid = Get-ComputerSID | ||
|
||
### Set this to the NETBIOS name of the domain you wish to test, not set for shippable ### | ||
$test_domain = $null | ||
|
||
$tests = @( | ||
# Local Users | ||
@{ sid = "S-1-1-0"; full_name = "Everyone"; names = @("Everyone") }, | ||
@{ sid = "S-1-5-18"; full_name = "NT AUTHORITY\SYSTEM"; names = @("NT AUTHORITY\SYSTEM", "SYSTEM") }, | ||
@{ sid = "S-1-5-20"; full_name = "NT AUTHORITY\NETWORK SERVICE"; names = @("NT AUTHORITY\NETWORK SERVICE", "NETWORK SERVICE") }, | ||
@{ sid = "$local_sid-500"; full_name = "$env:COMPUTERNAME\Administrator"; names = @("$env:COMPUTERNAME\Administrator", "Administrator", ".\Administrator") }, | ||
|
||
# Local Groups | ||
@{ sid = "S-1-5-32-544"; full_name = "BUILTIN\Administrators"; names = @("BUILTIN\Administrators", "Administrators", ".\Administrators") } | ||
) | ||
|
||
# Add domain tests if the domain name has been set | ||
if ($test_domain -ne $null) { | ||
Import-Module ActiveDirectory | ||
$domain_info = Get-ADDomain -Identity $test_domain | ||
$domain_sid = $domain_info.DomainSID | ||
$domain_netbios = $domain_info.NetBIOSName | ||
$domain_upn = $domain_info.Forest | ||
|
||
$tests += @{ | ||
sid = "$domain_sid-512" | ||
full_name = "$domain_netbios\Domain Admins" | ||
names = @("$domain_netbios\Domain Admins", "Domain Admins@$domain_upn", "Domain Admins") | ||
} | ||
|
||
$tests += @{ | ||
sid = "$domain_sid-500" | ||
full_name = "$domain_netbios\Administrator" | ||
names = @("$domain_netbios\Administrator", "Administrator@$domain_upn") | ||
} | ||
} | ||
|
||
foreach ($test in $tests) { | ||
$actual_account_name = Convert-FromSID -sid $test.sid | ||
Assert-Equals -actual $actual_account_name -expected $test.full_name | ||
|
||
foreach ($test_name in $test.names) { | ||
$actual_sid = Convert-ToSID -account_name $test_name | ||
Assert-Equals -actual $actual_sid -expected $test.sid | ||
} | ||
} | ||
|
||
Exit-Json @{ data = "success" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters