mirror of https://github.com/ansible/ansible.git
Added powershell SID utils for shared common code (#27091)
* Added powershell SID utils for shared common code * rebased from upstream and fixed up module util after changepull/28741/head
parent
adabefd016
commit
a695f30411
@ -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 *
|
@ -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" }
|
Loading…
Reference in New Issue