diff --git a/.semaphore/smoke-tests.yml b/.semaphore/smoke-tests.yml index 69404bae1f..3381210b0d 100644 --- a/.semaphore/smoke-tests.yml +++ b/.semaphore/smoke-tests.yml @@ -64,9 +64,52 @@ blocks: # following the pattern from cli-release/.semaphore/4-release-cli.yml). - $Env:VAULT_ADDR = "https://vault.cireops.gcp.internal.confluent.cloud" - vault login -no-print token=$(vault write -field=token "auth/semaphore_self_hosted/login" role="default" jwt="$Env:SEMAPHORE_OIDC_TOKEN") - - $Env:CONFLUENT_CLOUD_EMAIL = (vault kv get -field=CONFLUENT_CLOUD_EMAIL v1/ci/kv/apif/cli/live-testing-data) - - $Env:CONFLUENT_CLOUD_PASSWORD = (vault kv get -field=CONFLUENT_CLOUD_PASSWORD v1/ci/kv/apif/cli/live-testing-data) - - $Env:SLACK_WEBHOOK_URL = (vault kv get -field=SLACK_WEBHOOK_URL v1/ci/kv/apif/cli/slack-notifications-live-testing) + # These secrets keep everything in a single field named "script", whose value is + # a shell script of `export NAME=value` lines. That is why asking for + # `-field=CONFLUENT_CLOUD_EMAIL` failed with `Field "CONFLUENT_CLOUD_EMAIL" not + # present in secret` -- no such field exists. The linux/arm64 job above sources + # that script; PowerShell cannot, so parse the assignments out of it instead. + # Only the variables the job needs are exported, so anything else these secrets + # define never reaches the environment of `go test` and its children. + # Values are never echoed; only variable names appear, and only on failure. + - | + function Import-VaultScript($Path, $Names) { + # Check the exit code before touching the output: on a partial response, + # downstream errors could echo the input, which holds secrets. + $exports = vault kv get -field=script $Path + if ($LASTEXITCODE -ne 0) { throw "failed to read Vault secret $Path" } + + # Hashtable keys are case-insensitive, so the lookups below still succeed if + # the script happens to declare these names under a different case. + $defined = @{} + foreach ($line in ($exports -split "\r?\n")) { + if ($line -match '^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$') { + $name = $Matches[1] + $value = $Matches[2].Trim() + + # Strip one layer of surrounding quotes, as `source` would. + foreach ($quote in '"', "'") { + if ($value.Length -ge 2 -and $value.StartsWith($quote) -and $value.EndsWith($quote)) { + $value = $value.Substring(1, $value.Length - 2) + break + } + } + $defined[$name] = $value + } + } + + # Fail here rather than 20 minutes later inside `go test`, which would only + # report "required environment variable ... is not set". + foreach ($name in $Names) { + if (-not $defined.ContainsKey($name) -or [string]::IsNullOrEmpty($defined[$name])) { + throw "secret $Path does not define $name (defines: $(($defined.Keys | Sort-Object) -join ', '))" + } + [Environment]::SetEnvironmentVariable($name, $defined[$name]) + } + } + + Import-VaultScript v1/ci/kv/apif/cli/live-testing-data @("CONFLUENT_CLOUD_EMAIL", "CONFLUENT_CLOUD_PASSWORD") + Import-VaultScript v1/ci/kv/apif/cli/slack-notifications-live-testing @("SLACK_WEBHOOK_URL") # Install Go (matches the pattern in semaphore.yml; chocolatey is community-maintained) - $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -OutFile Go.zip -Uri https://go.dev/dl/go$(Get-Content .go-version).windows-amd64.zip -UseBasicParsing