@@ -327,17 +327,26 @@ jobs:
327327 --name "$TFSTATE_STORAGE_ACCOUNT" \
328328 --query publicNetworkAccess -o tsv)"
329329
330+ current_default_action="$(az storage account show \
331+ --resource-group "$TFSTATE_RESOURCE_GROUP" \
332+ --name "$TFSTATE_STORAGE_ACCOUNT" \
333+ --query networkRuleSet.defaultAction -o tsv)"
334+
330335 if [ "$current_access" = "Disabled" ]; then
331- echo "Enabling public network access on Terraform state storage account for CI connectivity."
332- az storage account update \
333- --resource-group "$TFSTATE_RESOURCE_GROUP" \
334- --name "$TFSTATE_STORAGE_ACCOUNT" \
335- --public-network-access Enabled \
336- --only-show-errors >/dev/null
336+ echo "Terraform state storage account has publicNetworkAccess=Disabled."
337+ echo "Permanent fix required: keep secure baseline and provide CI reachability (for example via approved runner egress/network path)."
338+ exit 1
339+ fi
340+
341+ if [ "$current_default_action" = "Deny" ]; then
342+ echo "Terraform state storage account has networkRuleSet.defaultAction=Deny."
343+ echo "Permanent fix required: keep secure baseline and provide CI reachability (for example via approved runner egress/network path)."
344+ exit 1
337345 fi
338346
339347 - name : Ensure Terraform state RBAC for OIDC principal
340348 env :
349+ AZURE_CLIENT_ID : ${{ secrets.AZURE_CLIENT_ID }}
341350 TFSTATE_RESOURCE_GROUP : ${{ secrets.TERRAFORM_STATE_RESOURCE_GROUP }}
342351 TFSTATE_STORAGE_ACCOUNT : ${{ secrets.TERRAFORM_STATE_STORAGE_ACCOUNT }}
343352 TFSTATE_CONTAINER : ${{ secrets.TERRAFORM_STATE_CONTAINER }}
@@ -349,11 +358,17 @@ jobs:
349358 --name "$TFSTATE_STORAGE_ACCOUNT" \
350359 --query id -o tsv)"
351360
352- ACCESS_TOKEN="$(az account get-access-token \
353- --resource https://management.azure.com/ \
354- --query accessToken -o tsv)"
361+ CONTAINER_SCOPE="${STORAGE_SCOPE}/blobServices/default/containers/${TFSTATE_CONTAINER}"
355362
356- PRINCIPAL_OBJECT_ID="$(ACCESS_TOKEN="$ACCESS_TOKEN" python -c "import base64,json,os; t=os.environ.get('ACCESS_TOKEN',''); p=t.split('.'); payload=(p[1] + '=' * (-len(p[1]) % 4)) if len(p) > 1 else ''; print(json.loads(base64.urlsafe_b64decode(payload.encode('utf-8')).decode('utf-8')).get('oid','') if payload else '')")"
363+ PRINCIPAL_OBJECT_ID="$(az ad sp show --id "$AZURE_CLIENT_ID" --query id -o tsv 2>/dev/null || true)"
364+
365+ if [ -z "$PRINCIPAL_OBJECT_ID" ]; then
366+ ACCESS_TOKEN="$(az account get-access-token \
367+ --resource https://management.azure.com/ \
368+ --query accessToken -o tsv)"
369+
370+ PRINCIPAL_OBJECT_ID="$(ACCESS_TOKEN="$ACCESS_TOKEN" python -c "import base64,json,os; t=os.environ.get('ACCESS_TOKEN',''); p=t.split('.'); payload=(p[1] + '=' * (-len(p[1]) % 4)) if len(p) > 1 else ''; print(json.loads(base64.urlsafe_b64decode(payload.encode('utf-8')).decode('utf-8')).get('oid','') if payload else '')")"
371+ fi
357372
358373 if [ -z "$PRINCIPAL_OBJECT_ID" ]; then
359374 echo "Unable to resolve OIDC principal object id from access token."
@@ -364,25 +379,18 @@ jobs:
364379 --assignee-object-id "$PRINCIPAL_OBJECT_ID" \
365380 --assignee-principal-type ServicePrincipal \
366381 --role "Storage Blob Data Contributor" \
367- --scope "$STORAGE_SCOPE" \
368- --only-show-errors >/dev/null || true
369-
370- az role assignment create \
371- --assignee-object-id "$PRINCIPAL_OBJECT_ID" \
372- --assignee-principal-type ServicePrincipal \
373- --role "Storage Blob Data Owner" \
374- --scope "$STORAGE_SCOPE" \
382+ --scope "$CONTAINER_SCOPE" \
375383 --only-show-errors >/dev/null || true
376384
377- ASSIGNMENT_COUNT ="$(az role assignment list \
385+ CONTAINER_ASSIGNMENT_COUNT ="$(az role assignment list \
378386 --assignee-object-id "$PRINCIPAL_OBJECT_ID" \
379- --scope "$STORAGE_SCOPE " \
387+ --scope "$CONTAINER_SCOPE " \
380388 --role "Storage Blob Data Contributor" \
381389 --query 'length(@)' -o tsv)"
382390
383- if [ "$ASSIGNMENT_COUNT " = "0" ]; then
384- echo "OIDC principal is missing 'Storage Blob Data Contributor' on Terraform state storage account ."
385- echo "Grant role on scope: $STORAGE_SCOPE "
391+ if [ "$CONTAINER_ASSIGNMENT_COUNT " = "0" ]; then
392+ echo "OIDC principal is missing 'Storage Blob Data Contributor' on Terraform state container scope ."
393+ echo "Grant role on scope: $CONTAINER_SCOPE "
386394 exit 1
387395 fi
388396
@@ -391,7 +399,12 @@ jobs:
391399 max_attempts=20
392400 attempt=1
393401 while [ "$attempt" -le "$max_attempts" ]; do
394- if az storage blob list \
402+ if az storage container show \
403+ --account-name "$TFSTATE_STORAGE_ACCOUNT" \
404+ --name "$TFSTATE_CONTAINER" \
405+ --auth-mode login \
406+ --only-show-errors >/dev/null 2>&1 && \
407+ az storage blob list \
395408 --account-name "$TFSTATE_STORAGE_ACCOUNT" \
396409 --container-name "$TFSTATE_CONTAINER" \
397410 --auth-mode login \
@@ -568,6 +581,24 @@ jobs:
568581 while [ "$attempt" -le "$max_attempts" ]; do
569582 echo "Provision attempt $attempt/$max_attempts"
570583
584+ if ! az storage blob list \
585+ --account-name "$RS_STORAGE_ACCOUNT" \
586+ --container-name "$RS_CONTAINER_NAME" \
587+ --auth-mode login \
588+ --num-results 1 \
589+ --only-show-errors >/dev/null 2>&1; then
590+ if [ "$attempt" -eq "$max_attempts" ]; then
591+ echo "Terraform state data-plane access is still unavailable after $max_attempts attempts."
592+ exit 1
593+ fi
594+
595+ sleep_seconds=$((attempt * 60))
596+ echo "State data-plane access not ready yet. Waiting ${sleep_seconds}s before retry."
597+ sleep "$sleep_seconds"
598+ attempt=$((attempt + 1))
599+ continue
600+ fi
601+
571602 set +e
572603 provision_output="$(azd provision --no-prompt --debug 2>&1)"
573604 provision_exit=$?
@@ -585,7 +616,7 @@ jobs:
585616 exit 1
586617 fi
587618
588- if ! echo "$provision_output" | grep -Eq 'RequestConflict|Failed to create/update resource|ContainerAppOperationInProgress|Operation expired'; then
619+ if ! echo "$provision_output" | grep -Eq 'RequestConflict|Failed to create/update resource|ContainerAppOperationInProgress|Operation expired|AuthorizationFailure|Failed to get existing workspaces|listing blobs|terraform init failed '; then
589620 echo "Provision failed with a non-transient error; not retrying further."
590621 exit "$provision_exit"
591622 fi
0 commit comments