Summary
Prerequisite for #173 (CD: GitHub Action to provision a sandbox).
scripts/bootstrap.sh and scripts/bootstrap.ps1 generate terraform.tfvars, but only in an
interactive way that can't run in CD:
- They use interactive prompts (
read -e / Read-Host) with defaults — they cannot complete unattended.
- They derive
user_object_id by JWT-decoding the Azure CLI signed-in user's access token (via
PyJWT). Under a CD managed identity / OIDC, the signed-in identity is the runner, not the human
admin, so this yields the wrong object id.
- They depend on
PyJWT (bootstrap.sh) just to decode the signed-in user's oid.
- They always comment out the
enable_module_* toggles, so module enablement must be edited
separately — CD needs to set these from inputs.
Goal
Add a headless / non-interactive mode to both scripts (kept equivalent) so the same scripts are
the single source of truth for terraform.tfvars generation in both manual and CD flows.
Acceptance criteria
Notes
Summary
Prerequisite for #173 (CD: GitHub Action to provision a sandbox).
scripts/bootstrap.shandscripts/bootstrap.ps1generateterraform.tfvars, but only in aninteractive way that can't run in CD:
read -e/Read-Host) with defaults — they cannot complete unattended.user_object_idby JWT-decoding the Azure CLI signed-in user's access token (viaPyJWT). Under a CD managed identity / OIDC, the signed-in identity is the runner, not the human
admin, so this yields the wrong object id.
PyJWT(bootstrap.sh) just to decode the signed-in user'soid.enable_module_*toggles, so module enablement must be editedseparately — CD needs to set these from inputs.
Goal
Add a headless / non-interactive mode to both scripts (kept equivalent) so the same scripts are
the single source of truth for
terraform.tfvarsgeneration in both manual and CD flows.Acceptance criteria
--non-interactive/-NonInteractive) that fails fast on anymissing required value instead of prompting.
aad_tenant_id, user_name/UPN, subscription_id, location, tags, and module toggles).
user_object_idresolved from a provided UPN via Microsoft Graph (az ad user show --id <upn>/Get-AzADUser) rather than JWT-decoding the signed-in user — so it works under a CDmanaged identity where the signed-in identity is not the admin. Direct
user_object_idinputshould also be accepted to skip the lookup. Removes the hard PyJWT dependency in that path.
enable_module_*toggles (uncommented) from inputs.user_nameUPN-format validation still enforced; no blankuser_namewritten.Notes
identity (no
TF_VAR_arm_client_secret), so the secret check should be conditional on auth mode.