-
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.
* download vault * stealing your resolve * set env * add Vault setup script * add configs * setup Vault in CI, see if we can run test CLI * typo * fix test display * need a detached process * update how setup script takes init data * add CcgVault tests with CLI test * do test through pester * fix paths * reg on bin only * add tests with docker * run in CI * fix credspec * set test container * raise timeout * lessee whas happening * remove half-baked thing * harumph * run-a-ping * not backgrounded duh * tryna * stop looking for ghosts * test cases!
- Loading branch information
Showing
8 changed files
with
343 additions
and
1 deletion.
There are no files selected for viewing
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
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,18 @@ | ||
--- | ||
defaults: | ||
vault_addr: http://127.0.0.1:8200 | ||
auth: | ||
type: token_from_file | ||
config: | ||
file_path: C:\ccg\tokenfile | ||
sources: | ||
static_kv1: | ||
type: kv1 | ||
config: | ||
path: win/gmsa-getter | ||
# mount_point: kv | ||
static_kv2: | ||
type: kv2 | ||
config: | ||
path: win/gmsa-getter | ||
mount_point: secret |
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,30 @@ | ||
{ | ||
"CmsPlugins": [ | ||
"ActiveDirectory" | ||
], | ||
"DomainJoinConfig": { | ||
"Sid": "S-1-5-21-702590844-1001920913-2680819671", | ||
"MachineAccountName": "ccg-gmsa", | ||
"Guid": "56d9b66c-d746-4f87-bd26-26760cfdca2e", | ||
"DnsTreeName": "contoso.com", | ||
"DnsName": "contoso.com", | ||
"NetBiosName": "CONTOSO" | ||
}, | ||
"ActiveDirectoryConfig": { | ||
"GroupManagedServiceAccounts": [ | ||
{ | ||
"Name": "ccg-gmsa", | ||
"Scope": "contoso.com" | ||
}, | ||
{ | ||
"Name": "ccg-gmsa", | ||
"Scope": "CONTOSO" | ||
} | ||
], | ||
"HostAccountConfig": { | ||
"PortableCcgVersion": "1", | ||
"PluginGUID": "{01BF101D-BFB6-433F-B416-02885CDC5AD3}", | ||
"PluginInput": "C:\\ccg\\ccgvault.yml|static_kv2" | ||
} | ||
} | ||
} |
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 @@ | ||
bin/ |
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,62 @@ | ||
#Requires -Version 7.0 | ||
[CmdletBinding()] | ||
param( | ||
[Parameter()] | ||
[ValidateNotNullOrEmpty()] | ||
[String] | ||
$VaultPath = 'vault.exe', | ||
|
||
[Parameter()] | ||
[hashtable] | ||
$Kv1Data = @{ | ||
Username = 'ccg-reader-1' | ||
Domain = 'contoso.com' | ||
Password = 'password1' | ||
} , | ||
|
||
[Parameter()] | ||
[hashtable] | ||
$Kv2Data = @{ | ||
Username = 'ccg-reader-2' | ||
Domain = 'contoso.com' | ||
Password = 'password2' | ||
} | ||
) | ||
|
||
if (-not $env:VAULT_ADDR) { | ||
$env:VAULT_ADDR = 'http://127.0.0.1:8200' | ||
} | ||
|
||
if (-not $env:VAULT_DEV_ROOT_TOKEN_ID) { | ||
$env:VAULT_DEV_ROOT_TOKEN_ID = '323e3e66-e5fe-42ba-a4b9-fad293077754' | ||
} | ||
|
||
if (-not $env:VAULT_TOKEN) { | ||
$env:VAULT_TOKEN = $env:VAULT_DEV_ROOT_TOKEN_ID | ||
} | ||
|
||
$env:VAULT_CLIENT_TIMEOUT = 1 | ||
& $VaultPath status | ||
$running = $? | ||
$env:VAULT_CLIENT_TIMEOUT = '' | ||
|
||
if ($running) { | ||
return | ||
} | ||
|
||
$w32p = Get-CimClass -ClassName Win32_Process | ||
$w32startup = Get-CimClass -ClassName Win32_ProcessStartup | ||
$vars = [System.Environment]::GetEnvironmentVariables([System.EnvironmentVariableTarget]::Process).GetEnumerator().ForEach({ | ||
"{0}={1}" -f $_.Name, $_.Value | ||
}) -as [string[]] | ||
$vars | Write-Verbose | ||
$startup = New-CimInstance -CiMClass $w32startup -Property @{ EnvironmentVariables = $vars } -ClientOnly | ||
$proc = Invoke-CimMethod -CiMClass $w32p -Name Create -Arguments @{ | ||
CommandLine = "$VaultPath server -dev" | ||
ProcessStartupInformation = $startup | ||
} | ||
$proc.ProcessId | Set-Content -LiteralPath $env:TMP\vaultpid -NoNewline -Encoding utf8NoBOM | ||
|
||
& $VaultPath secrets enable -path kv -version 1 kv | ||
& $VaultPath kv put kv/win/gmsa-getter $($Kv1Data.GetEnumerator().ForEach({"{0}={1}" -f $_.Name, $_.Value})) | ||
& $VaultPath kv put secret/win/gmsa-getter $($Kv2Data.GetEnumerator().ForEach({"{0}={1}" -f $_.Name, $_.Value})) |
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
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,176 @@ | ||
#Requires -Module @{ ModuleName = 'Pester'; ModuleVersion = '5.2.0' } | ||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', 'CredSpecPath')] | ||
param( | ||
[Parameter()] | ||
[ValidateNotNullOrEmpty()] | ||
[String] | ||
$CcgVault = "$env:CcgVaultBin\CcgVault.exe" , | ||
|
||
[Parameter()] | ||
[ValidateNotNullOrEmpty()] | ||
[String] | ||
$Config = 'C:\ccg\ccgvault.yml' , | ||
|
||
[Parameter()] | ||
[ValidateNotNullOrEmpty()] | ||
[String] | ||
$ContainerImage = $env:CcgVaultTestContainer, | ||
|
||
[Parameter()] | ||
[ValidateNotNullOrEmpty()] | ||
[String] | ||
$CredSpecPath = "$env:ProgramData\Docker\credentialspecs" | ||
) | ||
|
||
BeforeAll { | ||
$data = Import-PowerShellDataFile -LiteralPath $PSScriptRoot\TestData.psd1 | ||
|
||
$Script:ccgPluginId = [Guid]::Parse($data.ComPlus.CcgPlugin.ID) | ||
|
||
$kv1data = $data.CcgVault.Kv1Data | ||
$kv2data = $data.CcgVault.Kv2Data | ||
|
||
$Script:expected_data = @{ | ||
static_kv1 = $kv1data | ||
static_kv2 = $kv2data | ||
} | ||
|
||
# this doesn't work for some reason, haven't figured out why yet. | ||
# if the path is wrong, the tests fail, so it seems like it tries to execute it at least, | ||
# but it does not appear to actually start the Vault server; the tests only work if I run | ||
# it separately first (and even in that case, tests fail when the path is wrong). | ||
# & "$PSScriptRoot\.vault\setup.ps1" -Kv1Data $kv1data -Kv2Data $kv2data -ErrorAction Stop -Verbose | ||
} | ||
|
||
Describe 'CcgVault tests' -Tag CcgVault { | ||
Context 'CLI test command w/ source: <source>' -Tag CLI -Foreach @( | ||
@{ source = 'static_kv1' } | ||
@{ source = 'static_kv2' } | ||
) { | ||
BeforeAll { | ||
$Script:expected = $expected_data[$source] | ||
$Script:output = & $CcgVault test --input "${Config}|${source}" | ||
$Script:result = $output | | ||
ForEach-Object -Begin { $Script:r = @{} } -Process { | ||
$key, $value = $_ -split ': ' | ||
$r[$key] = $value | ||
} -End { $r } | ||
} | ||
|
||
It "Source '<source>' has Username '<expected.Username>'" { | ||
$result.User | Should -BeExactly $expected.Username | ||
} | ||
|
||
It "Source '<source>' has Domain '<expected.Domain>'" { | ||
$result.Domain | Should -BeExactly $expected.Domain | ||
} | ||
|
||
It "Source '<source>' has Password '<expected.Password>'" { | ||
$result.Pass | Should -BeExactly $expected.Password | ||
} | ||
} | ||
|
||
Context 'Docker run test w/ source: <source>' -Tag Docker -Foreach @( | ||
@{ source = 'static_kv1' } | ||
@{ source = 'static_kv2' } | ||
) { | ||
BeforeAll { | ||
$Script:timeout = 60 | ||
$Script:time = Get-Date | ||
$Script:logname = $data.CcgVault.LogName | ||
|
||
$credspecfile = "credspec_${source}.json" | ||
$credspec = Join-Path -Path $CredSpecPath -ChildPath $credspecfile | ||
|
||
$spec = Get-Content -LiteralPath "$PSScriptRoot/.config/credspec.json" -Raw | ConvertFrom-Json -AsHashtable -Depth 10 | ||
$spec.ActiveDirectoryConfig.HostAccountConfig.PluginInput = "${Config}|${source}" | ||
|
||
ConvertTo-Json -InputObject $spec -Depth 10 | Set-Content -LiteralPath $credspec -Encoding utf8NoBOM -Force | ||
|
||
$containerName = "ccgtest_${source}" | ||
|
||
& docker run --user "NT AUthority\System" --security-opt "credentialspec=file://${credspecfile}" --name "$containerName" --rm -d "$ContainerImage" cmd /c ping -t localhost | ||
|
||
if (-not $?) { | ||
throw "Error runnung docker command." | ||
} | ||
|
||
function Wait-WinEvent { | ||
[CmdletBinding()] | ||
param( | ||
[Parameter(Mandatory)] | ||
[ValidateNotNullOrEmpty()] | ||
[String] | ||
$LogName , | ||
|
||
[Parameter()] | ||
[UInt16] | ||
$EventID , | ||
|
||
[Parameter()] | ||
[ScriptBlock] | ||
$Condition , | ||
|
||
[Parameter()] | ||
[DateTime] | ||
$MinimumDateTime , | ||
|
||
[Parameter()] | ||
[UInt16] | ||
$TimeoutSeconds , | ||
|
||
[Parameter()] | ||
[UInt16] | ||
$SleepMilliseconds = 250 | ||
) | ||
|
||
End { | ||
$delay = $false | ||
$timeoutStart = [DateTime]::Now | ||
do { | ||
if ($delay) { | ||
Start-Sleep -Milliseconds $SleepMilliseconds | ||
} | ||
$ev = Get-WinEvent -LogName $LogName -FilterXPath "*[System[EventID=${EventID}]]" -MaxEvents 1 -ErrorAction SilentlyContinue | ||
$delay = $delay -or $SleepMilliseconds -as [bool] | ||
} until ( | ||
($null -eq $MinimumDateTime -or $ev.TimeCreated -gt $MinimumDateTime) -and | ||
($null -eq $Condition -or (ForEach-Object -InputObject $ev -Process $Condition)) -or | ||
(-not $TimeoutSeconds -or ($timedOut = ([DateTime]::Now - $timeoutStart).TotalSeconds -gt $TimeoutSeconds)) | ||
) | ||
|
||
if (-not $timedOut) { | ||
$ev | ||
} | ||
} | ||
} | ||
} | ||
|
||
It "The plugin was instantiated" { | ||
$event1 = Wait-WinEvent -LogName $logname -EventId 1 -Condition { | ||
[guid]::Parse($_.Properties[0].Value) -eq $ccgPluginId | ||
} -MinimumDateTime $time -TimeoutSeconds $timeout | ||
|
||
$event1 | Should -Not -BeNullOrEmpty | ||
} | ||
|
||
# EventID 8 gets logged on my local machine when used with test creds | ||
# and the contoso.com domain, but it doesn't happen in CI nor in a test | ||
# server; maybe this is because my machine is a desktop OS, maybe it's | ||
# because it's domain-joined, not sure. Will keep it around as a possible | ||
# future test-case. | ||
# | ||
# It "The credential fails without a real domain" -Tag NoDomain { | ||
# $event8 = Wait-WinEvent -LogName $logname -EventId 8 -Condition { | ||
# [guid]::Parse($_.Properties[1].Value) -eq $ccgPluginId | ||
# } -MinimumDateTime $time -TimeoutSeconds $timeout | ||
|
||
# $event8 | Should -Not -BeNullOrEmpty | ||
# } | ||
|
||
AfterAll { | ||
& docker stop "$containerName" | ||
Remove-Item -LiteralPath $credspec -Force | ||
} | ||
} | ||
} |
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