Skip to content

docs: Document AUTHCONTEXT secret lookup chain and Key Vault underscore limitation#2168

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/fix-authcontext-secret-resolution
Draft

docs: Document AUTHCONTEXT secret lookup chain and Key Vault underscore limitation#2168
Copilot wants to merge 3 commits intomainfrom
copilot/fix-authcontext-secret-resolution

Conversation

Copy link
Contributor

Copilot AI commented Mar 13, 2026

❔What, Why & How

AUTHCONTEXT secret resolution had several undocumented behaviors that could cause silent wrong-credential deployments with no log evidence: the dash variant was never mentioned, Key Vault silently dropped underscore secrets, and the generic fallback gave no warning.

Code change

  • Actions/ReadSecrets/ReadSecretsHelper.psm1: Emit ::warning:: when a Key Vault lookup is skipped because the secret name contains _. Previously returned $null with zero log output.
# Before: silent null return
if ($secret.Contains('_')) {
    return $null
}

# After: warning emitted
if ($secret.Contains('_')) {
    Write-Host "::warning::Secret name '$secret' contains an underscore ('_'), which is not supported in Azure Key Vault. ..."
    return $null
}

Documentation changes

  • Scenarios/secrets.md — Rewrote the AuthContext section to document:

    • Full three-step lookup chain in explicit precedence order: {envName}-AuthContext{envName}_AuthContextAuthContext
    • Azure Key Vault rejects underscore names → use the dash variant for KV-stored secrets
    • Generic AuthContext fallback is silent; in multi-tenant repos this can deploy with the wrong credentials
  • Scenarios/RegisterProductionEnvironment.md — Added a note clarifying that AUTHCONTEXT defined as a GitHub Environment secret is available in the deploy job when targeting that environment.

✅ Checklist

  • Add tests (E2E, unit tests)
  • Update RELEASENOTES.md
  • Update documentation (e.g. for new settings or scenarios)
  • Add telemetry
Original prompt

This section details on the original issue you should resolve

<issue_title>[Bug]: AUTHCONTEXT secret resolution undocumented -- silent Key Vault underscore failure, undocumented dash variant, silent org-level fallback trap, GitHub Environment secrets invisible at auth-check step</issue_title>
<issue_description>## AL-Go version

v8.2

Describe the issue

There are five related problems with AUTHCONTEXT secret resolution that together create silent wrong-environment deployments with no errors and no warnings. Each problem is individually confusing; together they are a reliability and security hazard in multi-environment and multi-tenant repos. I am documenting all five here as a single issue because fixing any one of them in isolation without fixing the others would still leave users in a broken state.


Finding 1: The full lookup chain is undocumented -- the dash variant is never mentioned

Both Templates/Per Tenant Extension/.github/workflows/CICD.yaml (line 351) and Templates/Per Tenant Extension/.github/workflows/PublishToEnvironment.yaml (line 90) declare:

getSecrets: '{envName}-AuthContext,{envName}_AuthContext,AuthContext'

The PowerShell resolution logic in PublishToEnvironment.yaml lines 100-106 then evaluates them in this exact order:

"$($envName)-AuthContext", "$($envName)_AuthContext", "AuthContext" | ForEach-Object {
    if (!($authContext)) {
        if ($secrets."$_") {
            Write-Host "Using $_ secret as AuthContext"
            $authContext = $secrets."$_"
            $secretName = $_
        }
    }
}

The dash variant {envName}-AuthContext is tried first and is the highest-priority lookup. It is never mentioned anywhere in the documentation. Scenarios/secrets.md documents only <EnvironmentName>_AuthContext (underscore). A user reading the documentation has no way to know the dash variant exists, let alone that it takes precedence.

This matters practically because the dash variant is the only one of the three that works correctly with Azure Key Vault (see Finding 2 below).


Finding 2: Azure Key Vault silently skips all underscore secrets -- {env}_AuthContext silently returns null

Actions/ReadSecrets/ReadSecretsHelper.psm1 lines 158-161:

if ($secret.Contains('_')) {
    # Secret name contains a '_', which is not allowed in Key Vault secret names
    return $null
}

When Azure Key Vault is configured as the secrets provider, any requested secret name containing an underscore is immediately returned as $null. No error is thrown. No warning is written to the log. No indication is given that the lookup was skipped.

The consequence: the documented pattern <EnvironmentName>_AuthContext is silently non-functional when Azure Key Vault is in use. A user who reads Scenarios/secrets.md, creates a Key Vault secret named MY-UAT_AuthContext, and triggers a deployment to MY-UAT will get no error. The workflow log will not mention that the Key Vault lookup was skipped. The workflow silently falls through to the generic AuthContext fallback.

The dash variant {env}-AuthContext does work with Key Vault because dashes are permitted in Key Vault secret names. This is never documented.


Finding 3: The generic AuthContext fallback is a silent cross-environment credential trap

When neither {env}-AuthContext nor {env}_AuthContext resolves to a value, AL-Go silently falls back to the generic AuthContext secret. The only log evidence of this is the message Using AuthContext secret as AuthContext. There is no warning that this is a fallback, no indication that a per-environment secret was expected but not found, and no indication that the credentials being used may not correspond to the target environment.

In organizations that define AUTHCONTEXT at the org level and share it with all repositories (a common pattern for product repos), every environment in every repo that lacks a per-environment secret will silently deploy using the org-level credential.

In a multi-tenant PTE scenario this creates a security isolation failure:

  • A TenantApps repo has environments CUSTOMER-A-UAT and CUSTOMER-B-UAT
  • Neither has a per-environment AuthContext secret defined
  • The org-level AUTHCONTEXT belongs to Customer A's BC service account
  • A developer triggers Publish To Environment targeting CUSTOMER-B-UAT
  • AL-Go resolves to the org-level AUTHCONTEXT (Customer A's credentials) with no warning
  • The workflow reports success; the log says "Using AuthContext secret as AuthContext"
  • No error is thrown and no credential mismatch is flagged

In regulated industries where BC tenant isolation is a compliance requirement, this silent fallback is particularly dangerous.


Finding 4: GitHub Environment secrets are invisible at the auth-check initialization step

In both CICD.yaml and...


📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.

…lution lookup chain

Co-authored-by: spetersenms <79980472+spetersenms@users.noreply.github.com>
Copilot AI changed the title [WIP] [Bug] Fix undocumented AUTHCONTEXT secret resolution issues docs: Document AUTHCONTEXT secret lookup chain, Key Vault underscore limitation, and GitHub Environment secret scope Mar 13, 2026
Copilot AI requested a review from spetersenms March 13, 2026 15:25
> **Multi-environment and multi-tenant repos:** If neither `<EnvironmentName>-AuthContext` nor `<EnvironmentName>_AuthContext` resolves to a value, AL-Go **silently falls back** to the generic `AuthContext` secret. The workflow log will only show `Using AuthContext secret as AuthContext` — no warning is emitted that a per-environment secret was expected but not found. In repositories with multiple environments (for example, different customer tenants), this means a missing per-environment secret will cause all environments to deploy using the same shared credentials, which may not be the intended behavior. Ensure all environments that require credential isolation have a per-environment `<EnvironmentName>-AuthContext` or `<EnvironmentName>_AuthContext` secret defined.

> [!NOTE]
> **GitHub Environment secrets scope:** GitHub Actions only injects environment-scoped secrets into jobs that explicitly declare an `environment:` property. The `AuthContext` resolution in the **Initialization job** (which performs the auth check before deployment) does **not** have an `environment:` property set. This means an `AUTHCONTEXT` secret defined as a **GitHub Environment secret** will not be visible to the auth-check step in the Initialization job. To ensure the AuthContext secret is found during initialization, define it as a **repository secret** or **organization secret** using the per-environment naming convention (`<EnvironmentName>-AuthContext` or `<EnvironmentName>_AuthContext`), rather than as a GitHub Environment secret named `AUTHCONTEXT`.
Copy link
Contributor

Choose a reason for hiding this comment

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

This is only true for deployments where the user selects an environment name that does not exist. Eg. no GitHub environment and environment found in settings with the given name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right — the auth check steps in Init are all gated behind if: steps.DetermineDeploymentEnvironments.outputs.UnknownEnvironment == 1, so they only run when the entered environment name is not found as a GitHub Environment or in settings. The note was misleading. Removed in 454ccba.

> The secret **NEEDS** to be compressed JSON and there should **NOT** be a newline after the secret value.

> [!NOTE]
> **GitHub Environment secrets** (defined under the environment in GitHub) are only injected into jobs that explicitly declare an `environment:` property. The AL-Go Initialization job that performs the auth check does **not** have this property, so environment-scoped `AUTHCONTEXT` secrets are **not** available at that step. The secret **is** available in the downstream deploy job, which is sufficient for deployment. If you prefer the secret to be resolved during the initialization auth check as well, define it as a **repository secret** using the naming convention `<EnvironmentName>-AuthContext` (e.g., `QA-AuthContext`) instead of as an environment secret named `AUTHCONTEXT`. See [secrets documentation](secrets.md#AuthContext) for the full lookup order.
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as the other comment. This is only true if the user calls the workflow with an environment name that does not exist as either a GitHub environment or defined as an environment in settings.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Correct — removed the note in 454ccba. The auth check only fires for unknown environment names, so a properly configured GitHub Environment works fine as-is.

… Init only runs for unknown environments

Co-authored-by: spetersenms <79980472+spetersenms@users.noreply.github.com>
Copilot AI changed the title docs: Document AUTHCONTEXT secret lookup chain, Key Vault underscore limitation, and GitHub Environment secret scope docs: Document AUTHCONTEXT secret lookup chain and Key Vault underscore limitation Mar 20, 2026
Copilot AI requested a review from spetersenms March 20, 2026 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants