From 1280b08bd2a84a5d3b37730d10981bc74160a2d6 Mon Sep 17 00:00:00 2001 From: ebronson68 <111298136+ebronson68@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:18:34 -0500 Subject: [PATCH 1/5] Add steps for creating environment variables in Function App --- .github/workflows/azfunction-deploy.yaml | 96 ++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/.github/workflows/azfunction-deploy.yaml b/.github/workflows/azfunction-deploy.yaml index bfbbd544..2a0c1dff 100644 --- a/.github/workflows/azfunction-deploy.yaml +++ b/.github/workflows/azfunction-deploy.yaml @@ -162,6 +162,102 @@ jobs: package: "${{ inputs.AZURE_FUNCTIONAPP_PACKAGE_PATH }}/output" publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE }} + - name: Enable identity for Azure Function + uses: azure/cli@v2 + with: + inlineScript: | + set -eu + if [[ "${{ inputs.environment }}" == "production" ]]; then + az functionapp identity assign \ + -g "${{ inputs.AZURE_FUNCTIONAPP_RESOURCEGROUP }}" \ + -n "${{ inputs.AZURE_FUNCTIONAPP_NAME }}" | tee + else + az functionapp identity assign \ + -g "${{ inputs.AZURE_FUNCTIONAPP_RESOURCEGROUP }}" \ + -n "${{ inputs.AZURE_FUNCTIONAPP_NAME }}" \ + --slot "${{ inputs.environment }}" | tee + fi + + - name: Get Azure Function Managed Identity + id: identity + uses: azure/cli@v2 + with: + inlineScript: | + set -eu + if [[ "${{ inputs.environment }}" == "production" ]]; then + IDENTITY=$(az functionapp identity show \ + -g "${{ inputs.AZURE_FUNCTIONAPP_RESOURCEGROUP }}" \ + -n "${{ inputs.AZURE_FUNCTIONAPP_NAME }}" | tee) + else + IDENTITY=$(az functionapp identity show \ + -g "${{ inputs.AZURE_FUNCTIONAPP_RESOURCEGROUP }}" \ + -n "${{ inputs.AZURE_FUNCTIONAPP_NAME }}" \ + --slot "${{ inputs.environment }}" | tee) + fi + echo "functionAppIdentity=$(echo $IDENTITY | jq -r '.principalId')" >> $GITHUB_ENV + + - name: Retrieve key vault name + uses: azure/cli@v2 + with: + inlineScript: | + set -eu + ENVIRONMENT="${{ inputs.environment }}" + REPOSITORY_NAME="${{ github.event.repository.name }}" + + echo -e "Searching for key vault with tags: \"repository-name=${REPOSITORY_NAME};environment=${ENVIRONMENT}\"" + KEYVAULT_NAME=$(az keyvault list --query "[?tags.\"repository-name\" == '${REPOSITORY_NAME}' && tags.environment == '${ENVIRONMENT}'].name" --output tsv) + + # Check if key vault was found + if [[ -z "$KEYVAULT_NAME" ]]; then + echo "Key Vault not found with tags: repository-name=${REPOSITORY_NAME};environment=${ENVIRONMENT}" + exit 1 + fi + + # Get key vault object + KEYVAULT_NAME=${KEYVAULT_NAME// /} + echo "keyVaultName=${KEYVAULT_NAME}" >> $GITHUB_ENV + + - name: Assign Azure Function System Managed Identity to Key Vault + uses: azure/cli@v2 + with: + inlineScript: | + set -eu + # Assign the Key Vault Secrets User role to the managed identity + az role assignment create --role "Key Vault Secrets User" --assignee ${{ env.functionAppIdentity }} --scope $(az keyvault show --name ${{ env.keyVaultName }} --query id --output tsv) + + - name: Retrieve environment variables + if: ${{ env.AZURE_CREDENTIALS_SET != 'false' }} + id: get-envs + uses: Andrews-McMeel-Universal/get-envs@v1 + with: + azurecredentials: ${{ secrets.AZURE_CREDENTIALS }} + environment: ${{ inputs.environment }} + contentTypes: Env + + - name: Add environment variables to function app + uses: azure/cli@v2 + with: + inlineScript: | + set -eu + # Iterate over each environment variable + for part in ${{ steps.get-envs.outputs.environmentVariables }}; do + part=$(echo $part | xargs) # Trim leading and trailing spaces + IFS='=' read -r key value <<< "$part" + VARIABLE_LC=$(echo "$key" | tr '[:upper:]' '[:lower:]' | tr "_" "-") + if [[ "${{ inputs.environment }}" == "production" ]]; then + az functionapp config appsettings set \ + -g "${{ inputs.AZURE_FUNCTIONAPP_RESOURCEGROUP }}" \ + -n "${{ inputs.AZURE_FUNCTIONAPP_NAME }}" \ + --settings "$key=@Microsoft.KeyVault(VaultName=${{ env.keyVaultName }};SecretName=${VARIABLE_LC})" | tee + else + az functionapp config appsettings set \ + -g "${{ inputs.AZURE_FUNCTIONAPP_RESOURCEGROUP }}" \ + -n "${{ inputs.AZURE_FUNCTIONAPP_NAME }}" \ + --slot "${{ inputs.environment }}" \ + --settings "$key=@Microsoft.KeyVault(VaultName=${{ env.keyVaultName }};SecretName=${VARIABLE_LC})" | tee + fi + done + - name: Remove GitHub Runner IP from Whitelist if: always() uses: azure/cli@v2 From 022a1be24fec3651fa705c72d649eb4bc0f5d12d Mon Sep 17 00:00:00 2001 From: ebronson68 <111298136+ebronson68@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:22:39 -0500 Subject: [PATCH 2/5] Set deployment slot settings --- .github/workflows/azfunction-deploy.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/azfunction-deploy.yaml b/.github/workflows/azfunction-deploy.yaml index 2a0c1dff..d6645835 100644 --- a/.github/workflows/azfunction-deploy.yaml +++ b/.github/workflows/azfunction-deploy.yaml @@ -248,13 +248,13 @@ jobs: az functionapp config appsettings set \ -g "${{ inputs.AZURE_FUNCTIONAPP_RESOURCEGROUP }}" \ -n "${{ inputs.AZURE_FUNCTIONAPP_NAME }}" \ - --settings "$key=@Microsoft.KeyVault(VaultName=${{ env.keyVaultName }};SecretName=${VARIABLE_LC})" | tee + --slot-settings "$key=@Microsoft.KeyVault(VaultName=${{ env.keyVaultName }};SecretName=${VARIABLE_LC})" | tee else az functionapp config appsettings set \ -g "${{ inputs.AZURE_FUNCTIONAPP_RESOURCEGROUP }}" \ -n "${{ inputs.AZURE_FUNCTIONAPP_NAME }}" \ --slot "${{ inputs.environment }}" \ - --settings "$key=@Microsoft.KeyVault(VaultName=${{ env.keyVaultName }};SecretName=${VARIABLE_LC})" | tee + --slot-settings "$key=@Microsoft.KeyVault(VaultName=${{ env.keyVaultName }};SecretName=${VARIABLE_LC})" | tee fi done From 468c14cc96e6398bbe251d4ff755c771ee04ef9e Mon Sep 17 00:00:00 2001 From: ebronson68 <111298136+ebronson68@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:56:36 -0500 Subject: [PATCH 3/5] Fix env var loop and key vault id query errors --- .github/workflows/azfunction-deploy.yaml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/azfunction-deploy.yaml b/.github/workflows/azfunction-deploy.yaml index d6645835..307e9c5a 100644 --- a/.github/workflows/azfunction-deploy.yaml +++ b/.github/workflows/azfunction-deploy.yaml @@ -222,8 +222,14 @@ jobs: with: inlineScript: | set -eu - # Assign the Key Vault Secrets User role to the managed identity - az role assignment create --role "Key Vault Secrets User" --assignee ${{ env.functionAppIdentity }} --scope $(az keyvault show --name ${{ env.keyVaultName }} --query id --output tsv) + # Retrieve the object ID of the managed identity + objectId=$(az ad sp show --id ${{ env.functionAppIdentity }} --query objectId --output tsv) + + # Retrieve the Key Vault ID + keyVaultId=$(az keyvault show --name ${{ env.keyVaultName }} --query id --output tsv) + + # Assign the Key Vault Secrets User role to the managed identity using object ID and principal type + az role assignment create --role "Key Vault Secrets User" --assignee-object-id $objectId --assignee-principal-type ServicePrincipal --scope $keyVaultId - name: Retrieve environment variables if: ${{ env.AZURE_CREDENTIALS_SET != 'false' }} @@ -240,8 +246,10 @@ jobs: inlineScript: | set -eu # Iterate over each environment variable - for part in ${{ steps.get-envs.outputs.environmentVariables }}; do - part=$(echo $part | xargs) # Trim leading and trailing spaces + + ENV_VARS=($(echo '${{ steps.get-envs.outputs.environmentVariables }}')) + + for part in ${ENV_VARS[@]}; do IFS='=' read -r key value <<< "$part" VARIABLE_LC=$(echo "$key" | tr '[:upper:]' '[:lower:]' | tr "_" "-") if [[ "${{ inputs.environment }}" == "production" ]]; then From 48e2bb09d9c35823db5315f60a38ffb918459ae6 Mon Sep 17 00:00:00 2001 From: ebronson68 <111298136+ebronson68@users.noreply.github.com> Date: Tue, 20 Aug 2024 17:14:06 -0500 Subject: [PATCH 4/5] Don't look up AD SP ID --- .github/workflows/azfunction-deploy.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/azfunction-deploy.yaml b/.github/workflows/azfunction-deploy.yaml index 307e9c5a..b04eb8fb 100644 --- a/.github/workflows/azfunction-deploy.yaml +++ b/.github/workflows/azfunction-deploy.yaml @@ -222,14 +222,11 @@ jobs: with: inlineScript: | set -eu - # Retrieve the object ID of the managed identity - objectId=$(az ad sp show --id ${{ env.functionAppIdentity }} --query objectId --output tsv) - # Retrieve the Key Vault ID keyVaultId=$(az keyvault show --name ${{ env.keyVaultName }} --query id --output tsv) # Assign the Key Vault Secrets User role to the managed identity using object ID and principal type - az role assignment create --role "Key Vault Secrets User" --assignee-object-id $objectId --assignee-principal-type ServicePrincipal --scope $keyVaultId + az role assignment create --role "Key Vault Secrets User" --assignee-object-id --assignee-principal-type ServicePrincipal ${{ env.functionAppIdentity }} --scope $keyVaultId - name: Retrieve environment variables if: ${{ env.AZURE_CREDENTIALS_SET != 'false' }} From 433f2c9a8bb82d96209c9eb3bf1c701ba576f495 Mon Sep 17 00:00:00 2001 From: ebronson68 <111298136+ebronson68@users.noreply.github.com> Date: Wed, 21 Aug 2024 09:18:26 -0500 Subject: [PATCH 5/5] Fixing positional arguments --- .github/workflows/azfunction-deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/azfunction-deploy.yaml b/.github/workflows/azfunction-deploy.yaml index b04eb8fb..229e125e 100644 --- a/.github/workflows/azfunction-deploy.yaml +++ b/.github/workflows/azfunction-deploy.yaml @@ -226,7 +226,7 @@ jobs: keyVaultId=$(az keyvault show --name ${{ env.keyVaultName }} --query id --output tsv) # Assign the Key Vault Secrets User role to the managed identity using object ID and principal type - az role assignment create --role "Key Vault Secrets User" --assignee-object-id --assignee-principal-type ServicePrincipal ${{ env.functionAppIdentity }} --scope $keyVaultId + az role assignment create --role "Key Vault Secrets User" --assignee-object-id ${{ env.functionAppIdentity }} --assignee-principal-type ServicePrincipal --scope $keyVaultId - name: Retrieve environment variables if: ${{ env.AZURE_CREDENTIALS_SET != 'false' }}