diff --git a/.github/workflows/contoso-traders-provisioning-deployment-template.yml b/.github/workflows/contoso-traders-provisioning-deployment-template.yml new file mode 100644 index 0000000..05b0cdd --- /dev/null +++ b/.github/workflows/contoso-traders-provisioning-deployment-template.yml @@ -0,0 +1,342 @@ +name: template + +on: + workflow_call: + inputs: + environmentName: + required: true + type: string + +env: + # You can specify any location for `SUB_DEPLOYMENT_REGION`. It's the region where the deployment + # metadata will be stored, and not where the resource groups will be deployed. + ACR_NAME: contosotradersacr + AKS_CLUSTER_NAME: contoso-traders-aks + AKS_DNS_LABEL: contoso-traders-products + AKS_NODES_RESOURCE_GROUP_NAME: contoso-traders-aks-nodes-rg + AKS_SECRET_NAME_ACR_PASSWORD: contoso-traders-acr-password + AKS_SECRET_NAME_KV_ENDPOINT: contoso-traders-kv-endpoint + AKS_SECRET_NAME_MI_CLIENTID: contoso-traders-mi-clientid + CARTS_ACA_NAME: contoso-traders-carts + CARTS_ACR_REPOSITORY_NAME: contosotradersapicarts + CDN_PROFILE_NAME: contoso-traders-cdn + SUB_DEPLOYMENT_REGION: eastus2 + KV_NAME: contosotraderskv + PRODUCTS_ACR_REPOSITORY_NAME: contosotradersapiproducts + PRODUCTS_DB_NAME: productsdb + PRODUCTS_DB_SERVER_NAME: contoso-traders-products + PRODUCTS_DB_USER_NAME: localadmin + PRODUCT_DETAILS_CONTAINER_NAME: product-details + PRODUCT_IMAGES_STORAGE_ACCOUNT_NAME: contosotradersimg + PRODUCT_LIST_CONTAINER_NAME: product-list + PRODUCTS_CDN_ENDPOINT_NAME: contoso-traders-images + RESOURCE_GROUP_NAME: contoso-traders-rg + STORAGE_ACCOUNT_NAME: contosotradersimg + UI_CDN_ENDPOINT_NAME: contoso-traders-ui2 + UI_STORAGE_ACCOUNT_NAME: contosotradersui2 + USER_ASSIGNED_MANAGED_IDENTITY_NAME: contoso-traders-mi-kv-access + +jobs: + provision-infrastructure: + runs-on: ubuntu-latest + environment: ${{ inputs.environmentName }} + steps: + - name: checkout code + uses: actions/checkout@v3 + - name: azure login + uses: azure/login@v1 + with: + creds: ${{ secrets.SERVICEPRINCIPAL }} + # The first step is to create the resource group: `contoso-traders-rg`. + # The below step can also be manually executed as follows: + # az deployment sub create --location {LOCATION} --template-file .\createResourceGroup.bicep + # Note: You can specify any location for `{LOCATION}`. It's the region where the deployment metadata will be stored, and not + # where the resource groups will be deployed. + - name: create resource group + uses: Azure/arm-deploy@v1 + with: + scope: subscription + region: ${{ env.SUB_DEPLOYMENT_REGION }} + template: ./iac/createResourceGroup.bicep + # Next step is to deploy the Azure resources to the resource group `contoso-traders-rg` created above. The deployed resources + # include storage accounts, function apps, app services cosmos db, and service bus etc. + # The below step can also be manually executed as follows: + # az deployment group create -g contoso-traders-rg --template-file .\createResources.bicep --parameters .\createResources.parameters.json + # Note: The `createResources.parameters.json` file contains the parameters for the deployment; specifically the environment name. + # You can modify the parameters to customize the deployment. + - name: create resources + uses: Azure/arm-deploy@v1 + with: + scope: resourcegroup + region: ${{ env.SUB_DEPLOYMENT_REGION }} + resourceGroupName: ${{ env.RESOURCE_GROUP_NAME }} + template: ./iac/createResources.bicep + parameters: ./iac/createResources.parameters.json environment=${{ secrets.ENVIRONMENT_SUFFIX }} sqlPassword=${{ secrets.SQL_PASSWORD }} + failOnStdErr: false # @TODO: Remove this later. Temporarily added to suppress warnings-as-errors during execution. + # Add the logged-in service principal to the key vault access policy + - name: add service principal to kv access policy + uses: azure/CLI@v1 + with: + inlineScript: az keyvault set-policy -n ${{ env.KV_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} --secret-permissions get list set --object-id $(az ad sp show --id $(az account show --query "user.name" -o tsv) --query "id" -o tsv) + # The AKS agent pool needs to be assigned the user-assigned managed identity created (which has kv access) + - name: assign user-assigned managed-identity to aks agentpool + uses: azure/CLI@v1 + with: + inlineScript: | + az vmss identity assign \ + --identities $(az identity show -g ${{ env.RESOURCE_GROUP_NAME }} --name ${{ env.USER_ASSIGNED_MANAGED_IDENTITY_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} --query "id" -o tsv) \ + --ids $(az vmss list -g ${{ env.AKS_NODES_RESOURCE_GROUP_NAME }} --query "[0].id" -o tsv) \ + # Seed the DBs and storage accounts + - name: seed products db + uses: azure/sql-action@v2 + with: + connection-string: Server=tcp:${{ env.PRODUCTS_DB_SERVER_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.database.windows.net,1433;Initial Catalog=${{ env.PRODUCTS_DB_NAME }};Persist Security Info=False;User ID=${{ env.PRODUCTS_DB_USER_NAME }};Password=${{ secrets.SQL_PASSWORD }};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30; + path: ./src/ContosoTraders.Api.Products/Migration/productsdb.sql + - name: seed product image (product details) + uses: azure/CLI@v1 + with: + inlineScript: az storage blob sync --account-name '${{ env.PRODUCT_IMAGES_STORAGE_ACCOUNT_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}' -c '${{ env.PRODUCT_DETAILS_CONTAINER_NAME }}' -s 'src/ContosoTraders.Api.Images/product-details' + - name: seed product image (product list) + uses: azure/CLI@v1 + with: + inlineScript: az storage blob sync --account-name '${{ env.PRODUCT_IMAGES_STORAGE_ACCOUNT_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}' -c '${{ env.PRODUCT_LIST_CONTAINER_NAME }}' -s 'src/ContosoTraders.Api.Images/product-list' + - name: purge CDN endpoint + uses: azure/CLI@v1 + with: + inlineScript: az cdn endpoint purge --no-wait --content-paths '/*' -n '${{ env.PRODUCTS_CDN_ENDPOINT_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}' -g '${{ env.RESOURCE_GROUP_NAME }}' --profile-name '${{ env.CDN_PROFILE_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}' + + deploy-carts-api: + runs-on: ubuntu-latest + environment: ${{ inputs.environmentName }} + needs: provision-infrastructure + steps: + - name: checkout code + uses: actions/checkout@v3 + - name: azure login + uses: azure/login@v1 + with: + creds: ${{ secrets.SERVICEPRINCIPAL }} + - name: extract acr password + uses: azure/CLI@v1 + id: extract-acr-password + with: + inlineScript: echo "acrPassword"="$(az acr credential show -n ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} -g ${{ env.RESOURCE_GROUP_NAME }} --query "passwords[0].value" --output tsv)" >> $GITHUB_OUTPUT + - name: azure container registry login + uses: azure/docker-login@v1 + with: + login-server: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io + username: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} + password: ${{ steps.extract-acr-password.outputs.acrPassword }} + - name: docker build + run: docker build src -f ./src/ContosoTraders.Api.Carts/Dockerfile -t ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io/${{ env.CARTS_ACR_REPOSITORY_NAME }}:latest -t ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io/${{ env.CARTS_ACR_REPOSITORY_NAME }}:${{ github.sha }} + - name: docker push (to acr) + run: docker push --all-tags ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io/${{ env.CARTS_ACR_REPOSITORY_NAME }} + - name: deploy to aca + uses: azure/CLI@v1 + with: + inlineScript: | + az config set extension.use_dynamic_install=yes_without_prompt + az containerapp update -n ${{ env.CARTS_ACA_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} -g ${{ env.RESOURCE_GROUP_NAME }} --image ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io/${{ env.CARTS_ACR_REPOSITORY_NAME }}:${{ github.sha }} + + deploy-products-api: + runs-on: ubuntu-latest + environment: ${{ inputs.environmentName }} + needs: provision-infrastructure + steps: + - name: checkout code + uses: actions/checkout@v3 + - name: azure login + uses: azure/login@v1 + with: + creds: ${{ secrets.SERVICEPRINCIPAL }} + - name: install helm + uses: Azure/setup-helm@v3 + id: install-helm + - name: extract acr password + uses: azure/CLI@v1 + id: extract-acr-password + with: + inlineScript: echo "acrPassword"="$(az acr credential show -n ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} -g ${{ env.RESOURCE_GROUP_NAME }} --query "passwords[0].value" --output tsv)" >> $GITHUB_OUTPUT + - name: azure container registry login + uses: azure/docker-login@v1 + with: + login-server: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io + username: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} + password: ${{ steps.extract-acr-password.outputs.acrPassword }} + - name: docker build + run: docker build src -f ./src/ContosoTraders.Api.Products/Dockerfile -t ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io/${{ env.PRODUCTS_ACR_REPOSITORY_NAME }}:latest -t ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io/${{ env.PRODUCTS_ACR_REPOSITORY_NAME }}:${{ github.sha }} + - name: docker push (to acr) + run: docker push --all-tags ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io/${{ env.PRODUCTS_ACR_REPOSITORY_NAME }} + - name: set aks context + uses: azure/aks-set-context@v3 + with: + resource-group: ${{ env.RESOURCE_GROUP_NAME }} + cluster-name: ${{ env.AKS_CLUSTER_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} + - name: setup kubectl + uses: azure/setup-kubectl@v3 + - name: create kubernetes secret (acr password) + uses: Azure/k8s-create-secret@v3.0 + with: + secret-name: ${{ env.AKS_SECRET_NAME_ACR_PASSWORD }} + container-registry-url: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io + container-registry-username: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} + container-registry-password: ${{ steps.extract-acr-password.outputs.acrPassword }} + - name: get managedIdentityClientId + uses: azure/CLI@v1 + id: get-managedIdentityClientId + with: + inlineScript: echo "managedIdentityClientId"="$(az identity show -g ${{ env.RESOURCE_GROUP_NAME }} --name ${{ env.USER_ASSIGNED_MANAGED_IDENTITY_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} --query "clientId" -o tsv)" >> $GITHUB_OUTPUT + - name: create kubernetes secret (kv endpoint) + uses: Azure/k8s-create-secret@v3.0 + with: + secret-type: "generic" + secret-name: ${{ env.AKS_SECRET_NAME_KV_ENDPOINT }} + string-data: '{ "${{ env.AKS_SECRET_NAME_KV_ENDPOINT }}" : "https://${{ env.KV_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.vault.azure.net/" }' + - name: create kubernetes secret (managed identity client id) + uses: Azure/k8s-create-secret@v3.0 + with: + secret-type: "generic" + secret-name: ${{ env.AKS_SECRET_NAME_MI_CLIENTID }} + string-data: '{ "${{ env.AKS_SECRET_NAME_MI_CLIENTID }}" : "${{ steps.get-managedIdentityClientId.outputs.managedIdentityClientId }}" }' + - name: substitute tokens in deployment manifest + uses: cschleiden/replace-tokens@v1.2 + with: + tokenPrefix: "{" + tokenSuffix: "}" + files: ./src/ContosoTraders.Api.Products/Manifests/Deployment.yaml + env: + ENVIRONMENT: ${{ secrets.ENVIRONMENT_SUFFIX }} + - name: lint deployment manifest + uses: azure/k8s-lint@v1 + with: + manifests: ./src/ContosoTraders.Api.Products/Manifests/Deployment.yaml + - name: apply deployment manifest + uses: Azure/k8s-deploy@v4 + with: + manifests: ./src/ContosoTraders.Api.Products/Manifests/Deployment.yaml + images: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}.azurecr.io/${{ env.PRODUCTS_ACR_REPOSITORY_NAME }}:${{ github.sha }} + imagepullsecrets: ${{ env.AKS_SECRET_NAME_ACR_PASSWORD }} + force: true + - name: apply service manifest + uses: Azure/k8s-deploy@v4 + with: + manifests: ./src/ContosoTraders.Api.Products/Manifests/Service.yaml + force: true + # create the ingress controller + - name: create ingress controller + run: | + az aks get-credentials --resource-group ${{ env.RESOURCE_GROUP_NAME }} --name ${{ env.AKS_CLUSTER_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} + ${{ steps.install-helm.outputs.helm-path }} repo add ingress-nginx https://kubernetes.github.io/ingress-nginx + ${{ steps.install-helm.outputs.helm-path }} repo update + ${{ steps.install-helm.outputs.helm-path }} upgrade --install nginx-ingress ingress-nginx/ingress-nginx \ + --set controller.replicaCount=1 \ + --set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \ + --set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux \ + --set controller.admissionWebhooks.patch.nodeSelector."beta\.kubernetes\.io/os"=linux \ + --set controller.service.externalTrafficPolicy=Local + - name: set dns label on public ip + uses: azure/CLI@v1 + with: + inlineScript: az network public-ip update --dns-name ${{ env.AKS_DNS_LABEL }}${{ secrets.ENVIRONMENT_SUFFIX }} -g ${{ env.AKS_NODES_RESOURCE_GROUP_NAME }} -n $(az network public-ip list --query "[?starts_with(name,'kubernetes-') ].name" -o tsv -g ${{ env.AKS_NODES_RESOURCE_GROUP_NAME }}) + # hack: extract the full fqdn / dns label of the aks app's public IP address + - name: get aks-fqdn + uses: azure/CLI@v1 + id: get-aks-fqdn + with: + # note: There should be a whitespace between ')' and ']'. More details: https://stackoverflow.com/a/59154958 + inlineScript: echo "aksFqdn"="$(az network public-ip list --query "[?starts_with(name,'kubernetes-') ].dnsSettings.fqdn" -o tsv -g ${{ env.AKS_NODES_RESOURCE_GROUP_NAME }})" >> $GITHUB_OUTPUT + # install cert-manager + - name: apply namespace manifest + uses: Azure/k8s-deploy@v4 + with: + manifests: ./src/ContosoTraders.Api.Products/Manifests/Namespace.yaml + force: true + - name: install cert-manager + run: | + az aks get-credentials --resource-group ${{ env.RESOURCE_GROUP_NAME }} --name ${{ env.AKS_CLUSTER_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} + kubectl apply --validate=false -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml + - name: apply clusterIssuer manifest + uses: Azure/k8s-deploy@v4 + with: + manifests: ./src/ContosoTraders.Api.Products/Manifests/ClusterIssuer.yaml + force: true + - name: substitute tokens in certificate manifest + uses: cschleiden/replace-tokens@v1.2 + with: + tokenPrefix: "{" + tokenSuffix: "}" + files: ./src/ContosoTraders.Api.Products/Manifests/Certificate.yaml + env: + AKS_FQDN: ${{ steps.get-aks-fqdn.outputs.aksFqdn }} + - name: apply certificate manifest + uses: Azure/k8s-deploy@v4 + with: + manifests: ./src/ContosoTraders.Api.Products/Manifests/Certificate.yaml + force: true + - name: substitute tokens in ingress manifest + uses: cschleiden/replace-tokens@v1.2 + with: + tokenPrefix: "{" + tokenSuffix: "}" + files: ./src/ContosoTraders.Api.Products/Manifests/Ingress.yaml + env: + AKS_FQDN: ${{ steps.get-aks-fqdn.outputs.aksFqdn }} + - name: apply ingress manifest + uses: Azure/k8s-deploy@v4 + with: + manifests: ./src/ContosoTraders.Api.Products/Manifests/Ingress.yaml + force: true + - name: apply clusterRole manifest + uses: Azure/k8s-deploy@v4 + with: + manifests: ./src/ContosoTraders.Api.Products/Manifests/ClusterRole.yaml + force: true + - name: set productsApiEndpoint in kv + uses: azure/CLI@v1 + with: + inlineScript: az keyvault secret set --vault-name ${{ env.KV_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} --name productsApiEndpoint --value ${{ steps.get-aks-fqdn.outputs.aksFqdn }} --description "endpoint url (fqdn) of the products api" + + deploy-ui: + runs-on: ubuntu-latest + environment: ${{ inputs.environmentName }} + needs: [provision-infrastructure, deploy-carts-api, deploy-products-api] + steps: + - name: checkout code + uses: actions/checkout@v3 + - name: azure login + uses: azure/login@v1 + with: + creds: ${{ secrets.SERVICEPRINCIPAL }} + - name: get carts api endpoint + uses: azure/CLI@v1 + id: get-cartsApiEndpoint + with: + inlineScript: echo "cartsApiEndpoint"="$(az keyvault secret show --vault-name ${{ env.KV_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} --name cartsApiEndpoint --query value -o tsv)" >> $GITHUB_OUTPUT + - name: get products api endpoint + uses: azure/CLI@v1 + id: get-productsApiEndpoint + with: + inlineScript: echo "productsApiEndpoint"="$(az keyvault secret show --vault-name ${{ env.KV_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }} --name productsApiEndpoint --query value -o tsv)" >> $GITHUB_OUTPUT + - name: substitute tokens in ui configuration + uses: cschleiden/replace-tokens@v1.2 + with: + tokenPrefix: "{{" + tokenSuffix: "}}" + files: ./src/ContosoTraders.Ui.Website/.env + env: + CARTS_API_ENDPOINT: ${{ steps.get-cartsApiEndpoint.outputs.cartsApiEndpoint }} + PRODUCTS_API_ENDPOINT: ${{ steps.get-productsApiEndpoint.outputs.productsApiEndpoint }} + - name: npm install + run: npm install + working-directory: src/ContosoTraders.Ui.Website + - name: npm run build + run: npm run build + working-directory: src/ContosoTraders.Ui.Website + - name: deploy to storage + uses: azure/CLI@v1 + with: + inlineScript: az storage blob sync --account-name '${{ env.UI_STORAGE_ACCOUNT_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}' -c '$web' -s 'src/ContosoTraders.Ui.Website/build' + - name: purge CDN endpoint + uses: azure/CLI@v1 + with: + inlineScript: az cdn endpoint purge --no-wait --content-paths '/*' -n '${{ env.UI_CDN_ENDPOINT_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}' -g '${{ env.RESOURCE_GROUP_NAME }}' --profile-name '${{ env.CDN_PROFILE_NAME }}${{ secrets.ENVIRONMENT_SUFFIX }}' diff --git a/.github/workflows/contoso-traders-provisioning-deployment.yml b/.github/workflows/contoso-traders-provisioning-deployment.yml index 45041f2..86cd17b 100644 --- a/.github/workflows/contoso-traders-provisioning-deployment.yml +++ b/.github/workflows/contoso-traders-provisioning-deployment.yml @@ -13,332 +13,12 @@ on: "src/ContosoTraders.Ui.Website/**", ] -env: - # You can specify any location for `SUB_DEPLOYMENT_REGION`. It's the region where the deployment - # metadata will be stored, and not where the resource groups will be deployed. - ACR_NAME: contosotradersacr - AKS_CLUSTER_NAME: contoso-traders-aks - AKS_DNS_LABEL: contoso-traders-products - AKS_NODES_RESOURCE_GROUP_NAME: contoso-traders-aks-nodes-rg - AKS_SECRET_NAME_ACR_PASSWORD: contoso-traders-acr-password - AKS_SECRET_NAME_KV_ENDPOINT: contoso-traders-kv-endpoint - AKS_SECRET_NAME_MI_CLIENTID: contoso-traders-mi-clientid - CARTS_ACA_NAME: contoso-traders-carts - CARTS_ACR_REPOSITORY_NAME: contosotradersapicarts - CDN_PROFILE_NAME: contoso-traders-cdn - SUB_DEPLOYMENT_REGION: eastus2 - KV_NAME: contosotraderskv - PRODUCTS_ACR_REPOSITORY_NAME: contosotradersapiproducts - PRODUCTS_DB_NAME: productsdb - PRODUCTS_DB_SERVER_NAME: contoso-traders-products - PRODUCTS_DB_USER_NAME: localadmin - PRODUCT_DETAILS_CONTAINER_NAME: product-details - PRODUCT_IMAGES_STORAGE_ACCOUNT_NAME: contosotradersimg - PRODUCT_LIST_CONTAINER_NAME: product-list - PRODUCTS_CDN_ENDPOINT_NAME: contoso-traders-images - RESOURCE_GROUP_NAME: contoso-traders-rg - STORAGE_ACCOUNT_NAME: contosotradersimg - UI_CDN_ENDPOINT_NAME: contoso-traders-ui2 - UI_STORAGE_ACCOUNT_NAME: contosotradersui2 - USER_ASSIGNED_MANAGED_IDENTITY_NAME: contoso-traders-mi-kv-access - jobs: - provision-infrastructure: - runs-on: ubuntu-latest - steps: - - name: checkout code - uses: actions/checkout@v3 - - name: azure login - uses: azure/login@v1 - with: - creds: ${{ secrets.SERVICEPRINCIPAL }} - # The first step is to create the resource group: `contoso-traders-rg`. - # The below step can also be manually executed as follows: - # az deployment sub create --location {LOCATION} --template-file .\createResourceGroup.bicep - # Note: You can specify any location for `{LOCATION}`. It's the region where the deployment metadata will be stored, and not - # where the resource groups will be deployed. - - name: create resource group - uses: Azure/arm-deploy@v1 - with: - scope: subscription - region: ${{ env.SUB_DEPLOYMENT_REGION }} - template: ./iac/createResourceGroup.bicep - # Next step is to deploy the Azure resources to the resource group `contoso-traders-rg` created above. The deployed resources - # include storage accounts, function apps, app services cosmos db, and service bus etc. - # The below step can also be manually executed as follows: - # az deployment group create -g contoso-traders-rg --template-file .\createResources.bicep --parameters .\createResources.parameters.json - # Note: The `createResources.parameters.json` file contains the parameters for the deployment; specifically the environment name. - # You can modify the parameters to customize the deployment. - - name: create resources - uses: Azure/arm-deploy@v1 - with: - scope: resourcegroup - region: ${{ env.SUB_DEPLOYMENT_REGION }} - resourceGroupName: ${{ env.RESOURCE_GROUP_NAME }} - template: ./iac/createResources.bicep - parameters: ./iac/createResources.parameters.json environment=${{ secrets.ENVIRONMENT }} sqlPassword=${{ secrets.SQL_PASSWORD }} - failOnStdErr: false # @TODO: Remove this later. Temporarily added to suppress warnings-as-errors during execution. - # Add the logged-in service principal to the key vault access policy - - name: add service principal to kv access policy - uses: azure/CLI@v1 - with: - inlineScript: az keyvault set-policy -n ${{ env.KV_NAME }}${{ secrets.ENVIRONMENT }} --secret-permissions get list set --object-id $(az ad sp show --id $(az account show --query "user.name" -o tsv) --query "id" -o tsv) - # The AKS agent pool needs to be assigned the user-assigned managed identity created (which has kv access) - - name: assign user-assigned managed-identity to aks agentpool - uses: azure/CLI@v1 - with: - inlineScript: | - az vmss identity assign \ - --identities $(az identity show -g ${{ env.RESOURCE_GROUP_NAME }} --name ${{ env.USER_ASSIGNED_MANAGED_IDENTITY_NAME }}${{ secrets.ENVIRONMENT }} --query "id" -o tsv) \ - --ids $(az vmss list -g ${{ env.AKS_NODES_RESOURCE_GROUP_NAME }} --query "[0].id" -o tsv) \ - # Seed the DBs and storage accounts - - name: seed products db - uses: azure/sql-action@v2 - with: - connection-string: Server=tcp:${{ env.PRODUCTS_DB_SERVER_NAME }}${{ secrets.ENVIRONMENT }}.database.windows.net,1433;Initial Catalog=${{ env.PRODUCTS_DB_NAME }};Persist Security Info=False;User ID=${{ env.PRODUCTS_DB_USER_NAME }};Password=${{ secrets.SQL_PASSWORD }};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30; - path: ./src/ContosoTraders.Api.Products/Migration/productsdb.sql - - name: seed product image (product details) - uses: azure/CLI@v1 - with: - inlineScript: az storage blob sync --account-name '${{ env.PRODUCT_IMAGES_STORAGE_ACCOUNT_NAME }}${{ secrets.ENVIRONMENT }}' -c '${{ env.PRODUCT_DETAILS_CONTAINER_NAME }}' -s 'src/ContosoTraders.Api.Images/product-details' - - name: seed product image (product list) - uses: azure/CLI@v1 - with: - inlineScript: az storage blob sync --account-name '${{ env.PRODUCT_IMAGES_STORAGE_ACCOUNT_NAME }}${{ secrets.ENVIRONMENT }}' -c '${{ env.PRODUCT_LIST_CONTAINER_NAME }}' -s 'src/ContosoTraders.Api.Images/product-list' - - name: purge CDN endpoint - uses: azure/CLI@v1 - with: - inlineScript: az cdn endpoint purge --no-wait --content-paths '/*' -n '${{ env.PRODUCTS_CDN_ENDPOINT_NAME }}${{ secrets.ENVIRONMENT }}' -g '${{ env.RESOURCE_GROUP_NAME }}' --profile-name '${{ env.CDN_PROFILE_NAME }}${{ secrets.ENVIRONMENT }}' - - deploy-carts-api: - runs-on: ubuntu-latest - needs: provision-infrastructure - steps: - - name: checkout code - uses: actions/checkout@v3 - - name: azure login - uses: azure/login@v1 - with: - creds: ${{ secrets.SERVICEPRINCIPAL }} - - name: extract acr password - uses: azure/CLI@v1 - id: extract-acr-password - with: - inlineScript: echo "acrPassword"="$(az acr credential show -n ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }} -g ${{ env.RESOURCE_GROUP_NAME }} --query "passwords[0].value" --output tsv)" >> $GITHUB_OUTPUT - - name: azure container registry login - uses: azure/docker-login@v1 - with: - login-server: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io - username: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }} - password: ${{ steps.extract-acr-password.outputs.acrPassword }} - - name: docker build - run: docker build src -f ./src/ContosoTraders.Api.Carts/Dockerfile -t ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io/${{ env.CARTS_ACR_REPOSITORY_NAME }}:latest -t ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io/${{ env.CARTS_ACR_REPOSITORY_NAME }}:${{ github.sha }} - - name: docker push (to acr) - run: docker push --all-tags ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io/${{ env.CARTS_ACR_REPOSITORY_NAME }} - - name: deploy to aca - uses: azure/CLI@v1 - with: - inlineScript: | - az config set extension.use_dynamic_install=yes_without_prompt - az containerapp update -n ${{ env.CARTS_ACA_NAME }}${{ secrets.ENVIRONMENT }} -g ${{ env.RESOURCE_GROUP_NAME }} --image ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io/${{ env.CARTS_ACR_REPOSITORY_NAME }}:${{ github.sha }} - - deploy-products-api: - runs-on: ubuntu-latest - needs: provision-infrastructure - steps: - - name: checkout code - uses: actions/checkout@v3 - - name: azure login - uses: azure/login@v1 - with: - creds: ${{ secrets.SERVICEPRINCIPAL }} - - name: install helm - uses: Azure/setup-helm@v3 - id: install-helm - - name: extract acr password - uses: azure/CLI@v1 - id: extract-acr-password - with: - inlineScript: echo "acrPassword"="$(az acr credential show -n ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }} -g ${{ env.RESOURCE_GROUP_NAME }} --query "passwords[0].value" --output tsv)" >> $GITHUB_OUTPUT - - name: azure container registry login - uses: azure/docker-login@v1 - with: - login-server: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io - username: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }} - password: ${{ steps.extract-acr-password.outputs.acrPassword }} - - name: docker build - run: docker build src -f ./src/ContosoTraders.Api.Products/Dockerfile -t ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io/${{ env.PRODUCTS_ACR_REPOSITORY_NAME }}:latest -t ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io/${{ env.PRODUCTS_ACR_REPOSITORY_NAME }}:${{ github.sha }} - - name: docker push (to acr) - run: docker push --all-tags ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io/${{ env.PRODUCTS_ACR_REPOSITORY_NAME }} - - name: set aks context - uses: azure/aks-set-context@v3 - with: - resource-group: ${{ env.RESOURCE_GROUP_NAME }} - cluster-name: ${{ env.AKS_CLUSTER_NAME }}${{ secrets.ENVIRONMENT }} - - name: setup kubectl - uses: azure/setup-kubectl@v3 - - name: create kubernetes secret (acr password) - uses: Azure/k8s-create-secret@v3.0 - with: - secret-name: ${{ env.AKS_SECRET_NAME_ACR_PASSWORD }} - container-registry-url: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io - container-registry-username: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }} - container-registry-password: ${{ steps.extract-acr-password.outputs.acrPassword }} - - name: get managedIdentityClientId - uses: azure/CLI@v1 - id: get-managedIdentityClientId - with: - inlineScript: echo "managedIdentityClientId"="$(az identity show -g ${{ env.RESOURCE_GROUP_NAME }} --name ${{ env.USER_ASSIGNED_MANAGED_IDENTITY_NAME }}${{ secrets.ENVIRONMENT }} --query "clientId" -o tsv)" >> $GITHUB_OUTPUT - - name: create kubernetes secret (kv endpoint) - uses: Azure/k8s-create-secret@v3.0 - with: - secret-type: "generic" - secret-name: ${{ env.AKS_SECRET_NAME_KV_ENDPOINT }} - string-data: '{ "${{ env.AKS_SECRET_NAME_KV_ENDPOINT }}" : "https://${{ env.KV_NAME }}${{ secrets.ENVIRONMENT }}.vault.azure.net/" }' - - name: create kubernetes secret (managed identity client id) - uses: Azure/k8s-create-secret@v3.0 - with: - secret-type: "generic" - secret-name: ${{ env.AKS_SECRET_NAME_MI_CLIENTID }} - string-data: '{ "${{ env.AKS_SECRET_NAME_MI_CLIENTID }}" : "${{ steps.get-managedIdentityClientId.outputs.managedIdentityClientId }}" }' - - name: substitute tokens in deployment manifest - uses: cschleiden/replace-tokens@v1.2 - with: - tokenPrefix: "{" - tokenSuffix: "}" - files: ./src/ContosoTraders.Api.Products/Manifests/Deployment.yaml - env: - ENVIRONMENT: ${{ secrets.ENVIRONMENT }} - - name: lint deployment manifest - uses: azure/k8s-lint@v1 - with: - manifests: ./src/ContosoTraders.Api.Products/Manifests/Deployment.yaml - - name: apply deployment manifest - uses: Azure/k8s-deploy@v4 - with: - manifests: ./src/ContosoTraders.Api.Products/Manifests/Deployment.yaml - images: ${{ env.ACR_NAME }}${{ secrets.ENVIRONMENT }}.azurecr.io/${{ env.PRODUCTS_ACR_REPOSITORY_NAME }}:${{ github.sha }} - imagepullsecrets: ${{ env.AKS_SECRET_NAME_ACR_PASSWORD }} - force: true - - name: apply service manifest - uses: Azure/k8s-deploy@v4 - with: - manifests: ./src/ContosoTraders.Api.Products/Manifests/Service.yaml - force: true - # create the ingress controller - - name: create ingress controller - run: | - az aks get-credentials --resource-group ${{ env.RESOURCE_GROUP_NAME }} --name ${{ env.AKS_CLUSTER_NAME }}${{ secrets.ENVIRONMENT }} - ${{ steps.install-helm.outputs.helm-path }} repo add ingress-nginx https://kubernetes.github.io/ingress-nginx - ${{ steps.install-helm.outputs.helm-path }} repo update - ${{ steps.install-helm.outputs.helm-path }} upgrade --install nginx-ingress ingress-nginx/ingress-nginx \ - --set controller.replicaCount=1 \ - --set controller.nodeSelector."beta\.kubernetes\.io/os"=linux \ - --set defaultBackend.nodeSelector."beta\.kubernetes\.io/os"=linux \ - --set controller.admissionWebhooks.patch.nodeSelector."beta\.kubernetes\.io/os"=linux \ - --set controller.service.externalTrafficPolicy=Local - - name: set dns label on public ip - uses: azure/CLI@v1 - with: - inlineScript: az network public-ip update --dns-name ${{ env.AKS_DNS_LABEL }}${{ secrets.ENVIRONMENT }} -g ${{ env.AKS_NODES_RESOURCE_GROUP_NAME }} -n $(az network public-ip list --query "[?starts_with(name,'kubernetes-') ].name" -o tsv -g ${{ env.AKS_NODES_RESOURCE_GROUP_NAME }}) - # hack: extract the full fqdn / dns label of the aks app's public IP address - - name: get aks-fqdn - uses: azure/CLI@v1 - id: get-aks-fqdn - with: - # note: There should be a whitespace between ')' and ']'. More details: https://stackoverflow.com/a/59154958 - inlineScript: echo "aksFqdn"="$(az network public-ip list --query "[?starts_with(name,'kubernetes-') ].dnsSettings.fqdn" -o tsv -g ${{ env.AKS_NODES_RESOURCE_GROUP_NAME }})" >> $GITHUB_OUTPUT - # install cert-manager - - name: apply namespace manifest - uses: Azure/k8s-deploy@v4 - with: - manifests: ./src/ContosoTraders.Api.Products/Manifests/Namespace.yaml - force: true - - name: install cert-manager - run: | - az aks get-credentials --resource-group ${{ env.RESOURCE_GROUP_NAME }} --name ${{ env.AKS_CLUSTER_NAME }}${{ secrets.ENVIRONMENT }} - kubectl apply --validate=false -f https://github.com/cert-manager/cert-manager/releases/download/v1.9.1/cert-manager.yaml - - name: apply clusterIssuer manifest - uses: Azure/k8s-deploy@v4 - with: - manifests: ./src/ContosoTraders.Api.Products/Manifests/ClusterIssuer.yaml - force: true - - name: substitute tokens in certificate manifest - uses: cschleiden/replace-tokens@v1.2 - with: - tokenPrefix: "{" - tokenSuffix: "}" - files: ./src/ContosoTraders.Api.Products/Manifests/Certificate.yaml - env: - AKS_FQDN: ${{ steps.get-aks-fqdn.outputs.aksFqdn }} - - name: apply certificate manifest - uses: Azure/k8s-deploy@v4 - with: - manifests: ./src/ContosoTraders.Api.Products/Manifests/Certificate.yaml - force: true - - name: substitute tokens in ingress manifest - uses: cschleiden/replace-tokens@v1.2 - with: - tokenPrefix: "{" - tokenSuffix: "}" - files: ./src/ContosoTraders.Api.Products/Manifests/Ingress.yaml - env: - AKS_FQDN: ${{ steps.get-aks-fqdn.outputs.aksFqdn }} - - name: apply ingress manifest - uses: Azure/k8s-deploy@v4 - with: - manifests: ./src/ContosoTraders.Api.Products/Manifests/Ingress.yaml - force: true - - name: apply clusterRole manifest - uses: Azure/k8s-deploy@v4 - with: - manifests: ./src/ContosoTraders.Api.Products/Manifests/ClusterRole.yaml - force: true - - name: set productsApiEndpoint in kv - uses: azure/CLI@v1 - with: - inlineScript: az keyvault secret set --vault-name ${{ env.KV_NAME }}${{ secrets.ENVIRONMENT }} --name productsApiEndpoint --value ${{ steps.get-aks-fqdn.outputs.aksFqdn }} --description "endpoint url (fqdn) of the products api" - - deploy-ui: - runs-on: ubuntu-latest - needs: [provision-infrastructure, deploy-carts-api, deploy-products-api] - steps: - - name: checkout code - uses: actions/checkout@v3 - - name: azure login - uses: azure/login@v1 - with: - creds: ${{ secrets.SERVICEPRINCIPAL }} - - name: get carts api endpoint - uses: azure/CLI@v1 - id: get-cartsApiEndpoint - with: - inlineScript: echo "cartsApiEndpoint"="$(az keyvault secret show --vault-name ${{ env.KV_NAME }}${{ secrets.ENVIRONMENT }} --name cartsApiEndpoint --query value -o tsv)" >> $GITHUB_OUTPUT - - name: get products api endpoint - uses: azure/CLI@v1 - id: get-productsApiEndpoint - with: - inlineScript: echo "productsApiEndpoint"="$(az keyvault secret show --vault-name ${{ env.KV_NAME }}${{ secrets.ENVIRONMENT }} --name productsApiEndpoint --query value -o tsv)" >> $GITHUB_OUTPUT - - name: substitute tokens in ui configuration - uses: cschleiden/replace-tokens@v1.2 - with: - tokenPrefix: "{{" - tokenSuffix: "}}" - files: ./src/ContosoTraders.Ui.Website/.env - env: - CARTS_API_ENDPOINT: ${{ steps.get-cartsApiEndpoint.outputs.cartsApiEndpoint }} - PRODUCTS_API_ENDPOINT: ${{ steps.get-productsApiEndpoint.outputs.productsApiEndpoint }} - - name: npm install - run: npm install - working-directory: src/ContosoTraders.Ui.Website - - name: npm run build - run: npm run build - working-directory: src/ContosoTraders.Ui.Website - - name: deploy to storage - uses: azure/CLI@v1 - with: - inlineScript: az storage blob sync --account-name '${{ env.UI_STORAGE_ACCOUNT_NAME }}${{ secrets.ENVIRONMENT }}' -c '$web' -s 'src/ContosoTraders.Ui.Website/build' - - name: purge CDN endpoint - uses: azure/CLI@v1 - with: - inlineScript: az cdn endpoint purge --no-wait --content-paths '/*' -n '${{ env.UI_CDN_ENDPOINT_NAME }}${{ secrets.ENVIRONMENT }}' -g '${{ env.RESOURCE_GROUP_NAME }}' --profile-name '${{ env.CDN_PROFILE_NAME }}${{ secrets.ENVIRONMENT }}' + provision-and-deploy: + strategy: + matrix: + environmentName: [TEST, PROD] + uses: ./.github/workflows/contoso-traders-provisioning-deployment-template.yml + secrets: inherit + with: + environmentName: ${{ matrix.environmentName }} diff --git a/README.md b/README.md index 094184b..47be21f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ## Documentation and Resources -* [Deployment Guide](./docs/App-Deployment-Guide.md) +* [Deployment Guide](./docs/app-deployment-Guide.md) * [Deployment Guide for Inventory Management PowerApp](./docs/Inventory-power-app-deployment-guide.md) * [Contributing](./docs/contributing.md) * [Bicep Templates](./iac/) diff --git a/demo-scripts/devsecops/technical-walkthrough.md b/demo-scripts/devsecops/technical-walkthrough.md index 47d648c..3be6da0 100644 --- a/demo-scripts/devsecops/technical-walkthrough.md +++ b/demo-scripts/devsecops/technical-walkthrough.md @@ -15,7 +15,7 @@ The key takeaways from this demo are: ## Before you Begin -You must have Contoso Traders deployed in your environment and setup with GitHub Actions. Please refer to the deployment instructions [here](https://github.com/microsoft/ContosoTraders/blob/main/docs/App-Deployment-Guide.md) +You must have Contoso Traders deployed in your environment and setup with GitHub Actions. Please refer to the deployment instructions [here](https://github.com/microsoft/ContosoTraders/blob/main/docs/app-deployment-Guide.md) ## Walkthrough – DevSecOps with Contoso Traders diff --git a/docs/App-Deployment-Guide.md b/docs/App-Deployment-Guide.md index 124864c..484c3c1 100644 --- a/docs/App-Deployment-Guide.md +++ b/docs/App-Deployment-Guide.md @@ -1,324 +1,342 @@ -

Contoso Traders - Deployment Guide

+# Contoso Traders - Deployment Guide +This deployment guide is designed to help you deploy the Contoso Traders application in your Azure environment. Contoso Trader is a micro-services-based application, leveraging various Azure services including Azure Kubernetes Service, App Services, Cosmos DB, SQL Database and many more. -This deployment guide is designed to help you deploy Contoso Traders application in your Azure environment. Contoso Trader is a micro-services-based application, leveraging various Azure services including Azure Kubernetes Service, App Services, Cosmos DB, SQL Database and many more. -While it’s possible to deploy overall solution using Azure Portal, CLI, PowerShell, ARM Templates, we will be using a combination of GitHub Actions and bicep templates to automate the provisioning of overall solution. +While it’s possible to deploy the overall solution using Azure Portal, CLI, PowerShell, ARM Templates, we will be using a combination of GitHub Actions and bicep templates to automate the provisioning of overall solution. -This will deploy all components defined in the Contoso Traders [architecture](../docs/architecture/contoso-traders-enhancements.drawio.png) +This will deploy all components defined in the Contoso Traders [architecture](../docs/architecture/contoso-traders-enhancements.drawio.png) -

Pre-Requisites

+## Prerequisites -You will need following before we start with deployment. -1. An Azure Subscription with Owner rights. If you don't have an Azure subscription, create a free account before you begin by clicking [here](https://azure.microsoft.com/free/). -2. A GitHub Account. You can create a free account [here](https://github.com/). +You will need following before we start with deployment: -

Preparing your Azure Subscription

+1. An Azure account with `Owner` role on the Azure subscription. If you don't have an Azure subscription, create a free account before you begin by clicking [here](https://azure.microsoft.com/free/). -

Register Required Resource Providers

+2. A GitHub Account. You can create one for free [here](https://github.com/). + +## Preparing your Azure Subscription + +### Register Required Resource Providers + +You will need to register required resource providers on your Azure subscription to your subscription to use the required Azure services. + +1. Login to the [Azure portal](https://portal.azure.com) and sign-in with an account having Owner privileges. + +2. Navigate to `Subscription` > `Resource Providers`. + +3. Find following resource provider and click register. + + - `Microsoft.OperationsManagement` + - `Microsoft.Cdn` -You will need to register required resource providers on your Azure subscription to your subscription to use the required Azure services. -1. Login to Azure Portal by visiting [Azure portal](https://portal.azure.com) and sign-in with an account having Owner privileges. -2. Navigate to Subscription > Resource Providers -3. Find following resource provider and click register. - 1. Microsoft.Operationsmanagement - 2. Microsoft.Cdn - ![img1](images/Dapp2.png) - - ![img2](images/cdnregister.png) - - - This will take few minutes to complete. -

Create an Azure Service Principal

+4. This will take few minutes to complete. + +### Create an Azure Service Principal + +GitHub Actions will need to authenticate with your Azure account in order to deploy the application. We will be using an Azure AD Service Principal for allowing GitHub Actions to deploy the resources in Azure. + +An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. This access is restricted by the roles assigned to the service principal, giving you control over which resources can be accessed and at which level. + +Let’s create an Azure Service Principal and assign required permissions. + +1. Sign in to your Azure Account through the Azure portal. -GitHub Actions will need to authenticate with your Azure account in order to deploy the application. We will be using an Azure AD Service Principal for allowing GitHub Actions to deploy the resources in Azure. - An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources. This access is restricted by the roles assigned to the service principal, giving you control over which resources can be accessed and at which level -Let’s create an Azure Service Principal and assign required permissions. +2. Select `Azure Active Directory`. -1. Sign in to your Azure Account through the Azure portal. -2. Select Azure Active Directory. -3. Select App registrations. -4. Select New registration. -5. Provide following values and click Register - 1. Name: “ContosoTraders-GitHubActions” - 2. Supported Account Type: Select the first option - Accounts in the organizational directory only(Default Directory-Single Tenant) - 3. Redirect URI: Select Web and enter the url : https://www.contosotraders.com or your domain url you can enter. +3. Select `App registrations`. - ![img3](images/appreg.png) +4. Select `New registration`. + +5. Provide following values and click Register: + + 1. Name: `ContosoTraders-GitHubActions` + + 2. Supported Account Type: Select the first option - `Accounts in the organizational directory only (Default Directory-Single Tenant)`. + + 3. Redirect URI: Select Web and enter the url : `https://www.contosotraders.com` or your domain url you can enter. + ![img3](images/appreg.png) Once the app is registered, please make a note of it’s Application ID, Secret and Tenant ID. -1. Find your newly created application in Azure AD > App Registration -2. Make a note of Application ID & Tenant ID - - ![img4](images/APPIDCTenantID.png) - -3. Navigate to Secrets and create a new secret. - 1. Name: ContosoTrader-Secret-GitHubActions - 2. Validity – 1 Year -4. Make a note of the secret value. Please keep it in a safe location until next step. This value can not be retrieved once you navigate away from this page. +1. Find your newly created application in Azure AD > App Registration + +2. Make a note of Application ID & Tenant ID + ![img4](images/APPIDCTenantID.png) + +3. Navigate to Secrets and create a new secret. + + 1. Name: ContosoTrader-Secret-GitHubActions + + 2. Validity – 1 Year + +4. Make a note of the secret value. Please keep it in a safe location until next step. This value can not be retrieved once you navigate away from this page. + +Now, we will assign Owner rights to this SPN on Azure subscription. + +1. In Azure Portal, Navigate to Subscriptions and Select your subscription -Now, we will assign Owner rights to this SPN on Azure subscription. -1. In Azure Portal, Navigate to Subscriptions and Select your subscription -2. Click on Access Control (IAM) and Click Add Role Assignment +2. Click on Access Control (IAM) and Click Add Role Assignment ![img5](images/Accesscontrol.png) - -3. Select Owner as role and find the newly created SPN - + +3. Select Owner as role and find the newly created SPN + ![img6](images/addrolespn.png) -4. Click Review+Assign -Your subscription is now ready for deployment. +4. Click Review+Assign + +Your subscription is now ready for deployment. + +### Accept Responsible AI Terms + +In Contoso Traders, we are using Azure Cognitive Service to facilitate the search by image functionality. Before you can use Azure AI services, you must accept the terms for Responsible AI usage. + +In order to accept the terms, you will need to manually provision a Cognitive Service Resource using Azure Portal, with which you will be able to accept the terms. -

Accept Responsible AI Terms

+It is recommended to create this temporary in a separate resource group, so that you can delete the resource group once the terms are accepted. -In Contoso Traders, we are using Azure Cognitive Service to facilitate the search by image functionality. Before you can use Azure AI services, you must accept the terms for Responsible AI usage. -In order to accept the terms, you will need to manually provision a Cognitive Service Resource using Azure Portal, with which you will be able to accept the terms. -It is recommended to create this temporary in a separate resource group, so that you can delete the resource group once the terms are accepted. -1. Select the following link to create a Computer Vision resource: +1. Click the following link to create a Computer Vision resource: [Computer vision](https://portal.azure.com/#create/Microsoft.CognitiveServicesComputerVision) - [Computer vision](https://portal.azure.com/#create/Microsoft.CognitiveServicesComputerVision) - 2. On the Create page, provide the following information: - -

Project details Description

- - 1. Subscription :Select one of your available Azure subscriptions. - 2. Resource group :Create new > Cognitive-Temp-RG - 3. Region :The location of your cognitive service instance. - 4. Name :A descriptive name for your cognitive services resource. For example, MyTempCognitiveServicesResource1. - 5. Pricing tier :Free or Standard S0. + + ```text + Project details Description + + 1. Subscription: Select one of your available Azure subscriptions. + 2. Resource group: Create new > Cognitive-Temp-RG + 3. Region: The location of your cognitive service instance. + 4. Name: A descriptive name for your cognitive services resource. For example, MyTempCognitiveServicesResource1. + 5. Pricing tier: Free or Standard S0. 6. Scroll down and check the box for reviewing and acknowledging Responsible AI terms. - + ``` + 3. Click Review & Create + 4. After Validating click Create -Once the provisioning is completed, you can delete the resource group “Cognitive-Temp-RG” as terms are accepted for your subscription now. +Once the provisioning is completed, you can delete the resource group “Cognitive-Temp-RG” as terms are accepted for your subscription now. -

Preparing your GitHub Account

+## Preparing your GitHub Account -In this step, you will form the original ContosoTraders GitHub repository to your GitHub Account and prepare for deployment. +In this step, you will form the original ContosoTraders GitHub repository to your GitHub Account and prepare for deployment. Fork the Contoso Traders Repo -1. Login to GitHub by visiting [github](https://github.com). -2. Open [ContosoTraders repository](https://github.com/microsoft/ContosoTraders) and Click on Fork - - ![img7](images/Repofork.png) +1. Login to GitHub by visiting [github](https://github.com). + +2. Open [ContosoTraders repository](https://github.com/microsoft/ContosoTraders) and Click on Fork -3. You should now a clone of this repository in your GitHub Account, with https://github.com/YOURUSERNAME/ContosoTraders. -4. You will be using this repository for deployment. Since it exists in your GitHub Account, you will be able to make changes to the contents as well, including source code. + ![img7](images/Repofork.png) +3. You should now a clone of this repository in your GitHub Account, with `https://github.com/YOURUSERNAME/ContosoTraders`. -

Create Secrets in GitHub

+4. You will be using this repository for deployment. Since it exists in your GitHub Account, you will be able to make changes to the contents as well, including source code. -GitHub Secrets are encrypted and allow you to store sensitive information, such as access tokens, in your repository. In our scenario, we will be using GitHub Secrets to store the Azure authentication credentials and other secrets. -These secretes will be used by GitHub Action Workflows during deployment and CI/CD process. We will be creating following three secrets +### Create Secrets in GitHub + +GitHub Secrets are encrypted and allow you to store sensitive information, such as access tokens, in your repository. In our scenario, we will be using GitHub Secrets to store the Azure authentication credentials and other secrets. +These secrets will be used by GitHub Action Workflows during deployment and CI/CD process. We will be creating following three secrets + +- ENVIRONMENT_SUFFIX: Per-environment suffix for guaranteeing unique resource names, URLs etc. You can give any value, such as `yournametraders`. +- SERVICEPRINCIPAL: Azure Service Principal credentials for GitHub Action workflow to authenticate with Azure +- SQL_PASSWORD: New Password for SQL DB to be created as part of deployment. - * ENVIRONMENT: Pre-fix for resource naming, URLs etc. You can give any value, such as yournametraders - * SERVICEPRINCIPAL: Azure Service Principal credentials for GitHub Action workflow to authenticate with Azure - * SQL_PASSWORD: New Password for SQL DB to be created as part of deployment. - Let’s get started -1. Login to GitHub and navigate to your fork of Contoso traders repository. https://github.com/YOURUSERNAME/ContosoTraders. +1. Login to GitHub and navigate to your fork of Contoso traders repository: `https://github.com/YOURUSERNAME/ContosoTraders`. 2. Under your repository name, click on the "Settings" tab. - - ![img8](images/settingsgithub.png) - + + ![img8](images/settingsgithub.png) + 3. In the left sidebar, click Secrets and select actions. - - ![img9](images/githubsett.png) + + ![img9](images/githubsett.png) 4. On the right bar, click on "Add a new secret" -5. Create the following secret for Azure SPN. - 1. Secret Name: SERVICEPRINCIPAL - 2. Value: Please replace the values with your App ID created earlier. - - { - - "clientId": "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz", - - "clientSecret": "your-client-secret", - - "tenantId": "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz", - - "subscriptionId": "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz" - - } - - 3. Click Add Secret - - ![img10](images/addserviceprniciopagithub.png) - -9. Create the following secret for ENVIRONMENT. This is a prefix for your environment and all resources are provisioned with this pre-fix to avoid conflict with public resource names in Azure. - - 1. Secret Name: ENVIRONMENT - 2. Value : Add any combination of characters not exceeding 6 and dont take below 3 - - ![img15](images/envwork.png) - - **Note: When you are creating secret for Environment please add combination of alphanumeric characters without any symbols. Maximum characters allowed is 6 and minimum characters allowed is 3. Keep small case letters** - -10. Create the following secret for SQL Password. - 1. Secret Name: SQL_PASSWORD - 2. Value : Add any combination of alphanumeric characters of minimum 12 - - - ![img12](images/sqlsecretgit.png) - -**Note : When you are creating secret for SQL password please add combination of alphanumeric characters. Minimum characters allowed is 12.Keep small case letters.** +5. Create the following secret for Azure SPN. + 1. Secret Name: SERVICEPRINCIPAL + 2. Value: Please replace the values with your App ID created earlier. + + ```json + { + "clientId": "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz", + "clientSecret": "your-client-secret", + "tenantId": "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz", + "subscriptionId": "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz" + } + ``` + + 3. Click Add Secret + + ![img10](images/addserviceprniciopagithub.png) + +6. Create the following secret for ENVIRONMENT. This is a suffix for your environment and all resources are provisioned with this pre-fix to avoid conflict with public resource names in Azure. + + 1. Secret Name: ENVIRONMENT_SUFFIX -Your GitHub repository is now ready for deployment. + 2. Value : Add any combination of characters not exceeding 6 and don't take below 3 + ![img15](images/envwork.png) -

Deploying the Contoso Traders Application

+ > When you are creating secret for Environment please add combination of alphanumeric characters without any symbols. Maximum characters allowed is 6 and minimum characters allowed is 3. Keep small case letters. +7. Create the following secret for SQL Password. -You are now ready to start deployment of application to your Azure account. We will be using GitHub Action workflows for this deployment. -We will be using following workflows as part of deployment. You can review workflow code by navigating to .github/workflows directory in your repository. -• contoso-traders-provisioning-deployment: + 1. Secret Name: SQL_PASSWORD -Let’s get started. + 2. Value : Add any combination of alphanumeric characters of minimum 12 -1. Login to GitHub and navigate to your fork of Contoso traders repository. https://github.com/YOURUSERNAME/ContosoTraders + ![img12](images/sqlsecretgit.png) + +**Note : When you are creating secret for SQL password please add combination of alphanumeric characters. Minimum characters allowed is 12.Keep small case letters.** + +Your GitHub repository is now ready for deployment. + +## Deploying the Contoso Traders Application + +You are now ready to start deployment of application to your Azure account. We will be using GitHub Action workflows for this deployment. +We will be using following workflows as part of deployment. You can review workflow code by navigating to .github/workflows directory in your repository. + +- contoso-traders-provisioning-deployment: + +Let’s get started. + +1. Login to GitHub and navigate to your fork of Contoso traders repository: `https://github.com/YOURUSERNAME/ContosoTraders` 2. Navigate to Actions and Accept enabling the workflows - - ![img13](images/workflowenable.png) - - + + ![img13](images/workflowenable.png) + 3. In the workflow list, select the “contoso-traders-provisioning-deployment” workflow. - -4. Click on Run Workflow and run the workflow with main branch. - - ![img14](images/workflowrun1.png) + +4. Click on Run Workflow and run the workflow with main branch. + + ![img14](images/workflowrun1.png) 5. If you refresh the page, you will see that workflow provisioning has started. You can click on workflow to see the progress live and logs. If you navigate in the workflow execution, you will the following stages. - 1. Provision-infrastructure: This stage provisions the required resource groups and other Azure services as per architecture and prepares them for app. - 2. You can see each stage and what it does in below screenshot - - ![img19](images/workflow5.png) - 3. Deploy the carts & product API: This stage provisions pushing of carts api and products api to azure container registry. - - ![img22](images/workflow7.png) - ![img20](images/workflow3.png) + 1. Provision-infrastructure: This stage provisions the required resource groups and other Azure services as per architecture and prepares them for app. - 5. Deploy the UI: This stage configure the endpoints of the cart api and products api. - - ![img21](images/workflow4.png) - -**Note : Please note that the workflow provisions all resources through bicep templates, scripts etc. We’ve observed that in many cases, Azure subscription resource cache does not get updated fast enough before the next dependent step starts executing. -If you find workflow failure error due to missing Azure resources (Key vault, CDN, container apps etc, please re-run the failed jobs.** + 2. You can see each stage and what it does in below screenshot. + ![img19](images/workflow5.png) -

Validate & test the deployment

+ 3. Deploy the carts & product API: This stage provisions pushing of carts api and products api to azure container registry. + + ![img22](images/workflow7.png) + ![img20](images/workflow3.png) + + 4. Deploy the UI: This stage configure the endpoints of the cart api and products api. + + ![img21](images/workflow4.png) + +> Note : Please note that the workflow provisions all resources through bicep templates, scripts etc. We’ve observed that in many cases, Azure subscription resource cache does not get updated fast enough before the next dependent step starts executing. +> If you find workflow failure error due to missing Azure resources (Key vault, CDN, container apps etc, please re-run the failed jobs. + +## Validate & test the deployment Contoso Traders application is now ready in your subscription. Let us review and validate the deployment to ensure application is functioning as expected. -

Review Provisioned Azure Resources

+### Review Provisioned Azure Resources Please refer to the architecture walkthrough demo script and technical walkthrough to review the provisioned resources. Please check [here](../demo-scripts/cloud-native-app-architecture/technical-walkthrough.md). +## Test Application + +1. Navigate to Azure and look for CDN endpoints by searching for Content Delivery Network in search menu. Type Content delivery network in the search box and select Front Door and CDN Profiles. + + ![img30](images/test1.png) + +2. Select the CDN profile starting with name contoso-traders-cdn$ENVIRONMENTNAME + + ![img31](images/Test2.png) + +3. Review the Endpoints and make a note of the URL for endpoint containing “UI2” website. It should look like `https://contoso-traders-ui2$ENVNAME.azureedge.net` + + ![img32](images/Test3.png) + +4. Launch the application by clicking on the endpoint hostname url. + + ![img33](images/Test4.png) + +5. The web app will launched. + + ![img34](images/test5.png) + +6. Test the website by navigating through various pages, search by image etc. -

Test Application

- -1. Navigate to Azure and look for CDN endpoints by searching for Content Delivery Network in search menu. Type Content delivery network in the search box and select Front Door and CDN Profiles. - - ![img30](images/test1.png) - -3. Select the CDN profile starting with name contoso-traders-cdn$ENVIRONMENTNAME - - ![img31](images/Test2.png) - -5. Review the Endpoints and make a note of the URL for endpoint containing “UI2” website. It should look like https://contoso-traders-ui2$ENVNAME.azureedge.net - - ![img32](images/Test3.png) - -7. Launch the application by clicking on the endpoint hostname url. - - ![img33](images/Test4.png) - -8. The web app will launched. - - ![img34](images/test5.png) - -9. Test the website by navigating through various pages, search by image etc. - If you would like to add a custom domain, like contosotraders.com, you can purchase the domain and add to CDN profile. Please see documentation [here](https://learn.microsoft.com/en-us/azure/cdn/cdn-map-content-to-custom-domain?tabs=azure-dns%2Cazure-portal%2Cazure-portal-cleanup). -

Deploy Inventory Management PowerApps

+## Deploy Inventory Management PowerApps + +If you are interested, you can follow these steps to deploy the inventory management application used by internal users for managing product pricing, stock etc. -If you are interested, you can follow these steps to deploy the inventory management application used by internal users for managing product pricing, stock etc. It will be hosted using Power Apps and will use Power Automate & MS Teams to enable a full inventory management and approval workflow. -Please follow the instructions here: [Deploy Inventory Management Power App](./Inventory-power-app-deployment-guide.md) - +Please follow the instructions here: [Deploy Inventory Management Power App](./Inventory-power-app-deployment-guide.md) -

Try Out Demo Scripts

- +## Try Out Demo Scripts As further learning, you can try running through some of the demo scripts listed below which’d help in understanding the Azure Cloud Native Technologies. + | Scenario | Level | + | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | Cloud Native App Architecture Walkthrough | [Overview](../demo-scripts/cloud-native-app-architecture/overview.md) \| [Technical Walkthrough](../demo-scripts/cloud-native-app-architecture/technical-walkthrough.md) | + | Autoscaling Cloud Native Apps in Azure | [Overview](../demo-scripts/autoscaling-cloud-native-apps-azure/overview.md) \| [Technical Walkthrough](../demo-scripts/autoscaling-cloud-native-apps-azure/technical-walkthrough.md) | + | DevSecOps Journey with GitHub + Azure | [Overview](../demo-scripts/devsecops/overview.md) \| [Technical Walkthrough](../demo-scripts/devsecops/technical-walkthrough.md) | + | Low Code App Development Power Platform | [Overview](../demo-scripts/low-code-development/overview.md) \| [Technical Walkthrough](../demo-scripts/low-code-development/technical-walkthrough.md) | + | Intelligent Apps with Azure AI Services | [Overview](../demo-scripts/intelligent-apps-with-azure-ai-services/overview.md) \| [Technical Walkthrough](../demo-scripts/intelligent-apps-with-azure-ai-services/technical-walkthrough.md) | + +## Common Errors & Troubleshooting + +This includes some of the common problems you may during deployment and approach to resolve them. + +1. AI Terms and services: + If you see an error stating that "Responsible AI terms are not accepted for this subscription", deploy an Azure Cognitive Service resource manually in your subscription temporarily and re-run the jobs. + +2. Lack of permissions + + Check the role of the service prinipal is owner. If its not shown please provide the owner role to the service principal. + +3. Environment name having not allowed characters + + When you are creating secret for Environment please add combination of alphanumeric characters without any symbols. Maximum characters allowed is 6 and minimum characters allowed is 3. Keep small case letters. + +4. Subscription quota: + + If you get an error related to subscription quota, you may need to raise quota requests in your subscription. For the details of subscription quota please click [here](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits). + +5. Can not find resources (Key Vault, CDN, Storage Account, etc. ) + + Please note that the workflow provisions all resources through bicep templates, scripts etc. We’ve observed that in many cases, Azure subscription resource cache does not get updated fast enough before the next dependent step starts executing. + + If you find workflow failure error due to missing Azure resources (Key vault, CDN, container apps etc, please re-run the failed jobs. + +### Known Issues - | Scenario | Level | - | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | Cloud Native App Architecture Walkthrough | [Overview](../demo-scripts/cloud-native-app-architecture/overview.md) \| [Technical Walkthrough](../demo-scripts/cloud-native-app-architecture/technical-walkthrough.md) | - | Autoscaling Cloud Native Apps in Azure | [Overview](../demo-scripts/autoscaling-cloud-native-apps-azure/overview.md) \| [Technical Walkthrough](../demo-scripts/autoscaling-cloud-native-apps-azure/technical-walkthrough.md) | - | DevSecOps Journey with GitHub + Azure | [Overview](../demo-scripts/devsecops/overview.md) \| [Technical Walkthrough](../demo-scripts/devsecops/technical-walkthrough.md) | - | Low Code App Development Power Platform | [Overview](../demo-scripts/low-code-development/overview.md) \| [Technical Walkthrough](../demo-scripts/low-code-development/technical-walkthrough.md) | - | Intelligent Apps with Azure AI Services | [Overview](../demo-scripts/intelligent-apps-with-azure-ai-services/overview.md) \| [Technical Walkthrough](../demo-scripts/intelligent-apps-with-azure-ai-services/technical-walkthrough.md) | - - - -

Common Errors & Troubleshooting

- -This includes some of the common problems you may during deployment and approach to resolve them. - -1. AI Terms and services: - - **If you see an error stating that "Responsible AI terms are not accepted for this subscription", deploy an Azure Cognitive Service resource manually in your subscription temporarily and re-run the jobs.** - -3. Lack of permissions - - **Check the role of the service prinipal is owner. If its not shown please provide the owner role to the service principal.** - -5. Environment name having not allowed characters - - **When you are creating secret for Environment please add combination of alphanumeric characters without any symbols. Maximum characters allowed is 6 and minimum characters allowed is 3. Keep small case letters** - -8. Subscription quota: - - **If you get an error related to subscription quota, you may need to raise quota requests in your subscription. For the details of subscription quota please click [here](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/azure-subscription-service-limits).** - -10. Can not find resources (Key Vault, CDN, Storage Account, etc. ) - - **Please note that the workflow provisions all resources through bicep templates, scripts etc. We’ve observed that in many cases, Azure subscription resource cache does not get updated fast enough before the next dependent step starts executing. - If you find workflow failure error due to missing Azure resources (Key vault, CDN, container apps etc, please re-run the failed jobs.** - -

Known Issues

- When you run the workflow, it shows following warnings. - -**Error: WARNING: /home/runner/work/ContosoTraders/ContosoTraders/iac/createResources.bicep(191,50) : Warning no-hardcoded-env-urls: Environment URLs should not be hardcoded. Use the environment() function to ensure compatibility across clouds. Found this disallowed host: "database.windows.net". ** -**Warning: WARNING: /home/runner/work/ContosoTraders/ContosoTraders/iac/createResources.bicep(191,50) : Warning no-hardcoded-env-urls: Environment URLs should not be hardcoded. Use the environment() function to ensure compatibility across clouds. Found this disallowed host: "database.windows.net". ** +```text +Error: WARNING: /home/runner/work/ContosoTraders/ContosoTraders/iac/createResources.bicep(191,50) : Warning no-hardcoded-env-urls: Environment URLs should not be hardcoded. Use the environment() function to ensure compatibility across clouds. Found this disallowed host: "database.windows.net". +``` +```text +Warning: WARNING: /home/runner/work/ContosoTraders/ContosoTraders/iac/createResources.bicep(191,50) : Warning no-hardcoded-env-urls: Environment URLs should not be hardcoded. Use the environment() function to ensure compatibility across clouds. Found this disallowed host: "database.windows.net". +``` -This does not block the deployment and workflow will run successfully. It does not have any other impact. It is being tracked here https://github.com/microsoft/ContosoTraders/issues/68 +This does not block the deployment and workflow will run successfully. It does not have any other impact. It is being tracked [here](https://github.com/microsoft/ContosoTraders/issues/68). +## Questions & Support +This project is community supported. Please raise issue via GitHub incase of issues/questions. -

Questions & Support

- -This project is community supported. Please raise issue via GitHub incase of issues/questions. +## Cleanup -

Cleanup

+Once you are done deploying, testing, exploring, you can delete the provisioned RGs to prevent incurring additional cost. -Once you are done deploying, testing, exploring, you can delete the provisioned RGs to prevent incurring additional cost. Delete the following resource groups. -1. contoso-traders-rg -2. contoso-traders-aks-nodes-rg + +1. `contoso-traders-rg` +2. `contoso-traders-aks-nodes-rg` diff --git a/docs/Inventory-power-app-deployment-guide.md b/docs/Inventory-power-app-deployment-guide.md index 65e37e9..b9886cb 100644 --- a/docs/Inventory-power-app-deployment-guide.md +++ b/docs/Inventory-power-app-deployment-guide.md @@ -13,7 +13,7 @@ You will be using a pre-created Package to import the Power App & Power Automate

Pre-Requisite

You will need the following before we start the deploymment -1. You need to have ContosoTraders App deployed in your Azure Subscription. If you have not deployed it yet, please refer the [documentation](../docs/App-Deployment-Guide.md). +1. You need to have ContosoTraders App deployed in your Azure Subscription. If you have not deployed it yet, please refer the [documentation](../docs/app-deployment-Guide.md). 2. An account with global administrator rights on the M365 tenant. diff --git a/docs/setup-local-instructions.md b/docs/setup-local-instructions.md index ecd80b6..430beef 100644 --- a/docs/setup-local-instructions.md +++ b/docs/setup-local-instructions.md @@ -1,14 +1,13 @@ -# Instructions to run Contoso Traders locally. +# Instructions to run Contoso Traders locally ## Setting up ContosoTraders Infrastructure 1. You'll need an Azure subscription with the `Microsoft.OperationsManagement` resource provider registered ([steps](https://learn.microsoft.com/en-us/azure/azure-resource-manager/troubleshooting/error-register-resource-provider?tabs=azure-portal)). 2. You'll need a service principal in the `owner` role on the Azure subscription where the infrastructure is to be provisioned. 3. Git clone this repository to your machine. -4. Create the `SERVICEPRINCIPAL`, `ENVIRONMENT`, and `SQL_PASSWORD` github secrets ([instructions here](./App-Deployment-Guide)). +4. Create the `SERVICEPRINCIPAL`, `ENVIRONMENT_SUFFIX`, and `SQL_PASSWORD` github secrets ([instructions here](./app-deployment-Guide)). 5. Next, run the `contoso-traders-provisioning-deployment` github workflow. You can do this by going to the github repo's `Actions` tab, selecting the workflow, and clicking on the `Run workflow` button. This will both provision the infrastructure on Azure as well as deploy the applications (APIs, UI) to the infrastructure. - ## Running ContosoTraders Locally 1. First ensure that the infrastructure setup has been completed as per steps above. diff --git a/iac/createResources.bicep b/iac/createResources.bicep index 2091a13..19da589 100644 --- a/iac/createResources.bicep +++ b/iac/createResources.bicep @@ -29,8 +29,11 @@ param prefixHyphenated string = 'contoso-traders' // variables //////////////////////////////////////////////////////////////////////////////// +// common +var suffix = toLower(environment) + // key vault -var kvName = '${prefix}kv${environment}' +var kvName = '${prefix}kv${suffix}' var kvSecretNameProductsApiEndpoint = 'productsApiEndpoint' var kvSecretNameProductsDbConnStr = 'productsDbConnectionString' var kvSecretNameProfilesDbConnStr = 'profilesDbConnectionString' @@ -43,89 +46,89 @@ var kvSecretNameCognitiveServicesAccountKey = 'cognitiveServicesAccountKey' var kvSecretNameAppInsightsConnStr = 'appInsightsConnectionString' // user-assigned managed identity (for key vault access) -var userAssignedMIForKVAccessName = '${prefixHyphenated}-mi-kv-access${environment}' +var userAssignedMIForKVAccessName = '${prefixHyphenated}-mi-kv-access${suffix}' // cosmos db (stocks db) -var stocksDbAcctName = '${prefixHyphenated}-stocks${environment}' +var stocksDbAcctName = '${prefixHyphenated}-stocks${suffix}' var stocksDbName = 'stocksdb' var stocksDbStocksContainerName = 'stocks' // cosmos db (carts db) -var cartsDbAcctName = '${prefixHyphenated}-carts${environment}' +var cartsDbAcctName = '${prefixHyphenated}-carts${suffix}' var cartsDbName = 'cartsdb' var cartsDbStocksContainerName = 'carts' // app service plan (products api) -var productsApiAppSvcPlanName = '${prefixHyphenated}-products${environment}' -var productsApiAppSvcName = '${prefixHyphenated}-products${environment}' +var productsApiAppSvcPlanName = '${prefixHyphenated}-products${suffix}' +var productsApiAppSvcName = '${prefixHyphenated}-products${suffix}' var productsApiSettingNameKeyVaultEndpoint = 'KeyVaultEndpoint' var productsApiSettingNameManagedIdentityClientId = 'ManagedIdentityClientId' // sql azure (products db) -var productsDbServerName = '${prefixHyphenated}-products${environment}' +var productsDbServerName = '${prefixHyphenated}-products${suffix}' var productsDbName = 'productsdb' var productsDbServerAdminLogin = 'localadmin' var productsDbServerAdminPassword = sqlPassword // sql azure (profiles db) -var profilesDbServerName = '${prefixHyphenated}-profiles${environment}' +var profilesDbServerName = '${prefixHyphenated}-profiles${suffix}' var profilesDbName = 'profilesdb' var profilesDbServerAdminLogin = 'localadmin' var profilesDbServerAdminPassword = sqlPassword // azure container app (carts api) -var cartsApiAcaName = '${prefixHyphenated}-carts${environment}' -var cartsApiAcaEnvName = '${prefix}acaenv${environment}' +var cartsApiAcaName = '${prefixHyphenated}-carts${suffix}' +var cartsApiAcaEnvName = '${prefix}acaenv${suffix}' var cartsApiAcaSecretAcrPassword = 'acr-password' -var cartsApiAcaContainerDetailsName = '${prefixHyphenated}-carts${environment}' +var cartsApiAcaContainerDetailsName = '${prefixHyphenated}-carts${suffix}' var cartsApiSettingNameKeyVaultEndpoint = 'KeyVaultEndpoint' var cartsApiSettingNameManagedIdentityClientId = 'ManagedIdentityClientId' // storage account (product images) -var productImagesStgAccName = '${prefix}img${environment}' +var productImagesStgAccName = '${prefix}img${suffix}' var productImagesProductDetailsContainerName = 'product-details' var productImagesProductListContainerName = 'product-list' // storage account (old website) -var uiStgAccName = '${prefix}ui${environment}' +var uiStgAccName = '${prefix}ui${suffix}' // storage account (new website) -var ui2StgAccName = '${prefix}ui2${environment}' +var ui2StgAccName = '${prefix}ui2${suffix}' // storage account (image classifier) -var imageClassifierStgAccName = '${prefix}ic${environment}' +var imageClassifierStgAccName = '${prefix}ic${suffix}' var imageClassifierWebsiteUploadsContainerName = 'website-uploads' // cognitive service (image recognition) -var cognitiveServiceName = '${prefixHyphenated}-cs${environment}' +var cognitiveServiceName = '${prefixHyphenated}-cs${suffix}' // cdn -var cdnProfileName = '${prefixHyphenated}-cdn${environment}' -var cdnImagesEndpointName = '${prefixHyphenated}-images${environment}' -var cdnUiEndpointName = '${prefixHyphenated}-ui${environment}' -var cdnUi2EndpointName = '${prefixHyphenated}-ui2${environment}' +var cdnProfileName = '${prefixHyphenated}-cdn${suffix}' +var cdnImagesEndpointName = '${prefixHyphenated}-images${suffix}' +var cdnUiEndpointName = '${prefixHyphenated}-ui${suffix}' +var cdnUi2EndpointName = '${prefixHyphenated}-ui2${suffix}' // redis cache -var redisCacheName = '${prefixHyphenated}-cache${environment}' +var redisCacheName = '${prefixHyphenated}-cache${suffix}' // azure container registry -var acrName = '${prefix}acr${environment}' +var acrName = '${prefix}acr${suffix}' // var acrCartsApiRepositoryName = '${prefix}apicarts' // @TODO: unused, probably remove later // load testing service -var loadTestSvcName = '${prefixHyphenated}-loadtest${environment}' +var loadTestSvcName = '${prefixHyphenated}-loadtest${suffix}' // application insights -var logAnalyticsWorkspaceName = '${prefixHyphenated}-loganalytics${environment}' -var appInsightsName = '${prefixHyphenated}-ai${environment}' +var logAnalyticsWorkspaceName = '${prefixHyphenated}-loganalytics${suffix}' +var appInsightsName = '${prefixHyphenated}-ai${suffix}' // portal dashboard -var portalDashboardName = '${prefixHyphenated}-dashboard${environment}' +var portalDashboardName = '${prefixHyphenated}-dashboard${suffix}' // aks cluster -var aksClusterName = '${prefixHyphenated}-aks${environment}' -var aksClusterDnsPrefix = '${prefixHyphenated}-aks${environment}' +var aksClusterName = '${prefixHyphenated}-aks${suffix}' +var aksClusterDnsPrefix = '${prefixHyphenated}-aks${suffix}' var aksClusterNodeResourceGroup = '${prefixHyphenated}-aks-nodes-rg' // tags