Skip to content

Deploy: Add secrets, workload identity, ACR support, and fix identity role assignments#468

Open
gambtho wants to merge 3 commits intoAzure:mainfrom
gambtho:thgamble/managedidentity
Open

Deploy: Add secrets, workload identity, ACR support, and fix identity role assignments#468
gambtho wants to merge 3 commits intoAzure:mainfrom
gambtho:thgamble/managedidentity

Conversation

@gambtho
Copy link
Collaborator

@gambtho gambtho commented Mar 18, 2026

Summary

  • Add per-variable secret toggle in the Deploy Wizard environment variables step — secret values are masked in the UI, stored as a Kubernetes Secret resource, and referenced via valueFrom.secretKeyRef in the Deployment manifest
  • Add a new "Workload Identity" stepper step that creates (or selects existing) Azure managed identities, configures federated credentials against the cluster's OIDC issuer, and generates a ServiceAccount with azure.workload.identity/client-id annotation plus pod labels/serviceAccountName on the Deployment
  • Update GitHub Pipeline agent templates to include workload identity ServiceAccount creation and pod configuration in generated workflows
  • Fix managed identity role assignments: assign the full required role matrix (AcrPush, Container Registry Tasks Contributor, AKS RBAC Writer, AKS Namespace User) scoped correctly for both normal and managed namespaces
  • Add ACR selection/creation to the pipeline wizard so the generated workflow can build and push container images
  • Extract shared identity setup logic into reusable utilities, eliminating duplication between the GitHub Pipeline and Deploy Wizard flows

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)

Related Issues

Closes #467

Changes Made

Secrets support

  • Extended ContainerConfig.envVars type with isSecret: boolean
  • Added lock icon toggle and password masking in ConfigureContainer.tsx
  • Updated yamlGenerator.ts to emit a Secret resource and secretKeyRef entries for secret env vars
  • Updated extractContainerConfig.ts to round-trip secretKeyRef entries

Workload Identity

  • Added getAksOidcIssuerUrl, listManagedIdentities, createK8sFederatedCredential to az-cli.ts
  • Created useDeployWorkloadIdentity hook (adapts existing GitHub Pipeline pattern)
  • Added new stepper step with "Create new" / "Use existing" identity modes
  • Updated yamlGenerator.ts to emit ServiceAccount, pod label, and serviceAccountName
  • Threaded Azure context from ClusterDeployCard through DeployWizard to ConfigureContainer

Identity role assignment fixes

  • Added assignRolesToIdentity() — generalized multi-role assignment function replacing the single hardcoded role
  • Added computeRequiredRoles() in new identityRoles.ts — computes the correct role set based on namespace type (normal vs managed), ACR presence, and Azure RBAC status
  • Normal namespace roles: AcrPush (ACR), Container Registry Tasks Contributor (ACR), AKS Cluster User Role (cluster), AKS RBAC Writer (cluster, if Azure RBAC enabled)
  • Managed namespace roles: AcrPush (ACR), Container Registry Tasks Contributor (ACR), AKS RBAC Writer (MNS scope), AKS Namespace User (MNS scope)
  • Extracted ensureIdentityAndResourceGroup() into shared identitySetup.ts — eliminates ~80% duplication between the two identity hooks
  • Added getManagedNamespaceResourceId() and buildClusterScope() helpers to az-cli.ts

ACR support in pipeline wizard

  • Added AcrSelector component — lists existing ACRs, supports creating new registries, shows a warning if skipped
  • Added createContainerRegistry() to az-cli.ts
  • Added acrResourceId and acrLoginServer to PipelineConfig
  • Agent templates now include az acr build instructions when ACR is configured
  • Pipeline secrets now include AZURE_ACR_NAME when ACR is selected

Pipeline integration

  • Added generateWorkloadIdentityWorkflowInstructions to agentTemplates.ts
  • Included workload identity config summary in generated agent markdown

Testing

  • Unit tests pass
  • Manual testing completed

Test Cases

  1. All 208 related tests pass (identity roles, identity setup, pipeline hooks, pipeline components, agent templates, pipeline orchestration)
  2. TypeScript type check passes
  3. ESLint and Prettier pass
  4. No new test failures introduced
  5. New test files: identityRoles.test.ts (10 tests), identitySetup.test.ts (8 tests)

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes

Performance Impact

  • No performance impact

Reviewer Notes

  • The workload identity step is disabled when Azure context is unavailable (non-Azure clusters or not signed in)
  • Secret values are visible in the YAML preview step (acceptable since this is a local desktop app and the user just typed them)
  • The Secret resource is placed first in the generated YAML so it exists before the Deployment that references it
  • ACR selection is optional with a warning — pipelines can still be created without an ACR for pre-built image scenarios
  • The old assignRoleToIdentity() function is preserved for backward compatibility but should be removed once all callers are migrated
  • getClusterCapabilities() already returns azureRbacEnabled — callers just need to thread it through to the identity hooks

Copilot AI review requested due to automatic review settings March 18, 2026 03:27
@gambtho gambtho changed the title Deploy: Add secrets support and workload identity to Deploy Wizard Deploy: add secrets support and workload identity to Deploy Wizard Mar 18, 2026
@gambtho gambtho marked this pull request as draft March 18, 2026 03:28
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds Deploy Wizard support for (1) marking environment variables as secrets (emitted as a Kubernetes Secret + valueFrom.secretKeyRef) and (2) configuring Azure Workload Identity (managed identity + federated credential flow), plus updates to pipeline agent templates/tests to account for the expanded container config shape.

Changes:

  • Extend ContainerConfig to include envVars[].isSecret and Workload Identity fields, and update fixtures/stories/tests accordingly.
  • Update Deploy Wizard UI + YAML generator to create Secret/ServiceAccount manifests and label/pod spec wiring for workload identity.
  • Add Azure CLI helpers and a new hook to automate managed identity + role assignment + OIDC issuer lookup + federated credential creation.

Reviewed changes

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

Show a summary per file
File Description
plugins/aks-desktop/src/utils/azure/az-cli.ts Adds AKS OIDC issuer lookup, managed identity listing, and K8s federated credential creation helpers.
plugins/aks-desktop/src/components/GitHubPipeline/utils/pipelineOrchestration.test.ts Updates tests to include the new envVars[].isSecret field.
plugins/aks-desktop/src/components/GitHubPipeline/utils/agentTemplates.ts Adds pipeline workflow instructions for workload identity and surfaces it in generated agent config.
plugins/aks-desktop/src/components/GitHubPipeline/utils/agentTemplates.test.ts Updates agent template tests for the new env var shape.
plugins/aks-desktop/src/components/GitHubPipeline/fixtures/pipelineConfig.ts Extends fixture defaults with isSecret and workload identity fields.
plugins/aks-desktop/src/components/DeployWizard/utils/yamlGenerator.ts Emits Secret + Workload Identity ServiceAccount/labels/serviceAccountName into generated YAML.
plugins/aks-desktop/src/components/DeployWizard/hooks/useDeployWorkloadIdentity.ts New hook to set up managed identity + role assignment + federated credentials for a K8s service account.
plugins/aks-desktop/src/components/DeployWizard/hooks/useContainerConfiguration.ts Extends ContainerConfig type and default state to include secrets + workload identity fields.
plugins/aks-desktop/src/components/DeployWizard/components/DeployWizardPure.stories.tsx Updates story stub config for new fields.
plugins/aks-desktop/src/components/DeployWizard/components/ConfigureContainer.tsx Adds env var secret toggle UI and a new Workload Identity step with “create”/“existing” identity flows.
plugins/aks-desktop/src/components/DeployWizard/DeployWizard.tsx Passes Azure context/namespace into ConfigureContainer for workload identity configuration.
plugins/aks-desktop/src/components/DeployTab/utils/extractContainerConfig.ts Extracts secret env vars and workload identity label/serviceAccountName from live deployments.
plugins/aks-desktop/src/components/DeployTab/utils/extractContainerConfig.test.ts Updates extraction tests for isSecret.
plugins/aks-desktop/src/components/DeployTab/components/ClusterDeployCard.tsx Supplies Azure context to Deploy Wizard from the Deploy Tab.

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

You can also share your feedback on Copilot code review. Take the survey.

@gambtho gambtho force-pushed the thgamble/managedidentity branch 3 times, most recently from 2e27c8d to 1517b6b Compare March 18, 2026 17:34
@gambtho gambtho changed the title Deploy: add secrets support and workload identity to Deploy Wizard Deploy: Add secrets, workload identity, ACR support, and fix identity role assignments Mar 18, 2026
@gambtho gambtho force-pushed the thgamble/managedidentity branch 3 times, most recently from 7d3dc54 to ec8f6f5 Compare March 19, 2026 01:54
@gambtho gambtho marked this pull request as ready for review March 19, 2026 02:01
Copilot AI review requested due to automatic review settings March 19, 2026 02:01
Add per-variable secret toggle in environment variables step and a new
Workload Identity stepper step that creates Azure managed identities
with federated credentials for the cluster's OIDC issuer.
@gambtho gambtho force-pushed the thgamble/managedidentity branch from ec8f6f5 to 55d85f2 Compare March 19, 2026 02:01
Assign the full required role matrix (AcrPush, Container Registry Tasks
Contributor, AKS RBAC Writer, AKS Namespace User) scoped correctly for
both normal and managed namespaces. Add ACR selection/creation to the
pipeline wizard and extract shared identity setup into reusable utilities.
@gambtho gambtho force-pushed the thgamble/managedidentity branch from 55d85f2 to 10a4895 Compare March 19, 2026 02:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends AKS Desktop’s Deploy Wizard and GitHub Pipeline flows to support per-env-var Kubernetes Secrets, Azure Workload Identity (with shared identity/role setup utilities), and optional Azure Container Registry (ACR) integration for build/push workflows, while correcting managed identity role assignment behavior.

Changes:

  • Introduces shared Azure identity setup utilities (identitySetup, identityRoles, identityWithRoles) and updates pipeline/deploy hooks to use multi-role assignment.
  • Adds Workload Identity configuration to deploy/pipeline flows (OIDC issuer discovery, federated credential creation, ServiceAccount + pod config generation).
  • Adds ACR selection/creation support and threads ACR context into pipeline secrets and agent instructions; adds per-variable secret env var support in YAML generation + extraction.

Reviewed changes

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

Show a summary per file
File Description
plugins/aks-desktop/src/utils/azure/identityWithRoles.ts New shared orchestration for identity creation + required role assignments
plugins/aks-desktop/src/utils/azure/identitySetup.ts New utility to ensure RG + identity exist
plugins/aks-desktop/src/utils/azure/identitySetup.test.ts Tests for identity setup utility
plugins/aks-desktop/src/utils/azure/identityRoles.ts New role-matrix computation for normal vs managed namespaces + ACR + Azure RBAC
plugins/aks-desktop/src/utils/azure/identityRoles.test.ts Tests for role computation
plugins/aks-desktop/src/utils/azure/az-cli.ts Adds ACR typing, multi-role assignment, OIDC issuer discovery, identity listing, K8s federated credential creation, ACR creation helpers
plugins/aks-desktop/src/components/GitHubPipeline/utils/pipelineOrchestration.ts Adds ACR name secret creation for workflows
plugins/aks-desktop/src/components/GitHubPipeline/utils/pipelineOrchestration.test.ts Updates env var fixtures for new isSecret field
plugins/aks-desktop/src/components/GitHubPipeline/utils/agentTemplates.ts Adds workload identity + ACR build/push instructions and summary output
plugins/aks-desktop/src/components/GitHubPipeline/utils/agentTemplates.test.ts Updates env var fixtures for new isSecret field
plugins/aks-desktop/src/components/GitHubPipeline/types.ts Extends pipeline config with ACR fields
plugins/aks-desktop/src/components/GitHubPipeline/hooks/useWorkloadIdentitySetup.ts Switches to shared identity+roles utility; adds cluster/ACR/namespace context
plugins/aks-desktop/src/components/GitHubPipeline/hooks/useWorkloadIdentitySetup.test.ts Updates mocks/expectations for multi-role assignment + shared utility
plugins/aks-desktop/src/components/GitHubPipeline/components/WorkloadIdentitySetup.tsx Updates UI step wording/status for role assignments and threads new inputs
plugins/aks-desktop/src/components/GitHubPipeline/components/WorkloadIdentitySetup.test.tsx Adds clusterName prop to fixture
plugins/aks-desktop/src/components/GitHubPipeline/components/AcrSelector.tsx New UI component to select/create/skip ACR
plugins/aks-desktop/src/components/GitHubPipeline/fixtures/pipelineConfig.ts Updates fixture for isSecret and workload identity fields
plugins/aks-desktop/src/components/GitHubPipeline/GitHubPipelineWizard.tsx Threads clusterName into workload identity setup component
plugins/aks-desktop/src/components/DeployWizard/utils/yamlGenerator.ts Emits Secret + secretKeyRef env vars; emits ServiceAccount + WI pod config
plugins/aks-desktop/src/components/DeployWizard/hooks/useDeployWorkloadIdentity.ts New deploy-side workload identity setup hook (OIDC issuer + K8s federated cred)
plugins/aks-desktop/src/components/DeployWizard/hooks/useContainerConfiguration.ts Extends container config with isSecret env vars and workload identity fields
plugins/aks-desktop/src/components/DeployWizard/components/DeployWizardPure.stories.tsx Updates stub config for new fields
plugins/aks-desktop/src/components/DeployWizard/components/ConfigureContainer.tsx Adds env var secret toggle/masking; adds workload identity step (create/select identity)
plugins/aks-desktop/src/components/DeployWizard/DeployWizard.tsx Threads Azure context + namespace into container configuration UI
plugins/aks-desktop/src/components/DeployTab/utils/extractContainerConfig.ts Adds round-trip support for secretKeyRef env vars and WI pod config detection
plugins/aks-desktop/src/components/DeployTab/utils/extractContainerConfig.test.ts Updates expected env var structure with isSecret
plugins/aks-desktop/src/components/DeployTab/components/ClusterDeployCard.tsx Threads Azure context into Deploy Wizard
Localize/locales/en/plugin-translation.json Updates localized strings set
Localize/locales/en/frontend-translation.json Adds new localized string key

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

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +1474 to +1482
if (value) {
const saName = getServiceAccountName(
containerConfig.config.appName || 'app'
);
containerConfig.setConfig(c => ({
...c,
workloadIdentityClientId: value.clientId,
workloadIdentityServiceAccount: saName,
}));
Comment on lines +66 to +78
let managedNamespaceResourceId: string | undefined;
if (isManagedNamespace && namespaceName) {
const nsResult = await getManagedNamespaceResourceId({
clusterName,
resourceGroup,
namespaceName,
subscriptionId,
});
if (!nsResult.success || !nsResult.resourceId) {
throw new Error(nsResult.error ?? 'Failed to get managed namespace resource ID');
}
managedNamespaceResourceId = nsResult.resourceId;
}
Comment on lines +3540 to +3545
if (!isValidGuid(subscriptionId)) {
return { success: false, error: 'Invalid subscription ID format' };
}
if (!isValidAzResourceName(resourceGroup)) {
return { success: false, error: 'Invalid resource group format' };
}
Comment on lines +202 to +212
<TextField
label={t('Registry Name')}
size="small"
value={newRegistryName}
onChange={e => setNewRegistryName(e.target.value)}
fullWidth
helperText={t(
'Globally unique name. Only alphanumeric characters, 5-50 characters.'
)}
sx={{ mb: 2 }}
/>
Comment on lines +1470 to +1494
<Autocomplete
options={existingIdentities}
getOptionLabel={option => `${option.name} (${option.clientId})`}
onChange={(_e, value) => {
if (value) {
const saName = getServiceAccountName(
containerConfig.config.appName || 'app'
);
containerConfig.setConfig(c => ({
...c,
workloadIdentityClientId: value.clientId,
workloadIdentityServiceAccount: saName,
}));
}
}}
renderInput={params => (
<TextField
{...params}
label={t('Select managed identity')}
helperText={t(
'Choose an existing user-assigned managed identity. You will still need to create federated credentials manually.'
)}
/>
)}
/>
Comment on lines +69 to +80
return `
- Before applying manifests, create a Kubernetes ServiceAccount for workload identity:
\`kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: ${saName}
namespace: \${{ inputs.namespace }}
annotations:
azure.workload.identity/client-id: "${cc.workloadIdentityClientId}"
EOF\`
- In the Deployment manifest, set \`spec.template.metadata.labels["azure.workload.identity/use"]: "true"\` and \`spec.template.spec.serviceAccountName: ${saName}\`
Comment on lines +146 to +149
if (config.acrLoginServer) {
// Extract ACR name from login server (e.g., "myregistry.azurecr.io" → "myregistry")
secrets.AZURE_ACR_NAME = config.acrLoginServer.split('.')[0];
}
Comment on lines +38 to +105
export async function ensureIdentityWithRoles(
config: EnsureIdentityWithRolesConfig
): Promise<IdentitySetupResult> {
const {
subscriptionId,
resourceGroup,
identityResourceGroup,
identityName,
clusterName,
acrResourceId,
isManagedNamespace = false,
namespaceName,
azureRbacEnabled,
onStatusChange,
} = config;

// Steps 1-3: Ensure RG + identity
const identity = await ensureIdentityAndResourceGroup({
subscriptionId,
resourceGroup,
identityResourceGroup,
identityName,
onStatusChange,
});

// Step 4: Compute and assign required roles
onStatusChange('assigning-roles');

let managedNamespaceResourceId: string | undefined;
if (isManagedNamespace && namespaceName) {
const nsResult = await getManagedNamespaceResourceId({
clusterName,
resourceGroup,
namespaceName,
subscriptionId,
});
if (!nsResult.success || !nsResult.resourceId) {
throw new Error(nsResult.error ?? 'Failed to get managed namespace resource ID');
}
managedNamespaceResourceId = nsResult.resourceId;
}

const roles = computeRequiredRoles({
subscriptionId,
resourceGroup,
clusterName,
acrResourceId,
isManagedNamespace,
managedNamespaceResourceId,
azureRbacEnabled,
});

const roleResult = await assignRolesToIdentity({
principalId: identity.principalId,
subscriptionId,
roles,
});

if (!roleResult.success) {
const failedRoles = roleResult.results
.filter(r => !r.success)
.map(r => `${r.role}: ${r.error}`)
.join('; ');
throw new Error(`Failed to assign roles: ${failedRoles}`);
}

return identity;
}
Comment on lines +169 to +175
const wiEnabled = config.enableWorkloadIdentity && config.workloadIdentityClientId;
const saName = config.workloadIdentityServiceAccount || `${name}-sa`;

const workloadIdentityLabel = wiEnabled ? `\n azure.workload.identity/use: "true"` : '';

const serviceAccountYaml = wiEnabled ? `\n serviceAccountName: ${saName}` : '';

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.

Add secrets support and workload identity to Deploy application flow

2 participants