Skip to content

Merge 1.2.3 to main#78

Closed
indrora wants to merge 1 commit into
mainfrom
release-1.2
Closed

Merge 1.2.3 to main#78
indrora wants to merge 1 commit into
mainfrom
release-1.2

Conversation

@indrora

@indrora indrora commented Apr 7, 2026

Copy link
Copy Markdown
Member

Merge release-1.2 to main - Automated PR

…ve for K8SNS/K8SCluster alias parsing (#77)

* fix(management): guard against IndexOutOfRangeException in HandleRemove for K8SNS/K8SCluster alias parsing

HandleRemove accessed splitAlias[^2] without a bounds check for both K8SNS and
K8SCluster store types. A bare alias without the expected '/' delimiter produced
a single-element array, causing 'Index was outside the bounds of the array'.

Added Length < 2 guard for K8SNS and Length < 3 guard for K8SCluster; returns
a clear FailJob with an actionable error message describing the expected alias format.

* Update generated docs

* chore(changelog): add 1.2.3 release notes

* Update generated docs

* chore(changelog): add K8SNS management add fix entry to 1.2.3 release notes

* chore(changelog): update 1.2.3 release notes to reference 1.1.4 hotfix fixes

* chore(changelog): fix 1.2.3 and add 1.1.4 release notes

* Update generated docs

---------

Co-authored-by: Keyfactor <keyfactor@keyfactor.github.io>
Copilot AI review requested due to automatic review settings April 7, 2026 18:39
@indrora indrora closed this Apr 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Automated merge of release 1.2.3 into main, primarily updating store-type creation scripts and hardening Kubernetes management “Remove” job alias parsing to avoid IndexOutOfRangeException.

Changes:

  • Update PowerShell + Bash scripts to create all 7 Kubernetes-related store types, with added OAuth/Bearer auth support.
  • Add alias-format guards in Management.HandleRemove() for K8SNS and K8SCluster.
  • Add/refresh documentation images and update CHANGELOG.md for 1.2.3.

Reviewed changes

Copilot reviewed 6 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
scripts/store_types/powershell/restmethod_create_store_types.ps1 Reworked REST-based store-type creation script with multiple auth modes and helper function.
scripts/store_types/powershell/kfutil_create_store_types.ps1 Expands kfutil-based script to create all 7 store types and adds clearer prechecks.
scripts/store_types/bash/kfutil_create_store_types.sh Expands kfutil-based Bash script to create all 7 store types and tightens tool checks.
scripts/store_types/bash/curl_create_store_types.sh Reworked curl-based store-type creation script with OAuth support and helper function.
kubernetes-orchestrator-extension/Jobs/Management.cs Adds alias parsing guards in Remove flow for K8SNS/K8SCluster capabilities.
docsource/images/K8SNS-basic-store-type-dialog.png Adds/updates documentation image asset.
docsource/images/K8SCluster-basic-store-type-dialog.png Adds/updates documentation image asset.
CHANGELOG.md Adds 1.2.3 changelog entry (and includes 1.1.4 section).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +691 to 699
if (splitAlias.Length < 2)
{
var errMsg = $"Invalid alias format for K8SNS store type. Expected pattern: 'secrets/<tls|opaque>/<secret_name>' but got '{certAlias}'";
Logger.LogError(errMsg);
return FailJob(errMsg, config.JobHistoryId);
}
// Split alias by / and get second to last element KubeSecretType
KubeSecretType = splitAlias[^2];
KubeSecretName = splitAlias[^1];

Copilot AI Apr 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The validation for the K8SNS remove alias is too lenient for the format described in the error message. With the documented pattern secrets/<tls|opaque>/<secret_name>, splitAlias.Length must be at least 3 (and ideally also validate the fixed secrets segment) before indexing [^2]/[^1]; otherwise aliases like tls/mysecret will be treated as valid and can lead to removing the wrong secret.

Copilot uses AI. Check for mistakes.
Comment on lines +704 to 712
if (splitAlias.Length < 3)
{
var errMsg = $"Invalid alias format for K8SCluster store type. Expected pattern: '<namespace>/secrets/<tls|opaque>/<secret_name>' but got '{certAlias}'";
Logger.LogError(errMsg);
return FailJob(errMsg, config.JobHistoryId);
}
KubeSecretType = splitAlias[^2];
KubeSecretName = splitAlias[^1];
KubeNamespace = splitAlias[0];

Copilot AI Apr 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The K8SCluster alias validation does not match the documented expected pattern. The message indicates <namespace>/secrets/<tls|opaque>/<secret_name> (4 segments), but the code only requires 3 segments; a 3-part alias will pass and then KubeSecretType becomes secrets. Consider requiring at least 4 segments (and validating the secrets segment) before extracting KubeSecretType/KubeSecretName/KubeNamespace.

Copilot uses AI. Check for mistakes.
Comment on lines +28 to +37
elif [ -n "${KEYFACTOR_AUTH_CLIENT_ID}" ] && [ -n "${KEYFACTOR_AUTH_CLIENT_SECRET}" ] && [ -n "${KEYFACTOR_AUTH_TOKEN_URL}" ]; then
echo "Fetching OAuth token..."
BEARER_TOKEN=$(curl -s -X POST "${KEYFACTOR_AUTH_TOKEN_URL}" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "client_id=${KEYFACTOR_AUTH_CLIENT_ID}" \
--data-urlencode "client_secret=${KEYFACTOR_AUTH_CLIENT_SECRET}" | jq -r '.access_token')
if [ -z "${BEARER_TOKEN}" ] || [ "${BEARER_TOKEN}" = "null" ]; then
echo "ERROR: Failed to fetch OAuth token from ${KEYFACTOR_AUTH_TOKEN_URL}"
exit 1

Copilot AI Apr 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The OAuth client-credentials path pipes the token response through jq, but the script doesn't verify jq is installed. On systems without jq this will silently produce an empty token and then fail later; either add a command -v jq check with a clear error, or avoid the dependency (e.g., parse with a minimal fallback).

Copilot uses AI. Check for mistakes.
client_id = $env:KEYFACTOR_AUTH_CLIENT_ID
client_secret = $env:KEYFACTOR_AUTH_CLIENT_SECRET
}
$tokenResp = Invoke-RestMethod -Method Post -Uri $env:KEYFACTOR_AUTH_TOKEN_URL -Body $tokenBody

Copilot AI Apr 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invoke-RestMethod token acquisition does not validate that an access_token was returned before constructing the Authorization header. If the token endpoint returns an error payload, $tokenResp.access_token can be $null and the script will proceed with an invalid Bearer header. Add a check for a non-empty token (and ideally surface the token endpoint error/HTTP status) before continuing.

Suggested change
$tokenResp = Invoke-RestMethod -Method Post -Uri $env:KEYFACTOR_AUTH_TOKEN_URL -Body $tokenBody
try {
$tokenResp = Invoke-RestMethod -Method Post -Uri $env:KEYFACTOR_AUTH_TOKEN_URL -Body $tokenBody
} catch {
$statusCode = $null
$responseBody = $null
if ($_.Exception.Response) {
try {
$statusCode = [int]$_.Exception.Response.StatusCode
} catch {
$statusCode = $null
}
try {
$reader = New-Object System.IO.StreamReader($_.Exception.Response.GetResponseStream())
$responseBody = $reader.ReadToEnd()
$reader.Dispose()
} catch {
$responseBody = $null
}
}
$errorMessage = "Failed to fetch OAuth token from $($env:KEYFACTOR_AUTH_TOKEN_URL): $($_.Exception.Message)"
if ($statusCode) {
$errorMessage += " (HTTP $statusCode)"
}
if ($responseBody) {
$errorMessage += ". Response: $responseBody"
}
Write-Error $errorMessage
exit 1
}
if (-not $tokenResp -or [string]::IsNullOrWhiteSpace($tokenResp.access_token)) {
$tokenErrorDetails = $null
if ($tokenResp) {
$tokenErrorDetails = $tokenResp | ConvertTo-Json -Compress
}
$errorMessage = "OAuth token response did not contain a non-empty access_token."
if ($tokenErrorDetails) {
$errorMessage += " Response: $tokenErrorDetails"
}
Write-Error $errorMessage
exit 1
}

Copilot uses AI. Check for mistakes.
Invoke-RestMethod -Method Post -Uri $uri -Headers $headers -Body $Body -ContentType "application/json" | Out-Null
Write-Host " OK"
} catch {
Write-Warning " FAILED: $($_.Exception.Message)"

Copilot AI Apr 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New-StoreType catches failures and only emits a warning, but then the script continues and ends with "Completed." even if one or more store type creations failed. For automation usage this makes failures easy to miss; consider tracking failures and exiting non-zero at the end (or re-throw / exit 1 on first failure).

Suggested change
Write-Warning " FAILED: $($_.Exception.Message)"
Write-Warning " FAILED: $($_.Exception.Message)"
throw

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants