From 2f7e6460a88727a84b3d077295bbe418faf38d27 Mon Sep 17 00:00:00 2001 From: Luiz Macedo Date: Tue, 29 Jul 2025 11:54:16 -0500 Subject: [PATCH 1/8] adds az-2010 labs splitted - Splits Dev Box Lab in two - Fix requisites --- ...traffic-manager-test-azure-chaos-studio.md | 1 - ...ement-self-service-infrastructure-bicep.md | 665 ++++++++++++++++++ ...ment-real-time-monitoring-azure-monitor.md | 130 ++++ .../02-implement-microsoft-dev-box.md | 322 +++++++++ .../03-customize-microsoft-dev-box.md | 535 ++++++++++++++ 5 files changed, 1652 insertions(+), 1 deletion(-) create mode 100644 Instructions/advanced/02-implement-self-service-infrastructure-bicep.md create mode 100644 Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md create mode 100644 Instructions/intermediate/02-implement-microsoft-dev-box.md create mode 100644 Instructions/intermediate/03-customize-microsoft-dev-box.md diff --git a/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md b/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md index 6ec1c69..d846c84 100644 --- a/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md +++ b/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md @@ -17,7 +17,6 @@ You will learn how to: - Deploy Azure App Service web apps to two Azure regions - Enhance workload resiliency by using Traffic Manager - Test workload resiliency by using Azure Chaos Studio -- Remove the resources used in the labs > **Note:** In this lab, you will deploy two instances of a .NET web app into two Azure regions (East US and West US) and then create a resilient configuration that implements the load balancing functionality of Azure Traffic Manager between the two web app instances. You will then use Azure Chaos Studio to trigger a failure of one of the apps to test the resiliency of the load balancing implementation. You can adapt the regions used to ones closer to your location if preferred. diff --git a/Instructions/advanced/02-implement-self-service-infrastructure-bicep.md b/Instructions/advanced/02-implement-self-service-infrastructure-bicep.md new file mode 100644 index 0000000..7cdbb95 --- /dev/null +++ b/Instructions/advanced/02-implement-self-service-infrastructure-bicep.md @@ -0,0 +1,665 @@ +--- +lab: + topic: Advanced + title: "Implement Self-Service Infrastructure with Bicep" + description: "Learn how to implement Infrastructure as Code using Bicep for self-service platform engineering scenarios." +--- + +# Implement Self-Service Infrastructure with Bicep + +In this lab, you will learn how to implement Infrastructure as Code (IaC) using Bicep to create self-service infrastructure capabilities for development teams. You will create Bicep templates to deploy Azure resources, enforce governance through policies and tags, and implement automated scaling for platform engineering scenarios. + +You will learn how to: + +- Set up and use Bicep for Infrastructure as Code +- Create Bicep templates to define and deploy Azure resources +- Deploy Azure App Service with SQL Database backend using Bicep +- Enforce governance using tags and Azure policies +- Implement automated scaling with Bicep + +This lab takes approximately **20** minutes to complete. + +## Before you start + +To complete the lab, you need: + +- An Azure subscription to which you have at least the Contributor-level access. If you don't already have one, you can [sign up for one](https://azure.microsoft.com/). +- Access to Azure Cloud Shell or a local environment with Azure CLI installed. +- Basic knowledge of Azure services and Infrastructure as Code concepts. +- Basic familiarity with JSON and declarative syntax. + +> **Note:** This lab uses Azure Cloud Shell, which is accessible from the Azure portal and requires no local installation. However, you can also complete this lab using a local environment with Azure CLI and Visual Studio Code installed. + +## Create and deploy Bicep templates for Azure resources + +In this exercise, you will create a Bicep template to deploy an Azure App Service with a SQL Database backend. This template will include security best practices and governance controls. + +### Set up Bicep environment + +1. Start a web browser and navigate to the Azure portal at `https://portal.azure.com`. +1. When prompted to authenticate, sign in by using your Azure account. +1. In the Azure portal, select the **Cloud Shell** icon in the top menu bar. +1. If prompted to choose between **Bash** and **PowerShell**, select **Bash**. +1. If this is your first time using Cloud Shell, follow the prompts to create a storage account. +1. Once Cloud Shell is ready, verify that Bicep is available by running: + + ```bash + az bicep version + ``` + + > **Note:** Bicep comes pre-installed in Azure Cloud Shell. You should see output indicating the Bicep CLI version. + +1. To ensure you have the latest version, run: + + ```bash + az bicep upgrade + ``` + +### Create a Bicep template + +1. In the Cloud Shell, create a new Bicep file: + + ```bash + code main.bicep + ``` + +1. Copy and paste the following Bicep code into the file: + + ```bicep + param location string = 'eastus' + param appServicePlanName string = 'asp-bicep-${uniqueString(resourceGroup().id)}' + param webAppName string = 'app-bicep-${uniqueString(resourceGroup().id)}' + param storageAccountName string = 'stbicep${uniqueString(resourceGroup().id)}' + param sqlServerName string = 'sql-bicep-${uniqueString(resourceGroup().id)}' + param sqlDatabaseName string = 'bicepdb' + param sqlAdminUser string + @secure() + param sqlAdminPassword string + + targetScope = 'resourceGroup' + + // Storage Account + resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + properties: { + accessTier: 'Hot' + allowBlobPublicAccess: false + minimumTlsVersion: 'TLS1_2' + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // App Service Plan + resource appPlan 'Microsoft.Web/serverfarms@2023-01-01' = { + name: appServicePlanName + location: location + sku: { + name: 'F1' + tier: 'Free' + } + properties: { + reserved: false + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // Web App + resource webApp 'Microsoft.Web/sites@2023-01-01' = { + name: webAppName + location: location + properties: { + serverFarmId: appPlan.id + httpsOnly: true + siteConfig: { + minTlsVersion: '1.2' + ftpsState: 'FtpsOnly' + } + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // SQL Server + resource sqlServer 'Microsoft.Sql/servers@2023-05-01-preview' = { + name: sqlServerName + location: location + properties: { + administratorLogin: sqlAdminUser + administratorLoginPassword: sqlAdminPassword + version: '12.0' + minimalTlsVersion: '1.2' + publicNetworkAccess: 'Enabled' + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // SQL Database + resource sqlDb 'Microsoft.Sql/servers/databases@2023-05-01-preview' = { + name: sqlDatabaseName + location: location + parent: sqlServer + properties: { + collation: 'SQL_Latin1_General_CP1_CI_AS' + maxSizeBytes: 2147483648 + requestedServiceObjectiveName: 'Basic' + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // SQL Server Firewall Rule (Allow Azure Services) + resource sqlFirewallRule 'Microsoft.Sql/servers/firewallRules@2023-05-01-preview' = { + name: 'AllowAzureServices' + parent: sqlServer + properties: { + startIpAddress: '0.0.0.0' + endIpAddress: '0.0.0.0' + } + } + + // Outputs + output webAppUrl string = 'https://${webApp.properties.defaultHostName}' + output storageAccountName string = storage.name + output sqlServerFqdn string = sqlServer.properties.fullyQualifiedDomainName + ``` + + > **Note:** This template uses the `uniqueString()` function to generate unique names for resources, ensuring that deployments don't fail due to naming conflicts. + +1. Save the file by pressing **Ctrl+S** and then close the editor by pressing **Ctrl+Q**. + +### Deploy the Bicep template + +1. Create a resource group for the deployment: + + ```bash + az group create --name rg-bicep-infrastructure --location eastus + ``` + +1. Validate the Bicep template before deployment: + + ```bash + az deployment group validate \ + --resource-group rg-bicep-infrastructure \ + --template-file main.bicep \ + --parameters sqlAdminUser='bicepAdmin' sqlAdminPassword='SecureP@ssw0rd123!' + ``` + + > **Note:** Replace the password with a strong password that meets Azure SQL Database requirements. + +1. Deploy the template to the resource group: + + ```bash + az deployment group create \ + --resource-group rg-bicep-infrastructure \ + --template-file main.bicep \ + --parameters sqlAdminUser='bicepAdmin' sqlAdminPassword='SecureP@ssw0rd123!' + ``` + + > **Note:** The deployment may take 3-5 minutes to complete. + +1. Wait for the deployment to complete. You should see a confirmation message indicating successful deployment. + +1. View the deployment outputs: + + ```bash + az deployment group show \ + --resource-group rg-bicep-infrastructure \ + --name main \ + --query properties.outputs + ``` + +1. Verify the resources were created successfully by listing the resources in the resource group: + + ```bash + az resource list --resource-group rg-bicep-infrastructure --output table + ``` + +You have successfully deployed an Azure App Service with a SQL Database backend using a Bicep template. The template includes security best practices such as HTTPS enforcement, TLS version requirements, and proper tagging for governance. + +## Enforce governance with tags and Azure policies + +In a self-service infrastructure environment, it is essential to enforce governance to ensure compliance, cost control, and proper resource management. Azure tags and policies are two key mechanisms to achieve this. In this exercise, you will implement governance controls for your infrastructure deployments. + +### Verify resource tagging + +1. In the Cloud Shell, verify that the resources were deployed with the appropriate tags: + + ```bash + az resource list --resource-group rg-bicep-infrastructure \ + --query "[].{Name:name, Type:type, Tags:tags}" \ + --output table + ``` + +1. Check the tags on the resource group itself: + + ```bash + az group show --name rg-bicep-infrastructure --query tags + ``` + +1. Add tags to the resource group to identify ownership and environment: + + ```bash + az group update --name rg-bicep-infrastructure \ + --set tags.Environment='Development' tags.Owner='PlatformEngineering' tags.Project='BicepInfrastructure' + ``` + +1. Verify the tags were applied: + + ```bash + az group show --name rg-bicep-infrastructure --query tags + ``` + +### Create and implement Azure policies for governance + +1. Create a policy definition file to enforce required tags: + + ```bash + cat > tagging-policy.json << EOF + { + "if": { + "allOf": [ + { + "field": "type", + "notIn": [ + "Microsoft.Resources/subscriptions/resourceGroups" + ] + }, + { + "anyOf": [ + { + "not": { + "field": "tags[Environment]", + "exists": "true" + } + }, + { + "not": { + "field": "tags[Owner]", + "exists": "true" + } + } + ] + } + ] + }, + "then": { + "effect": "deny" + } + } + EOF + ``` + +1. Get your subscription ID: + + ```bash + SUBSCRIPTION_ID=$(az account show --query id --output tsv) + echo "Subscription ID: $SUBSCRIPTION_ID" + ``` + +1. Create the policy definition: + + ```bash + az policy definition create \ + --name 'require-tags-policy' \ + --display-name 'Require Environment and Owner tags' \ + --description 'Deny creation of resources without Environment and Owner tags' \ + --rules tagging-policy.json \ + --mode All + ``` + +1. Assign the policy to the resource group: + + ```bash + az policy assignment create \ + --name 'require-tags-assignment' \ + --display-name 'Require tags on resources' \ + --policy "/subscriptions/$SUBSCRIPTION_ID/providers/Microsoft.Authorization/policyDefinitions/require-tags-policy" \ + --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/rg-bicep-infrastructure" + ``` + +1. Verify the policy assignment: + + ```bash + az policy assignment list --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/rg-bicep-infrastructure" --output table + ``` + +### Test policy enforcement + +1. Create a simple Bicep template without required tags to test the policy: + + ```bash + cat > test-policy.bicep << EOF + param location string = 'eastus' + param storageAccountName string = 'testpolicy\${uniqueString(resourceGroup().id)}' + + resource testStorage 'Microsoft.Storage/storageAccounts@2023-01-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + // Note: No tags defined - this should be blocked by policy + } + EOF + ``` + +1. Attempt to deploy the template without required tags: + + ```bash + az deployment group create \ + --resource-group rg-bicep-infrastructure \ + --template-file test-policy.bicep + ``` + + > **Note:** This deployment should fail due to the policy enforcement, demonstrating that the governance controls are working correctly. + +1. Now create a compliant version with the required tags: + + ```bash + cat > test-policy-compliant.bicep << EOF + param location string = 'eastus' + param storageAccountName string = 'testcompliant\${uniqueString(resourceGroup().id)}' + + resource testStorage 'Microsoft.Storage/storageAccounts@2023-01-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + tags: { + Environment: 'Testing' + Owner: 'PlatformEngineering' + } + } + EOF + ``` + +1. Deploy the compliant template: + + ```bash + az deployment group create \ + --resource-group rg-bicep-infrastructure \ + --template-file test-policy-compliant.bicep + ``` + + > **Note:** This deployment should succeed because it includes the required tags. + +1. Clean up the test storage account: + + ```bash + az storage account delete \ + --name "testcompliant$(az group show --name rg-bicep-infrastructure --query id --output tsv | sed 's/.*\///' | tr -d '\n' | openssl dgst -sha1 | cut -c1-13)" \ + --resource-group rg-bicep-infrastructure \ + --yes + ``` + +You have successfully implemented and tested governance controls using Azure policies. The policy ensures that all resources deployed to the resource group must include the required Environment and Owner tags, enforcing organizational standards for resource management. + +## Implement automated scaling with Bicep + +In this exercise, you will enhance your Bicep template to include automated scaling capabilities for the Azure App Service. This will allow the platform to automatically adjust resources based on demand, improving performance and cost efficiency. + +### Create an enhanced Bicep template with autoscaling + +1. Create a new Bicep template that includes autoscaling capabilities: + + ```bash + cat > main-autoscale.bicep << 'EOF' + param location string = 'eastus' + param appServicePlanName string = 'asp-autoscale-${uniqueString(resourceGroup().id)}' + param webAppName string = 'app-autoscale-${uniqueString(resourceGroup().id)}' + param sqlServerName string = 'sql-autoscale-${uniqueString(resourceGroup().id)}' + param sqlDatabaseName string = 'autoscaledb' + param sqlAdminUser string + @secure() + param sqlAdminPassword string + + targetScope = 'resourceGroup' + + // App Service Plan (Standard tier required for autoscaling) + resource appPlan 'Microsoft.Web/serverfarms@2023-01-01' = { + name: appServicePlanName + location: location + sku: { + name: 'S1' + tier: 'Standard' + capacity: 1 + } + properties: { + perSiteScaling: false + maximumElasticWorkerCount: 10 + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // Web App + resource webApp 'Microsoft.Web/sites@2023-01-01' = { + name: webAppName + location: location + properties: { + serverFarmId: appPlan.id + httpsOnly: true + siteConfig: { + minTlsVersion: '1.2' + ftpsState: 'FtpsOnly' + alwaysOn: true + } + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // SQL Server + resource sqlServer 'Microsoft.Sql/servers@2023-05-01-preview' = { + name: sqlServerName + location: location + properties: { + administratorLogin: sqlAdminUser + administratorLoginPassword: sqlAdminPassword + version: '12.0' + minimalTlsVersion: '1.2' + publicNetworkAccess: 'Enabled' + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // SQL Database + resource sqlDb 'Microsoft.Sql/servers/databases@2023-05-01-preview' = { + name: sqlDatabaseName + location: location + parent: sqlServer + properties: { + collation: 'SQL_Latin1_General_CP1_CI_AS' + maxSizeBytes: 2147483648 + requestedServiceObjectiveName: 'S1' + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // Autoscale Settings + resource autoscaleSetting 'Microsoft.Insights/autoscalesettings@2022-10-01' = { + name: 'autoscale-${appServicePlanName}' + location: location + properties: { + targetResourceUri: appPlan.id + enabled: true + profiles: [ + { + name: 'defaultProfile' + capacity: { + minimum: '1' + maximum: '5' + default: '1' + } + rules: [ + { + metricTrigger: { + metricName: 'CpuPercentage' + metricResourceUri: appPlan.id + operator: 'GreaterThan' + threshold: 75 + timeAggregation: 'Average' + timeGrain: 'PT1M' + timeWindow: 'PT5M' + statistic: 'Average' + } + scaleAction: { + direction: 'Increase' + type: 'ChangeCount' + value: '1' + cooldown: 'PT5M' + } + } + { + metricTrigger: { + metricName: 'CpuPercentage' + metricResourceUri: appPlan.id + operator: 'LessThan' + threshold: 25 + timeAggregation: 'Average' + timeGrain: 'PT1M' + timeWindow: 'PT10M' + statistic: 'Average' + } + scaleAction: { + direction: 'Decrease' + type: 'ChangeCount' + value: '1' + cooldown: 'PT10M' + } + } + ] + } + ] + } + tags: { + Environment: 'Development' + Owner: 'PlatformEngineering' + } + } + + // Outputs + output webAppUrl string = 'https://${webApp.properties.defaultHostName}' + output sqlServerFqdn string = sqlServer.properties.fullyQualifiedDomainName + output autoscaleSettingName string = autoscaleSetting.name + EOF + ``` + +1. Validate the enhanced Bicep template: + + ```bash + az deployment group validate \ + --resource-group rg-bicep-infrastructure \ + --template-file main-autoscale.bicep \ + --parameters sqlAdminUser='autoscaleAdmin' sqlAdminPassword='SecureP@ssw0rd123!' + ``` + +### Deploy the autoscaling infrastructure + +1. Deploy the enhanced template with autoscaling capabilities: + + ```bash + az deployment group create \ + --resource-group rg-bicep-infrastructure \ + --template-file main-autoscale.bicep \ + --parameters sqlAdminUser='autoscaleAdmin' sqlAdminPassword='SecureP@ssw0rd123!' + ``` + + > **Note:** This deployment will upgrade the existing App Service Plan to Standard tier and add autoscaling rules. + +1. Verify the deployment completed successfully: + + ```bash + az deployment group show \ + --resource-group rg-bicep-infrastructure \ + --name main-autoscale \ + --query properties.provisioningState + ``` + +1. Check the autoscale settings were created: + + ```bash + az monitor autoscale list \ + --resource-group rg-bicep-infrastructure \ + --output table + ``` + +1. View the details of the autoscale configuration: + + ```bash + AUTOSCALE_NAME=$(az monitor autoscale list --resource-group rg-bicep-infrastructure --query "[0].name" --output tsv) + az monitor autoscale show \ + --resource-group rg-bicep-infrastructure \ + --name "$AUTOSCALE_NAME" \ + --query "{Name:name, Enabled:enabled, MinCapacity:profiles[0].capacity.minimum, MaxCapacity:profiles[0].capacity.maximum, Rules:length(profiles[0].rules)}" + ``` + +### Validate autoscaling configuration + +1. Navigate to the Azure portal and verify the autoscaling configuration: + + - Go to your resource group `rg-bicep-infrastructure` + - Select the App Service Plan + - In the left menu, select **Scale out (App Service plan)** + - Verify that autoscaling is enabled with the rules you defined + +1. View the current instance count and scaling history: + + ```bash + APP_SERVICE_PLAN=$(az appservice plan list --resource-group rg-bicep-infrastructure --query "[0].name" --output tsv) + az appservice plan show \ + --resource-group rg-bicep-infrastructure \ + --name "$APP_SERVICE_PLAN" \ + --query "{Name:name, Sku:sku.name, CurrentInstances:numberOfWorkers, MaxWorkers:maximumNumberOfWorkers}" + ``` + + > **Note:** To fully test autoscaling behavior, you would need to generate load on the application to trigger the CPU threshold. This could be done using load testing tools, but for this lab, verifying the configuration is sufficient. + +You have successfully implemented automated scaling for Azure App Service using Bicep. The autoscaling configuration will: + +- Scale out (add instances) when CPU usage exceeds 75% for 5 minutes +- Scale in (remove instances) when CPU usage falls below 25% for 10 minutes +- Maintain between 1 and 5 instances +- Include cooldown periods to prevent rapid scaling actions + +This ensures your applications can handle varying traffic loads efficiently while optimizing costs. + +## Clean up resources + +Now that you finished the exercise, you should delete the cloud resources you created to avoid unnecessary resource usage. + +1. In your browser navigate to the Azure portal [https://portal.azure.com](https://portal.azure.com); signing in with your Azure credentials if prompted. +1. Navigate to the resource group you created and view the contents of the resources used in this exercise. +1. On the toolbar, select **Delete resource group**. +1. Enter the resource group name and confirm that you want to delete it. diff --git a/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md b/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md new file mode 100644 index 0000000..b036430 --- /dev/null +++ b/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md @@ -0,0 +1,130 @@ +--- +lab: + topic: Basic + title: "Implement Real-Time Monitoring with Azure Monitor" + description: "Learn how to implement comprehensive monitoring and observability for applications using Azure Monitor and Application Insights." +--- + +# Implement Real-Time Monitoring with Azure Monitor + +In this lab, you will implement real-time monitoring for a web application using Azure Monitor and Application Insights. This will help you gain insights into application performance, detect anomalies, and ensure the reliability of your services. + +You will learn how to: + +- Create a sample web app. +- Enable and configure Azure Monitor and Application Insights. +- Create custom dashboards to visualize application metrics. +- Set up alerts to notify stakeholders of performance anomalies. +- Analyze performance data for potential improvements. + +This lab takes approximately **20** minutes to complete. + +## Before you start + +To complete the lab, you need: + +- An active Azure subscription. If you don't have one, you can create a free account at [Azure Free Account](https://azure.microsoft.com/free). +- Basic knowledge of monitoring and observability concepts. +- Basic understanding of Azure services. + +## Create a sample web application + +In this exercise, you will create a sample web application in Azure App Service and enable Application Insights for monitoring. + +### Create an Azure Web App + +1. Open the Azure portal. +1. In the Search bar, type App Services and select it. +1. Click + Create and select Web App. +1. In the Basics tab: + - Subscription: Select your Azure subscription. + - Resource Group: Click Create new, enter **`monitoringlab-rg`**, and click OK. + - Name: Enter a unique name, such as **`monitoringlab-webapp`**. + - Publish: Select Code. + - Runtime stack: Choose .NET 8 (LTS). + - Region: Select a region close to you. +1. Click Review + create, then click Create. +1. Wait for deployment to complete, then click "Go to resource". +1. In the Overview tab, click the URL to verify the web app is running. + +### Verify Application Insights + +1. In the Web App resource, scroll to the Monitoring section. +1. Click Application Insights. +1. Application Insights is already enabled for this web app. Click the link to open the Application Insights resource. +1. In the Application Insights resource, click in the Application Dashboard to view the performance data the default dashboard provided. + +## Configure Azure Monitor and dashboards + +### Access Azure Monitor + +1. In the Azure portal, search for Monitor and click on it. +1. Click Metrics in the left panel. +1. In the Scope section, select the web app under the subscription and resource group where you deployed the web app. +1. Click Apply and observe the metrics available for the web app. + +### Add key metrics to the dashboard + +1. In the Scope section, select your Web App (monitoringlab-webapp). +1. Under Metric, choose Response Time. +1. Set the Aggregation to Average and click + Add metric. +1. Repeat the process for additional metrics: + - CPU Time (Count) + - Requests (Average) +1. Click to dashboard and pin to dashboard. +1. Select type Shared and select the subscription and the monitoringlab-webapp Dashboard. +1. Click Pin to dashboard. +1. Click the dashboard icon in the left panel to view the dashboard. +1. Verify the metrics are displayed on the dashboard and are updating in real-time. + +## Create alerts + +### Define alert conditions and actions + +1. In Azure Monitor, click Alerts. +1. Click + Create and select Alert rule. +1. Under Scope, select your Web App (monitoringlab-webapp) and click Apply. +1. Under Condition, click in the Signal name field and select Response Time. +1. Configure the alert rule: + - Threshold type: Dynamic + - Aggregation type: Average + - Value is: Greater or Less than + - Threshold Sensitivity: High + - When to evaluate: Check every 1 minutes and look back at 5 minutes. +1. Under Actions, select Use quick actions. +1. Enter: + - Action group name: WebAppMonitoringAlerts + - Display name: WebAlert + - Email: Enter your email address. +1. Click Save. +1. Click Next: Details. +1. Enter a Name `WebAppResponseTimeAlert` and select a Severity level Verbose. +1. Click Review + create and then Create. + + > **Note:** Your alert rule is now created and will trigger an email notification when the response time exceeds the threshold. You can force the alert to trigger by sending a large number of requests to the web app. For example, you can use Azure Load testing or a tool like Apache JMeter. + +1. Go back to the Azure Monitor > Alerts. +1. Click on Alert rules and you should see the alert rule you created. + +## Analyze performance data + +### Review Collected Metrics + +1. Go to Application Insights in the Azure portal. +1. Click on the Application Dashboard. +1. Click Performance tile to analyze server response times and load. You can also view the number of requests and failed requests. +1. Click on Analyze with Workbooks and select Performance Counter Analysis. +1. Click Workbooks. +1. Select the workbook Performance Analysis under Performance. +1. You can see the performance data for the web app. + +> **Note:** You can customize the workbook to include additional metrics and filters. + +## Clean up resources + +Now that you finished the exercise, you should delete the cloud resources you created to avoid unnecessary resource usage. + +1. In your browser navigate to the Azure portal [https://portal.azure.com](https://portal.azure.com); signing in with your Azure credentials if prompted. +1. Navigate to the resource group you created and view the contents of the resources used in this exercise. +1. On the toolbar, select **Delete resource group**. +1. Enter the resource group name and confirm that you want to delete it. diff --git a/Instructions/intermediate/02-implement-microsoft-dev-box.md b/Instructions/intermediate/02-implement-microsoft-dev-box.md new file mode 100644 index 0000000..bfbad1e --- /dev/null +++ b/Instructions/intermediate/02-implement-microsoft-dev-box.md @@ -0,0 +1,322 @@ +--- +lab: + topic: Intermediate + title: "Implement Microsoft Dev Box for Developer Self-Service" + description: "Learn how to implement basic Microsoft Dev Box environments for developer self-service scenarios." +--- + +# Implement Microsoft Dev Box for Developer Self-Service + +In this lab, you will learn how to implement Microsoft Dev Box environments to provide developer self-service capabilities. You will create a dev center, configure dev box definitions, set up projects and pools, and evaluate the developer experience using Microsoft-hosted networking. + +You will learn how to: + +- Create and configure a Microsoft Dev Box environment +- Set up dev box definitions and projects +- Configure dev box pools with Microsoft-hosted networking +- Manage permissions for different roles +- Evaluate the developer experience + +This lab takes approximately **30** minutes to complete. + +## Before you start + +To complete the lab, you need: + +- An Azure subscription to which you have at least the Contributor-level access. If you don't already have one, you can [sign up for one](https://azure.microsoft.com/). +- A Microsoft Entra tenant with appropriate permissions to create users and groups +- A Microsoft Intune subscription associated with the same Microsoft Entra tenant as the Azure subscription +- A GitHub user account. If you don't have one, you can [create a new account](https://github.com/join). If you need instructions on how to create a GitHub account, refer to the article [Creating an account on GitHub](https://docs.github.com/get-started/quickstart/creating-an-account-on-github). + +## Prepare the lab environment + +> **Note:** In this lab, you will create Microsoft Entra users and groups to simulate different roles in a Microsoft Dev Box deployment. If you already have suitable test users and groups in your tenant, you can skip the user creation steps and adapt the instructions accordingly. + +### Create Microsoft Entra users and groups + +1. Start a web browser and navigate to the Microsoft Entra admin center at `https://entra.microsoft.com`. +1. If prompted, sign in by using a Microsoft Entra account with Global Administrator permissions in your tenant. +1. In the Microsoft Entra admin center, in the left navigation pane, expand **Identity** and select **Groups**. +1. On the **Groups | All groups** page, select **+ New group**. +1. On the **New Group** page, specify the following settings and select **Create**: + + | Setting | Value | + | ----------- | ------------------------------------- | + | Group type | **Security** | + | Group name | **DevCenter_Platform_Engineers** | + | Description | **Platform Engineers for Dev Center** | + +1. Repeat the previous steps to create two additional groups: + + - **DevCenter_Dev_Leads** (Development team leads) + - **DevCenter_Dev_Users** (Developers) + +1. In the Microsoft Entra admin center, in the left navigation pane, expand **Identity** and select **Users**. +1. On the **Users | All users** page, select **+ New user** and then **Create new user**. +1. On the **New user** page, specify the following settings and select **Create**: + + | Setting | Value | + | ---------------------- | ------------------------------------ | + | User principal name | **platformegineer01@yourdomain.com** | + | Display name | **Platform Engineer 01** | + | Auto-generate password | **Enabled** | + | Account enabled | **Enabled** | + + > **Note:** Replace `yourdomain.com` with your actual domain name. Record the auto-generated password for later use. + +1. Repeat the previous steps to create two additional users: + + - **devlead01@yourdomain.com** (Development Lead 01) + - **devuser01@yourdomain.com** (Developer User 01) + +1. Add the users to their respective groups: + - Add **platformegineer01** to **DevCenter_Platform_Engineers** + - Add **devlead01** to **DevCenter_Dev_Leads** + - Add **devuser01** to **DevCenter_Dev_Users** + +### Fork required GitHub repository + +1. Open a new browser tab and navigate to [https://github.com/microsoft/devcenter-catalog](https://github.com/microsoft/devcenter-catalog). +1. Sign in to GitHub with your account if prompted. +1. Select **Fork** to create a fork of the repository in your GitHub account. + +## Implement a Microsoft Dev Box environment + +In this exercise, you will leverage a set of features provided by Microsoft to implement a Microsoft Dev Box environment. This approach focuses on minimizing the effort involved in building a functional developer self-service solution using Microsoft-hosted networking. + +The exercise consists of the following tasks: + +- Create a dev center +- Review the dev center settings +- Create a dev box definition +- Create a project +- Create a dev box pool +- Configure permissions +- Evaluate a dev box + +### Create a dev center + +In this task, you will create an Azure dev center that will be used throughout this lab. A dev center is a platform engineering service that centralizes the creation and management of scalable, pre-configured development and deployment environments, optimizing collaboration and resource utilization for software development teams. + +1. Start a web browser and navigate to the Azure portal at `https://portal.azure.com`. +1. When prompted to authenticate, sign in by using your Microsoft Entra user account. +1. In the Azure portal, in the **Search** text box, search for and select **`Dev centers`**. +1. On the **Dev centers** page, select **+ Create**. +1. On the **Basics** tab of the **Create a dev center** page, specify the following settings and then select **Next: Settings**: + + | Setting | Value | + | ----------------------------------------------------------------------- | ------------------------------------------------------------ | + | Subscription | The name of the Azure subscription you are using in this lab | + | Resource group | The name of a **new** resource group **rg-devcenter-basic** | + | Name | **devcenter-basic** | + | Location | **(US) East US** | + | Attach a quick start catalog - Azure deployment environment definitions | Enabled | + | Attach a quick start catalog - Dev box customization tasks | Disabled | + +1. On the **Settings** tab of the **Create a dev center** page, specify the following settings and then select **Review + Create**: + + | Setting | Value | + | ------------------------------------------ | ------- | + | Enable catalogs per project | Enabled | + | Allow Microsoft hosted network in projects | Enabled | + | Enable Azure Monitor agent installation | Enabled | + + > **Note:** By design, resources from catalogs attached to the dev center are available to all projects within it. The setting **Enable catalogs per project** makes it possible to attach additional catalogs to arbitrarily selected projects as well. + + > **Note:** Dev boxes can be connected either to a virtual network in your own Azure subscription or a Microsoft hosted one, depending on whether they need to communicate with resources in your environment. If there is no such need, by enabling the setting **Allow Microsoft hosted network in projects**, you introduce the option to connect dev boxes to a Microsoft hosted network, effectively minimizing the management and configuration overhead. + + > **Note:** The setting **Enable Azure Monitor agent installation** automatically triggers installation of the Azure Monitor agent on all dev boxes in the dev center. + +1. On the **Review + Create** tab, wait for the validation to complete and then select **Create**. + + > **Note:** Wait for the project to be provisioned. The project creation might take about 1 minute. + +1. On the **Deployment is completed** page, select **Go to resource**. + +### Review the dev center settings + +In this task, you will review the basic configuration settings of the dev center you created in the previous task. + +1. In the web browser displaying the Azure portal, on the **devcenter-basic** page, in the vertical navigation menu on the left side, expand the **Environment configuration** section and select **Catalogs**. +1. On the **devcenter-basic | Catalogs** page, notice that the dev center is configured with the **quickstart-environment-definitions** catalog, which points to the GitHub repository `https://github.com/microsoft/devcenter-catalog.git`. +1. Verify that the **Status** column contains the **Sync successful** entry. If that is not the case, use the following sequence of steps to re-create the catalog: + + 1. Select the checkbox next to the autogenerated catalog entry **quickstart-environment-definitions** and then, in the toolbar, select **Delete**. + 1. On the **devcenter-basic | Catalogs** page, select **+ Add**. + 1. In the **Add catalog** pane, in the **Name** text box, enter **`quickstart-environment-definitions-fix`**, in the **Catalog location** section, select **GitHub**, in the **Authentication type**, select **GitHub app**, leave the checkbox **Automatically sync this catalog** checkbox enabled, and then select **Sign in with GitHub**. + 1. In the **Sign in with GitHub** window, enter the GitHub credentials and select **Sign in**. + + > **Note:** These GitHub credentials provide you with access to a GitHub repo created as a fork of + + 1. When prompted, in the **Authorize Microsoft DevCenter** window, select **Authorize Microsoft DevCenter**. + 1. Back in the **Add catalog** pane, in the **Repo** drop-down list, select **devcenter-catalog**, in the **Branch** drop-down list, accept the **Default branch** entry, in the **Folder path**, enter **`Environment-Definitions`** and then select **Add**. + 1. Back on the **devcenter-basic | Catalogs** page, verify that the sync completes successfully by monitoring the entry in the **Status** column. + +1. On the **devcenter-basic | Catalogs** page, select the **quickstart-environment-definitions-fix** entry. +1. On the **quickstart-environment-definitions-fix** page, review the list of predefined environment definitions. + + > **Note:** Each entry represents a definition of an Azure deployment environment defined in a respective subfolder of the **Environment-Definitions** folder of the GitHub repository `https://github.com/microsoft/devcenter-catalog.git`. + + > **Note:** A deployment environment is a collection of Azure resources defined in a template referred to as an environment definition. Developers can use these definitions to deploy infrastructure that will serve to host their solutions. For more information regarding Azure deployment environments, refer to the Microsoft Learn article [What is Azure Deployment Environments?](https://learn.microsoft.com/azure/deployment-environments/overview-what-is-azure-deployment-environments) + +### Create a dev box definition + +In this task, you will create a dev box definition. Its purpose is to define the operating system, tools, settings, and resources that serve as a blueprint for creating consistent and tailored development environments (referred to as dev boxes). + +1. In the web browser displaying the Azure portal, on the **devcenter-basic** page, in the vertical navigation menu on the left side, expand the **Dev box configuration** section and select **Dev box definitions**. +1. On the **devcenter-basic | Dev box definitions** page, select **+ Create**. +1. On the **Create dev box definition** page, specify the following settings and then select **Create**: + + | Setting | Value | + | ------------------ | ----------------------------------------------------------------------------------------------------------- | + | Name | **devbox-definition-basic** | + | Image | **Visual Studio 2022 Enterprise on Windows 11 Enterprise + Microsoft 365 Apps 24H2 \| Hibernate supported** | + | Image version | **Latest** | + | Compute | **8 vCPU, 32 GB RAM** | + | Storage | **256 GB SSD** | + | Enable hibernation | Enabled | + + > **Note:** Wait for the dev box definition to be created. This should take less than 1 minute. + +### Create a dev center project + +In this task, you will create a dev center project. A dev center project typically corresponds with a development project within your organization. For example, you might create a project for the development of a line of business application, and another project for the development of the company website. All projects in a dev center share the same dev box definitions, network connection, catalogs, and compute galleries. You might consider creating multiple dev center projects if you have multiple development projects that have separate project administrators and access permissions requirements. + +1. In the web browser displaying the Azure portal, on the **devcenter-basic** page, in the vertical navigation menu on the left side, expand the **Manage** section and select **Projects**. +1. On the **devcenter-basic | Projects** page, select **+ Create**. +1. On the **Basics** tab of the **Create a project** page, specify the following settings and then select **Next: Dev box management**: + + | Setting | Value | + | -------------- | ------------------------------------------------------------ | + | Subscription | The name of the Azure subscription you are using in this lab | + | Resource group | **rg-devcenter-basic** | + | Dev center | **devcenter-basic** | + | Name | **devcenter-project-basic** | + | Description | **Basic Dev Center Project** | + +1. On the **Dev box management** tab of the **Create a project** page, specify the following settings and then select **Next: Catalogs**: + + | Setting | Value | + | ----------------------- | ----- | + | Enable dev box limits | Yes | + | Dev boxes per developer | **2** | + +1. On the **Catalogs** tab of the **Create a project** page, specify the following settings and then select **Review + Create**: + + | Setting | Value | + | ---------------------------------- | ------- | + | Deployment environment definitions | Enabled | + | Image definitions | Enabled | + +1. On the **Review + Create** tab of the **Create a project** page, select **Create**: + + > **Note:** Wait for the project to be created. This should take less than 1 minute. + +1. On the **Deployment is completed** page, select **Go to resource**. + +### Create a dev box pool + +In this task, you will create a dev box pool in the dev center project you created in the previous task. Dev box pools are used by dev box users to create dev boxes. A dev box pool links a dev box definition with a network connection. In this lab, you will use Microsoft-hosted connections, which minimize the management and configuration overhead. The network connection determines where a dev box is hosted and its access to other cloud and on-premises resources. In addition, to reduce the cost of running dev boxes, you can configure a dev box pool to shut them down daily at a predefined time. + +1. In the web browser displaying the Azure portal, on the **devcenter-project-basic** page, in the vertical navigation menu on the left side, expand the **Manage** section and select **Dev box pools**. +1. On the **devcenter-project-basic | Dev box pools** page, select **+ Create**. +1. On the **Basics** tab of the **Create a dev box pool** page, specify the following settings and then select **Create**: + + | Setting | Value | + | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | + | Name | **devbox-pool-basic** | + | Definition | **devbox-definition-basic** | + | Network connection | **Deploy to a Microsoft hosted network** | + | Region | **(US) East US** | + | Enable single sign-on | Enabled | + | Dev box Creator Privileges | **Local Administrator** | + | Enable auto-stop on schedule | Enabled | + | Stop time | **07:00 PM** | + | Time zone | Your current time zone | + | Enable hibernate on disconnect | Enabled | + | Grace period in minutes | **60** | + | I confirm that my organization has Azure Hybrid Benefits licenses, which will apply to all dev boxes in this pool | Enabled | + + > **Note:** Wait for the dev box pool to be created. This might take about 2 minutes. + +### Configure permissions + +In this task, you will assign suitable Microsoft dev box-related permissions to the three Microsoft Entra security principals which have been provisioned in your lab environment. These security principals correspond to typical roles in platform engineering scenarios: + +| User | Group | Role | +| ----------------- | ---------------------------- | --------------------- | +| platformegineer01 | DevCenter_Platform_Engineers | Platform engineer | +| devlead01 | DevCenter_Dev_Leads | Development team lead | +| devuser01 | DevCenter_Dev_Users | Developer | + +Microsoft dev box relies on Azure role-based access control (Azure RBAC) to control access to project-level functionality. Platform engineers should have full control to create and manage dev centers, their catalogs, and projects. This effectively requires the owner or contributor role, depending on whether they also need the ability to delegate permissions to others. Development team leads should be assigned the dev center Project Admin role, which grants the ability to perform administrative tasks on Microsoft Dev Box projects. Dev box users need the ability to create and manage their own dev boxes, which are associated with the Dev Box User role. + +> **Note:** You will start by assigning permissions to the Microsoft Entra group intended to contain platform engineer user accounts. + +1. In the web browser displaying the Azure portal, navigate to the **devcenter-basic** page and, in the vertical navigation menu on the left side, select **Access control (IAM)**. +1. On the **devcenter-basic | Access control (IAM)** page, select **+ Add** and, in the drop-down list, select **Add role assignment**. +1. On the **Role** tab of the **Add role assignment** page, select the **Privileged administrator role** tab, in the list of roles, select **Owner** and finally select **Next**. +1. On the **Members** tab of the **Add role assignment** page, ensure that the **User, group, or service principal** option is selected and click **+ Select members**. +1. In the **Select members** pane, search for and select **`DevCenter_Platform_Engineers`** and then click **Select**. +1. Back on the **Members** tab of the **Add role assignment** page, select **Next**. +1. On the **Conditions** tab of the **Add role assignment** page, in the **What user can do** section, select the option **Allow user to assign all roles (highly privileged)** and then select **Next**. +1. On the **Review + assign** tab of the **Add role assignment** page, select **Review + assign**. + + > **Note:** Next you will assign permissions to the Microsoft Entra group intended to contain development team lead user accounts. + +1. Back on the **devcenter-basic | Access control (IAM)** page, in the vertical navigation menu on the left side, expand the **Manage** section, select **Projects**, and, in the list of projects, select **devcenter-project-basic**. +1. On the **devcenter-project-basic** page, in the vertical navigation menu on the left side, select **Access control (IAM)**. +1. On the **devcenter-project-basic | Access control (IAM)** page, select **+ Add** and, in the drop-down list, select **Add role assignment**. +1. On the **Role** tab of the **Add role assignment** page, ensure that the **Job function roles** tab is selected, in the list of roles, select **DevCenter Project Admin** and select **Next**. +1. On the **Members** tab of the **Add role assignment** page, ensure that the **User, group, or service principal** option is selected and click **+ Select members**. +1. In the **Select members** pane, search for and select **`DevCenter_Dev_Leads`** and then click **Select**. +1. Back on the **Members** tab of the **Add role assignment** page, select **Next**. +1. On the **Review + assign** tab of the **Add role assignment** page, select **Review + assign**. + + > **Note:** Finally, you will assign permissions to the Microsoft Entra group intended to contain developer user accounts. + +1. Back on the **devcenter-project-basic | Access control (IAM)** page, select **+ Add** and, in the drop-down list, select **Add role assignment**. +1. On the **Role** tab of the **Add role assignment** page, ensure that the **Job function roles** tab is selected, in the list of roles, select **DevCenter Dev Box Users** and select **Next**. +1. On the **Members** tab of the **Add role assignment** page, ensure that the **User, group, or service principal** option is selected and click **+ Select members**. +1. In the **Select members** pane, search for and select **`DevCenter_Dev_Users`** and then click **Select**. +1. Back on the **Members** tab of the **Add role assignment** page, select **Next**. +1. On the **Review + assign** tab of the **Add role assignment** page, select **Review + assign**. + +### Evaluate a dev box + +In this task, you will evaluate a dev box functionality by using a Microsoft Entra developer user account. + +1. Start a web browser incognito/in-private and navigate to the Microsoft Dev Box developer portal at `https://aka.ms/devbox-portal`. +1. When prompted to sign in, provide the credentials of the **devuser01** user account. +1. On the **Welcome, devuser01** page of the Microsoft Dev Box developer portal, select **+ New dev box**. +1. In the **Add a dev box** pane, in the **Name** text box, enter **`devuser01box01`** +1. Review other information presented in the **Add a dev box** pane, including the project name, dev box pool specifications, hibernation support status, and the scheduled shutdown timing. In addition, note the option to apply customizations and the notification that dev box creation might take up to 65 minutes. + + > **Note:** Dev box names must be unique within a project. + +1. In the **Add a dev box** pane, select **Create**. + + > **Note:** Do not wait for the dev box to be created. You can continue with the cleanup section while the dev box is being provisioned in the background. + +1. Once the dev box is fully provisioned and running, connect to it by selecting the option to **Connect via app**. + + > **Note:** Connectivity to a dev box can be established by using a Remote Desktop Windows app, a Remote Desktop client (mstsc.exe), or directly within a web browser window. + +1. In the pop-up window titled **This site is trying to open Microsoft Remote Connection Center**, select **Open**. This will automatically initiate a Remote Desktop session to the dev box. +1. When prompted for credentials, authenticate by providing the user name and the password of the **devuser01** account. +1. Within the Remote Desktop session to the dev box, verify that its configuration includes an installation of Visual Studio 2022 and Microsoft 365 apps. + + > **Note:** You can shut down the dev box directly from the Microsoft Dev Box developer portal as a dev user by first selecting the ellipsis symbol in the **Your dev box** interface and then selecting **Shut down** from the cascading menu. Alternatively, as a platform engineer or development team leads, you can control dev box lifecycle from the **Dev box pools** section of the corresponding dev center project. + +## Clean up resources + +Now that you finished the exercise, you should delete the cloud resources you created to avoid unnecessary resource usage. + +1. In your browser navigate to the Azure portal [https://portal.azure.com](https://portal.azure.com); signing in with your Azure credentials if prompted. +1. Navigate to the resource group you created and view the contents of the resources used in this exercise. +1. On the toolbar, select **Delete resource group**. +1. Enter the resource group name and confirm that you want to delete it. + +You don't need to clean up your GitHub repo or project, as they will remain available for you to use as a reference and portfolio item. + +If you want to delete the repo, you can do so by following this documentation: [Deleting a repository](https://docs.github.com/repositories/creating-and-managing-repositories/deleting-a-repository). diff --git a/Instructions/intermediate/03-customize-microsoft-dev-box.md b/Instructions/intermediate/03-customize-microsoft-dev-box.md new file mode 100644 index 0000000..5788130 --- /dev/null +++ b/Instructions/intermediate/03-customize-microsoft-dev-box.md @@ -0,0 +1,535 @@ +--- +lab: + topic: Intermediate + title: "Customize Microsoft Dev Box with Custom Images and Networking" + description: "Learn how to customize Microsoft Dev Box environments with custom images, private networking, and advanced configurations." +--- + +# Customize Microsoft Dev Box with Custom Images and Networking + +In this lab, you will learn how to customize Microsoft Dev Box environments using custom images built with Azure Image Builder, private networking configurations, and advanced customization features. You will create Azure compute galleries, build custom images, configure virtual network connections, and implement image definitions for team-specific development environments. + +You will learn how to: + +- Create and configure Azure compute galleries +- Build custom dev box images using Azure Image Builder +- Configure private networking for dev boxes +- Implement image definitions and customization catalogs +- Create customized dev box pools with private networking + +This lab takes approximately **30** minutes to complete. + +## Before you start + +To complete the lab, you need: + +- An Azure subscription to which you have at least the Contributor-level access. If you don't already have one, you can [sign up for one](https://azure.microsoft.com/). +- An Microsoft Dev Box environment set up in your Azure subscription. If you haven't set it up yet, refer to the lab [Implement Microsoft Dev Box for Developer Self-Service](../intermediate/02-implement-microsoft-dev-box.md) or follow the instructions [Configure Microsoft Dev Box using the Get Started template](https://learn.microsoft.com/azure/dev-box/quickstart-get-started-template). +- A Microsoft Entra tenant with 3 pre-created user accounts (and, optionally 3 pre-created Microsoft Entra groups) representing 3 different roles involved in Microsoft Dev Box deployments. For the sake of clarity, the user and group names in the lab instructions will be matching the information in the following table: + + | User | Group | Role | + | ----------------- | ---------------------------- | --------------------- | + | platformegineer01 | DevCenter_Platform_Engineers | Platform engineer | + | devlead01 | DevCenter_Dev_Leads | Development team lead | + | devuser01 | DevCenter_Dev_Users | Developer | + +- A Microsoft Entra tenant with appropriate permissions to create users and groups +- A Microsoft Intune subscription associated with the same Microsoft Entra tenant as the Azure subscription +- A GitHub user account. If you don't have one, you can [create a new account](https://github.com/join). If you need instructions on how to create a GitHub account, refer to the article [Creating an account on GitHub](https://docs.github.com/get-started/quickstart/creating-an-account-on-github). + +### Fork required GitHub repositories + +1. Open a new browser tab and navigate to [https://github.com/MicrosoftLearning/contoso-co-eShop](https://github.com/MicrosoftLearning/contoso-co-eShop). +1. Sign in to GitHub with your account if prompted. +1. Select **Fork** to create a fork of the repository in your GitHub account. + +> **Note:** This repository contains image definition files that will be used for customization. + +## Customize a Microsoft Dev Box environment + +In this exercise, you will customize the functionality of the Microsoft Dev Box environment. This approach focuses on the extent of changes you can apply when implementing a custom developer self-service solution using Azure compute galleries, custom images, and private networking. + +The exercise consists of the following tasks: + +- Create an Azure compute gallery and attach it to the dev center +- Configure authentication and authorization for Azure Image Builder +- Create a custom image by using Azure Image Builder +- Create an Azure dev center network connection +- Adding image definitions to an Azure dev center project +- Create a customized dev box pool +- Evaluate a customized dev box + +### Create an Azure compute gallery and attach it to the dev center + +In this task, you will create an Azure compute gallery and attach it to a dev center. A gallery is a repository residing in an Azure subscription, which helps you build structure and organization around custom images. After you attach a compute gallery to a dev center and populate it with images, you will be able to create dev box definitions based on images stored in the compute gallery. + +1. Start a web browser and navigate to the Azure portal at `https://portal.azure.com`. +1. When prompted to authenticate, sign in by using your Microsoft account. +1. In the Azure portal, in the **Search** text box, search for and select **`Azure compute galleries`**. +1. On the **Azure compute galleries** page, select **+ Create**. +1. On the **Basics** tab of the **Create Azure compute gallery** page, specify the following settings and then select **Next: Sharing method**: + + | Setting | Value | + | -------------- | ------------------------------------------------------------ | + | Subscription | The name of the Azure subscription you are using in this lab | + | Resource group | The name of a **new** resource group **rg-devcenter-custom** | + | Name | **compute_gallery_custom** | + | Region | **(US) East US** | + +1. On the **Sharing method** tab of the **Create Azure compute gallery** page, ensure that the **Role based access control (RBAC)** option is selected and then select **Review + Create**: +1. On the **Review + Create** tab, wait for the validation to complete and then select **Create**. + + > **Note:** Wait for the project to be provisioned. The Azure compute gallery creation should take less than 1 minute. + +1. In the Azure portal, search for and select **`Dev centers`**. +1. On the **Dev centers** page, select **+ Create**. +1. On the **Basics** tab of the **Create a dev center** page, specify the following settings and then select **Next: Settings**: + + | Setting | Value | + | ----------------------------------------------------------------------- | ------------------------------------------------------------ | + | Subscription | The name of the Azure subscription you are using in this lab | + | Resource group | **rg-devcenter-custom** | + | Name | **devcenter-custom** | + | Location | **(US) East US** | + | Attach a quick start catalog - Azure deployment environment definitions | Enabled | + | Attach a quick start catalog - Dev box customization tasks | Enabled | + +1. On the **Settings** tab of the **Create a dev center** page, specify the following settings and then select **Review + Create**: + + | Setting | Value | + | ------------------------------------------ | ------- | + | Enable catalogs per project | Enabled | + | Allow Microsoft hosted network in projects | Enabled | + | Enable Azure Monitor agent installation | Enabled | + +1. On the **Review + Create** tab, wait for the validation to complete and then select **Create**. + + > **Note:** Wait for the dev center to be provisioned. This might take about 1 minute. + +1. On the **Deployment is completed** page, select **Go to resource**. +1. On the **devcenter-custom** page, in the vertical navigation menu on the left side, expand the **Dev box configuration** section and select **Azure compute galleries**. +1. On the **devcenter-custom | Azure compute galleries** page, select **+ Add**. +1. In the **Add Azure compute gallery** pane, in the **Gallery** drop-down list, select **compute_gallery_custom** and then select **Add**. + + > **Note:** If you receive an error message: "_This dev center does not have a system assigned or user assigned identity. Galleries cannot be added until an identity has been assigned._" you will need to assign a system assigned identity to the dev center. + > To do so, in the Azure portal, on the **devcenter-custom** page, in the vertical navigation menu on the left side, select **Identity** under Settings, in the **System assigned** tab, set the **Status** switch to **On**, and then select **Save**. + +### Configure authentication and authorization for Azure Image Builder + +In this task, you will create a user-assigned managed identity that will be used by Azure Image Builder to add images to the Azure compute gallery you created in the previous task. You will also configure the required permissions by creating a custom role based access control (RBAC) role and assigning it to the managed identity. This will allow you to use Azure Image Builder in the next task to build a custom image. + +1. In the Azure portal, select the **Cloud Shell** toolbar icon to open the Cloud Shell pane and, if needed, select **Switch to PowerShell** to start a PowerShell session and, in the **Switch to PowerShell in Cloud Shell** dialog box, select **Confirm**. + + > **Note:** If this is the first time you are opening Cloud Shell, in the **Welcome to Azure Cloud Shell** dialog box, select **PowerShell**, in the **Getting Started** pane, select the option **No Storage Account required** and, in the **Subscription** drop-down list, select the name of the Azure subscription you are using in this lab. + +1. In the PowerShell session of the Cloud Shell pane, run the following commands to ensure that all required resource providers are registered: + + ```powershell + Register-AzResourceProvider -ProviderNamespace Microsoft.VirtualMachineImages + Register-AzResourceProvider -ProviderNamespace Microsoft.Storage + Register-AzResourceProvider -ProviderNamespace Microsoft.Compute + Register-AzResourceProvider -ProviderNamespace Microsoft.KeyVault + Register-AzResourceProvider -ProviderNamespace Microsoft.Network + ``` + +1. Run the following command to install the required PowerShell modules (when prompted, type **A** and press the **Enter** key): + + ```powershell + 'Az.ImageBuilder', 'Az.ManagedServiceIdentity' | ForEach-Object {Install-Module -Name $_ -AllowPrerelease} + ``` + +1. Run the following commands to set up variables that will be referenced throughout the image build process: + + ```powershell + $currentAzContext = Get-AzContext + # the target Azure subscription ID + $subscriptionID=$currentAzContext.Subscription.Id + # the target Azure resource group name + $imageResourceGroup='rg-devcenter-custom' + # the target Azure region + $location='eastus' + # the reference name assigned to the image created by using the Azure Image Builder service + $runOutputName="aibWinImgCustom" + # image template name + $imageTemplateName="templateWinVSCodeCustom" + # the Azure compute gallery name + $computeGallery = 'compute_gallery_custom' + ``` + +1. Run the following commands to create a user-assigned managed identity (VM Image Builder uses the user identity you provide to store images in the target Azure Compute Gallery): + + ```powershell + # Install the Azure PowerShell module to support AzUserAssignedIdentity + Install-Module -Name Az.ManagedServiceIdentity + # Generate a pseudo-random integer to be used for resource names + $timeInt=$(get-date -UFormat "%s") + + # Create an identity + $identityName='identityAIBCustom' + $timeInt + New-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName -Location $location + $identityNameResourceId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).Id + $identityNamePrincipalId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).PrincipalId + ``` + +1. Run the following commands to grant the newly created user-assigned managed identity the permissions required to store images in the **rg-devcenter-custom** resource group: + + ```powershell + # Set variables + $imageRoleDefName = 'Custom Azure Image Builder Image Def Custom' + $timeInt + $aibRoleImageCreationUrl = 'https://raw.githubusercontent.com/azure/azvmimagebuilder/master/solutions/12_Creating_AIB_Security_Roles/aibRoleImageCreation.json' + $aibRoleImageCreationPath = 'aibRoleImageCreation.json' + + # Customize the role definition file + Invoke-WebRequest -Uri $aibRoleImageCreationUrl -OutFile $aibRoleImageCreationPath -UseBasicParsing + ((Get-Content -path $aibRoleImageCreationPath -Raw) -Replace '', $subscriptionID) | Set-Content -Path $aibRoleImageCreationPath + ((Get-Content -path $aibRoleImageCreationPath -Raw) -Replace '', $imageResourceGroup) | Set-Content -Path $aibRoleImageCreationPath + ((Get-Content -path $aibRoleImageCreationPath -Raw) -Replace 'Azure Image Builder Service Image Creation Role', $imageRoleDefName) | Set-Content -Path $aibRoleImageCreationPath + + # Create a role definition + New-AzRoleDefinition -InputFile ./aibRoleImageCreation.json + + # Assign the role to the VM Image Builder user-assigned managed identity within the scope of the **rg-devcenter-custom** resource group + New-AzRoleAssignment -ObjectId $identityNamePrincipalId -RoleDefinitionName $imageRoleDefName -Scope "/subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup" + ``` + +### Create a custom image by using Azure Image Builder + +In this task, you will use Azure Image Builder to create a custom image based on an existing Azure Resource Manager (ARM) template that defines a Windows 11 Enterprise image with automatically installed Chocolatey and Visual Studio Code. Azure VM Image Builder considerably simplifies the process of defining and provisioning VM images. It relies on an image configuration that you specify to configure an automated imaging pipeline. Subsequently, developers will be able to use such images to provision their dev boxes. + +1. In the PowerShell session of the Cloud Shell pane, run the following commands to create an image definition to be added to the Azure compute gallery you created in the first task of this exercise: + + ```powershell + # ensure that the image definition security type property is set to 'TrustedLaunch' + $securityType = @{Name='SecurityType';Value='TrustedLaunch'} + $features = @($securityType) + # Image definition name + $imageDefName = 'imageDefDevBoxVSCodeCustom' + + # Create the image definition + New-AzGalleryImageDefinition -GalleryName $computeGallery -ResourceGroupName $imageResourceGroup -Location $location -Name $imageDefName -OsState generalized -OsType Windows -Publisher 'Contoso' -Offer 'vscodedevbox' -Sku '1-0-0' -Feature $features -HyperVGeneration 'V2' + ``` + + > **Note:** A dev box image must satisfy a number of requirements including the use of Generation 2, Hyper-V v2, and Windows 10 or 11 Enterprise version 20H2 or later. For their full list, refer to the Microsoft Learn article [Configure Azure Compute Gallery for Microsoft Dev Box](https://learn.microsoft.com/azure/dev-box/how-to-configure-azure-compute-gallery). + +1. Run the following commands to create an empty file named template.json that will contain an ARM template defining a Windows 11 Enterprise image with automatically installed Chocolatey and Visual Studio Code: + + ```powershell + Set-Location -Path ~ + $templateFile = 'template.json' + Set-Content -Path $templateFile -Value '' + ``` + +1. In the PowerShell session of Cloud Shell, use the nano text editor to add the following content to the newly created file: + + > **Note:** To open the nano text editor, run the command `nano ./template.json`. To save changes and exit the nano text editor, press **Ctrl+X**, then **Y**, and finally **Enter**. + + ```json + { + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "imageTemplateName": { + "type": "string" + }, + "api-version": { + "type": "string" + }, + "svclocation": { + "type": "string" + } + }, + "variables": {}, + "resources": [ + { + "name": "[parameters('imageTemplateName')]", + "type": "Microsoft.VirtualMachineImages/imageTemplates", + "apiVersion": "[parameters('api-version')]", + "location": "[parameters('svclocation')]", + "dependsOn": [], + "tags": { + "imagebuilderTemplate": "win11multi", + "userIdentity": "enabled" + }, + "identity": { + "type": "UserAssigned", + "userAssignedIdentities": { + "": {} + } + }, + "properties": { + "buildTimeoutInMinutes": 100, + "vmProfile": { + "vmSize": "Standard_DS2_v2", + "osDiskSizeGB": 127 + }, + "source": { + "type": "PlatformImage", + "publisher": "MicrosoftWindowsDesktop", + "offer": "Windows-11", + "sku": "win11-21h2-ent", + "version": "latest" + }, + "customize": [ + { + "type": "PowerShell", + "name": "CreateBuildPath", + "inline": [ + "mkdir c:\\buildArtifacts", + "echo Azure-Image-Builder-Was-Here > c:\\buildArtifacts\\azureImageBuilder.txt" + ] + }, + { + "type": "PowerShell", + "name": "InstallChocolatey", + "inline": [ + "Set-ExecutionPolicy Bypass -Scope Process -Force", + "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072", + "iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))" + ] + }, + { + "type": "PowerShell", + "name": "InstallVSCode", + "inline": ["choco install vscode -y"] + } + ], + "distribute": [ + { + "type": "SharedImage", + "galleryImageId": "/subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/", + "runOutputName": "", + "artifactTags": { + "source": "azureVmImageBuilder", + "baseosimg": "windows11" + }, + "replicationRegions": ["", ""] + } + ] + } + } + ] + } + ``` + +1. Run the following commands to replace placeholders in the template.json with the values specific to your Azure environment: + + ```powershell + $replRegion2 = 'eastus2' + $templateFilePath = '.\template.json' + (Get-Content -Path $templateFilePath -Raw ) -Replace '', $subscriptionID | Set-Content -Path $templateFilePath + (Get-Content -Path $templateFilePath -Raw ) -Replace '', $imageResourceGroup | Set-Content -Path $templateFilePath + (Get-Content -Path $templateFilePath -Raw ) -Replace '', $runOutputName | Set-Content -Path $templateFilePath + (Get-Content -Path $templateFilePath -Raw ) -Replace '', $imageDefName | Set-Content -Path $templateFilePath + (Get-Content -Path $templateFilePath -Raw ) -Replace '', $computeGallery | Set-Content -Path $templateFilePath + (Get-Content -Path $templateFilePath -Raw ) -Replace '', $location | Set-Content -Path $templateFilePath + (Get-Content -Path $templateFilePath -Raw ) -Replace '', $replRegion2 | Set-Content -Path $templateFilePath + ((Get-Content -Path $templateFilePath -Raw) -Replace '', $identityNameResourceId) | Set-Content -Path $templateFilePath + ``` + +1. Run the following command to submit the template to the Azure Image Builder service (the service processes the submitted template by downloading any dependent artifacts, such as scripts, and storing them in a staging resource group, which name includes the **IT\_** prefix, for building a custom virtual machine image): + + ```powershell + New-AzResourceGroupDeployment -ResourceGroupName $imageResourceGroup -TemplateFile $templateFilePath -Api-Version "2020-02-14" -imageTemplateName $imageTemplateName -svclocation $location + ``` + +1. Run the following command to invoke the image build process: + + ```powershell + Invoke-AzResourceAction -ResourceName $imageTemplateName -ResourceGroupName $imageResourceGroup -ResourceType Microsoft.VirtualMachineImages/imageTemplates -ApiVersion "2020-02-14" -Action Run -Force + ``` + +1. Run the following command to determine the image provisioning state: + + ```powershell + Get-AzImageBuilderTemplate -ImageTemplateName $imageTemplateName -ResourceGroupName $imageResourceGroup | Select-Object -Property Name, LastRunStatusRunState, LastRunStatusMessage, ProvisioningState + ``` + + > **Note:** The following output will indicate that the build process has completed successfully: + + ```powershell + Name LastRunStatusRunState LastRunStatusMessage ProvisioningState + ---- --------------------- -------------------- ----------------- + templateWinVSCodeCustom Succeeded Succeeded + ``` + +1. Alternatively, to monitor the build progress, use the following procedure: + + 1. In the Azure portal, search for and select **`Image templates`**. + 1. On the **Image templates** page, select **templateWinVSCodeCustom**. + 1. On the **templateWinVSCodeCustom** page, in the **Essentials** section, note the value of the **Build run state** entry. + + > **Note:** The build process might take about 30 minutes. For the sake of time, you can proceed to the next task while the build is in progress and return to verify the completion later. + +1. Once the build completes, in the Azure portal, search for and select **`Azure compute galleries`**. +1. On the **Azure compute galleries** page, select **compute_gallery_custom**. +1. On the **compute_gallery_custom** page, ensure that the **Definitions** tab is selected and, in the list of definitions, select **imageDefDevBoxVSCodeCustom**. +1. On the **imageDefDevBoxVSCodeCustom** page, select the **Versions** tab and verify that the **1.0.0 (latest version)** entry appears on the list with the **Provisioning State** set to **Succeeded**. +1. Select the **1.0.0 (latest version)** entry. +1. On the **1.0.0 (compute_gallery_custom/imageDefDevBoxVSCodeCustom/1.0.0)** page, review the VM image version settings. + +### Create an Azure dev center network connection + +In this task, you will configure Azure dev center networking to be used in a scenario that requires private connectivity to resources hosted within an Azure virtual network. Unlike Microsoft hosted network that you might have used in previous labs, virtual network connections also support hybrid scenarios (providing connectivity to on-premises resources) and Microsoft Entra hybrid join of Azure dev boxes (in addition to support for Microsoft Entra join). + +1. In the web browser displaying the Azure portal, in the **Search** text box, search for and select **`Virtual networks`**. +1. On the **Virtual networks** page, select **+ Create**. +1. On the **Basics** tab of the **Create virtual network** page, specify the following settings and then select **Next**: + + | Setting | Value | + | -------------- | ------------------------------------------------------------ | + | Subscription | The name of the Azure subscription you are using in this lab | + | Resource group | **rg-devcenter-custom** | + | Name | **vnet-custom** | + | Location | **(US) East US** | + +1. On the **Security** tab of the **Create virtual network** page, review the existing settings without changing their default values and then select **Next**. +1. On the **IP addresses** tab of the **Create virtual network** page, review the existing settings without changing their default values and then select **Review + Create**. +1. On the **Review + Create** tab of the **Create virtual network** page, select **Create**. + + > **Note:** Wait for the virtual network to be created. This should take less than 1 minute. + +1. In the Azure portal, in the **Search** text box, search for and select **`Network connections`**. +1. On the **Network connections** page, select **+ Create**. +1. On the **Basics** tab of the **Create a network connection** page, specify the following settings and then select **Review + Create**: + + | Setting | Value | + | --------------- | ------------------------------------------------------------ | + | Subscription | The name of the Azure subscription you are using in this lab | + | Resource group | **rg-devcenter-custom** | + | Name | **network-connection-vnet-custom** | + | Virtual network | **vnet-custom** | + | Subnet | **default** | + +1. On the **Review + Create** tab of the **Create virtual network** page, select **Create**. + + > **Note:** Wait for the network connection to be created. This might take about 1 minute. + +1. In the Azure portal, search for and select **`Dev centers`** and, on the **Dev centers** page, select **devcenter-custom**. +1. On the **devcenter-custom** page, in the vertical navigation menu on the left side, expand the **Dev box configuration** section and select **Networking**. +1. On the **devcenter-custom | Networking** page, select **+ Add**. +1. In the **Add network connection** pane, in the **Network connection** drop-down list, select **network-connection-vnet-custom** and then select **Add**. + + > **Note:** Do not wait for network connection to be added, but instead proceed to the next task. Adding a network connection might take about 1 minute. + +### Adding image definitions to an Azure dev center project + +In this task, you will add image definitions to an Azure dev center project. Image definitions combine an Azure Marketplace or a custom image with configurable tasks that define additional modifications to be applied to the underlying image. An image definition can be used to build a new image (containing all changes, including those applied by tasks) or to create dev box pools directly. Creating a reusable image minimizes time required for dev box provisioning. + +To configure imaging for Microsoft Dev Box team customizations, project-level catalogs must be enabled (which you configured when creating the dev center). In this task, you will configure catalog sync settings for the project. This will involve attaching a catalog that contains image definition files. + +1. In the web browser displaying the Azure portal, on the **devcenter-custom** page, in the vertical navigation menu on the left side, expand the **Manage** section and select **Projects**. +1. On the **devcenter-custom | Projects** page, select **+ Create**. +1. On the **Basics** tab of the **Create a project** page, specify the following settings and then select **Next: Dev box management**: + + | Setting | Value | + | -------------- | ------------------------------------------------------------ | + | Subscription | The name of the Azure subscription you are using in this lab | + | Resource group | **rg-devcenter-custom** | + | Dev center | **devcenter-custom** | + | Name | **devcenter-project-custom** | + | Description | **Custom Dev Center Project** | + +1. On the **Dev box management** tab of the **Create a project** page, specify the following settings and then select **Next: Catalogs**: + + | Setting | Value | + | ----------------------- | ----- | + | Enable dev box limits | Yes | + | Dev boxes per developer | **2** | + +1. On the **Catalogs** tab of the **Create a project** page, specify the following settings and then select **Review + Create**: + + | Setting | Value | + | ---------------------------------- | ------- | + | Deployment environment definitions | Enabled | + | Image definitions | Enabled | + +1. On the **Review + Create** tab of the **Create a project** page, select **Create**: + + > **Note:** Wait for the project to be created. This should take less than 1 minute. + +1. On the **Deployment is completed** page, select **Go to resource**. +1. On the **devcenter-project-custom** page, in the vertical navigation menu on the left side, expand the **Settings** section and select **Catalogs**. +1. On the **devcenter-project-custom | Catalogs** page, select **+ Add**. +1. In the **Add catalog** pane, in the **Name** text box, enter **`image-definitions-custom`**, in the **Catalog source** section, select **GitHub**, in the **Authentication type**, select **GitHub app**, leave the checkbox **Automatically sync this catalog** checkbox enabled, and then select **Sign in with GitHub**. +1. If prompted, in the **Sign in with GitHub** window, enter your GitHub credentials and select **Sign in**. + + > **Note:** You need to fork the https://github.com/MicrosoftLearning/contoso-co-eShop repository to your GitHub account before you can complete this step. + +1. If prompted, in the **Authorize Microsoft DevCenter** window, select **Authorize Microsoft DevCenter**. +1. Back in the **Add catalog** pane, in the **Repo** drop-down list, select **contoso-co-eShop**, in the **Branch** drop-down list, accept the **Default branch** entry, in the **Folder path**, enter **`.devcenter/catalog/image-definitions`** and then select **Add**. +1. Back on the **devcenter-project-custom | Catalogs** page, verify that the sync completes successfully by monitoring the entry in the **Status** column. +1. Select the **Sync successful** link in the **Status** column, review the resulting notification pane, verify 3 items were added to the catalog, and close the pane by selecting the **x** symbol in the upper right corner. +1. Back on the **devcenter-project-custom | Catalogs** page, select **image-definitions-custom** and verify that it contains three entries named **ContosoBaseImageDefinition**, **backend-eng**, and **frontend-eng**. +1. In the Azure portal, navigate back to the **devcenter-project-custom** page, in the vertical navigation menu on the left side, expand the **Manage** section, select **Image definitions**, and verify that the page displays the same 3 image definitions you identified earlier in this task. + +### Create a customized dev box pool + +In this task, you will use the newly provisioned image definitions to create a dev box pool. The pool will also utilize the network connection you set up earlier in this exercise. + +1. In the Azure portal displaying the **devcenter-project-custom | Image definitions** page, in the vertical navigation menu on the left side, in the **Manage** section, select **Dev box pools**. +1. On the **devcenter-project-custom | Dev box pools** page, select **+ Create**. +1. On the **Basics** tab of the **Create a dev box pool** page, specify the following settings and then select **Create**: + + | Setting | Value | + | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------- | + | Name | **devbox-pool-custom** | + | Definition | **frontend-eng** | + | Network connection | **network-connection-vnet-custom** | + | Enable single sign-on | Enabled | + | Dev box Creator Privileges | **Local Administrator** | + | Enable auto-stop on schedule | Enabled | + | Stop time | **07:00 PM** | + | Time zone | Your current time zone | + | Enable hibernate on disconnect | Enabled | + | Grace period in minutes | **60** | + | I confirm that my organization has Azure Hybrid Benefits licenses, which will apply to all dev boxes in this pool | Enabled | + + > **Note:** Wait for the dev box pool to be created. This might take about 2 minutes. + +### Evaluate a customized dev box + +In this task, you will evaluate the customized dev box functionality by creating a dev box using the custom image and private networking. + +> **Note:** For this task, you will need the developer user account credentials from the previous lab or you can create a new user account following the steps in the prepare lab environment section. + +1. First, you need to assign permissions to allow developers to use the new dev box pool. In the Azure portal, navigate to the **devcenter-project-custom** page. +1. In the vertical navigation menu on the left side, select **Access control (IAM)**. +1. On the **devcenter-project-custom | Access control (IAM)** page, select **+ Add** and, in the drop-down list, select **Add role assignment**. +1. On the **Role** tab of the **Add role assignment** page, ensure that the **Job function roles** tab is selected, in the list of roles, select **DevCenter Dev Box Users** and select **Next**. +1. On the **Members** tab of the **Add role assignment** page, ensure that the **User, group, or service principal** option is selected and click **+ Select members**. +1. In the **Select members** pane, search for and select **`DevCenter_Dev_Users`** and then click **Select**. +1. Back on the **Members** tab of the **Add role assignment** page, select **Next**. +1. On the **Review + assign** tab of the **Add role assignment** page, select **Review + assign**. +1. Start a web browser incognito/in-private and navigate to the Microsoft Dev Box developer portal at `https://aka.ms/devbox-portal`. +1. When prompted to sign in, provide the credentials of the **devuser01** user account. +1. On the **Welcome, devuser01** page of the Microsoft Dev Box developer portal, select **+ New dev box**. +1. In the **Add a dev box** pane, specify the following settings: + + | Setting | Value | + | ------- | ---------------------------- | + | Name | **devuser01custombox01** | + | Project | **devcenter-project-custom** | + | Pool | **devbox-pool-custom** | + +1. Review other information presented in the **Add a dev box** pane, including the pool specifications, hibernation support status, and the scheduled shutdown timing. Note the customization options available. +1. In the **Add a dev box** pane, select **Create**. + + > **Note:** The dev box creation process may take 30-65 minutes. For the sake of time in this lab, you don't need to wait for the complete provisioning, but you should observe that the dev box is being created with the custom image and private network configuration. + +1. Observe the provisioning status and note that the dev box is being created using: + - The custom **frontend-eng** image definition + - Private network connection **network-connection-vnet-custom** + - Custom configurations from the image definition catalog + +## Clean up resources + +Now that you finished the exercise, you should delete the cloud resources you created to avoid unnecessary resource usage. + +1. In your browser navigate to the Azure portal [https://portal.azure.com](https://portal.azure.com); signing in with your Azure credentials if prompted. +1. Navigate to the resource group you created and view the contents of the resources used in this exercise. +1. On the toolbar, select **Delete resource group**. +1. Enter the resource group name and confirm that you want to delete it. + +You don't need to clean up your GitHub repo or project, as they will remain available for you to use as a reference and portfolio item. + +If you want to delete the repo, you can do so by following this documentation: [Deleting a repository](https://docs.github.com/repositories/creating-and-managing-repositories/deleting-a-repository). From eb67fae5ebd5ab31b91eb5307169304cba74c80d Mon Sep 17 00:00:00 2001 From: Luiz Macedo Date: Tue, 29 Jul 2025 12:06:01 -0500 Subject: [PATCH 2/8] fix formatting --- ...nce-workload-traffic-manager-test-azure-chaos-studio.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md b/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md index d846c84..81e8d5f 100644 --- a/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md +++ b/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md @@ -71,10 +71,9 @@ The exercise consists of the following tasks: 1. From the **Bash** session in the **Cloud Shell** pane, run the following commands to clone your forked eShopOnWeb repository: > **Note:** Replace `{YOUR_GITHUB_USERNAME}` in the command below with your actual GitHub username. For example, if your GitHub username is `johnsmith`, the command would be: - > - > ```bash - > git clone https://github.com/johnsmith/eShopOnWeb.git - > ``` + + > `git clone https://github.com/johnsmith/eShopOnWeb.git` + ```bash git clone https://github.com/{YOUR_GITHUB_USERNAME}/eShopOnWeb.git cd eShopOnWeb From 3a3e41766e147fd0883d859877f162528b62392d Mon Sep 17 00:00:00 2001 From: Luiz Macedo Date: Tue, 29 Jul 2025 12:08:05 -0500 Subject: [PATCH 3/8] fix formatting --- ...1-enhance-workload-traffic-manager-test-azure-chaos-studio.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md b/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md index 81e8d5f..20823da 100644 --- a/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md +++ b/Instructions/advanced/01-enhance-workload-traffic-manager-test-azure-chaos-studio.md @@ -71,7 +71,6 @@ The exercise consists of the following tasks: 1. From the **Bash** session in the **Cloud Shell** pane, run the following commands to clone your forked eShopOnWeb repository: > **Note:** Replace `{YOUR_GITHUB_USERNAME}` in the command below with your actual GitHub username. For example, if your GitHub username is `johnsmith`, the command would be: - > `git clone https://github.com/johnsmith/eShopOnWeb.git` ```bash From 7ef58cb4a405a4c49baafb1f77f9bacb963e44be Mon Sep 17 00:00:00 2001 From: Luiz Macedo Date: Tue, 29 Jul 2025 16:24:10 -0500 Subject: [PATCH 4/8] update steps with latest PRs --- ...plement-real-time-monitoring-azure-monitor.md | 16 ++++++++++++---- .../03-customize-microsoft-dev-box.md | 13 ++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md b/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md index b036430..363fd3e 100644 --- a/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md +++ b/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md @@ -54,6 +54,8 @@ In this exercise, you will create a sample web application in Azure App Service 1. Application Insights is already enabled for this web app. Click the link to open the Application Insights resource. 1. In the Application Insights resource, click in the Application Dashboard to view the performance data the default dashboard provided. + > **Note:** The dashboard may take a few moments to fully load and display all performance data. Wait for the dashboard to completely render before proceeding to ensure optimal experience in subsequent exercises. + ## Configure Azure Monitor and dashboards ### Access Azure Monitor @@ -71,10 +73,16 @@ In this exercise, you will create a sample web application in Azure App Service 1. Repeat the process for additional metrics: - CPU Time (Count) - Requests (Average) -1. Click to dashboard and pin to dashboard. -1. Select type Shared and select the subscription and the monitoringlab-webapp Dashboard. -1. Click Pin to dashboard. -1. Click the dashboard icon in the left panel to view the dashboard. +1. In the metrics chart area, click the **Pin to dashboard** button (pin icon) in the top-right corner of the chart. +1. In the **Pin to dashboard** dialog that appears: + - Select **New** to create a new dashboard + - Enter a dashboard name: **`MonitoringLab Dashboard`** + - Select the appropriate subscription + - Choose **Public** for dashboard type + - Click **Create and pin** +1. After the dashboard is created and the metrics are pinned, click **Save** in the top menu to save the dashboard. +1. Navigate to the dashboard by clicking the **Dashboard** icon in the left panel of the Azure portal, or search for "Dashboard" in the top search bar. +1. Select your newly created **MonitoringLab Dashboard** from the dashboard list. 1. Verify the metrics are displayed on the dashboard and are updating in real-time. ## Create alerts diff --git a/Instructions/intermediate/03-customize-microsoft-dev-box.md b/Instructions/intermediate/03-customize-microsoft-dev-box.md index 5788130..4d6550c 100644 --- a/Instructions/intermediate/03-customize-microsoft-dev-box.md +++ b/Instructions/intermediate/03-customize-microsoft-dev-box.md @@ -259,7 +259,7 @@ In this task, you will use Azure Image Builder to create a custom image based on "properties": { "buildTimeoutInMinutes": 100, "vmProfile": { - "vmSize": "Standard_DS2_v2", + "vmSize": "Standard_D2s_v3", "osDiskSizeGB": 127 }, "source": { @@ -452,6 +452,17 @@ To configure imaging for Microsoft Dev Box team customizations, project-level ca 1. On the **devcenter-project-custom | Catalogs** page, select **+ Add**. 1. In the **Add catalog** pane, in the **Name** text box, enter **`image-definitions-custom`**, in the **Catalog source** section, select **GitHub**, in the **Authentication type**, select **GitHub app**, leave the checkbox **Automatically sync this catalog** checkbox enabled, and then select **Sign in with GitHub**. 1. If prompted, in the **Sign in with GitHub** window, enter your GitHub credentials and select **Sign in**. +1. If you see a message stating "We could not find any GitHub repos associated with the account" with a link to **configure your repositories**, complete the following additional steps to set up the Microsoft DevCenter GitHub App: + + 1. Select the **configure your repositories** link. This will open a new browser tab or window directed to GitHub. + 1. On the GitHub **Install Microsoft DevCenter** page, you will be prompted to install the app on your personal account. + 1. In the **Install on your personal account** section, choose one of the following options: + - Select **All repositories** to grant access to all current and future repositories in your account. + - Select **Only select repositories** to choose specific repositories. If you choose this option, use the **Select repositories** dropdown to select the **contoso-co-eShop** repository (or any other repositories you want to make available to Azure DevCenter). + 1. Review the permissions that will be granted under **with these permissions** section, which typically includes "Read access to code and metadata". + 1. Select **Install** to complete the GitHub App installation. + 1. You will be redirected back to the Azure portal. If the redirect doesn't happen automatically, close the GitHub tab and return to the Azure portal. + 1. Back in the Azure portal, on the **Add catalog** page, select **Refresh** or refresh the page to reload the repository list. > **Note:** You need to fork the https://github.com/MicrosoftLearning/contoso-co-eShop repository to your GitHub account before you can complete this step. From cb85c76f3edba7ce24bb970938f6ee267b3f179d Mon Sep 17 00:00:00 2001 From: Luiz Macedo Date: Fri, 1 Aug 2025 15:38:53 -0500 Subject: [PATCH 5/8] update cleanup and remove expert --- .../02-implement-self-service-infrastructure-bicep.md | 2 ++ .../03-implement-real-time-monitoring-azure-monitor.md | 2 ++ ...ent-ci-cd-with-github-actions-and-iac-with-bicep.md | 2 ++ .../intermediate/02-implement-microsoft-dev-box.md | 2 ++ .../intermediate/03-customize-microsoft-dev-box.md | 2 ++ index.md | 10 +++++----- 6 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Instructions/advanced/02-implement-self-service-infrastructure-bicep.md b/Instructions/advanced/02-implement-self-service-infrastructure-bicep.md index 7cdbb95..d15fd9d 100644 --- a/Instructions/advanced/02-implement-self-service-infrastructure-bicep.md +++ b/Instructions/advanced/02-implement-self-service-infrastructure-bicep.md @@ -663,3 +663,5 @@ Now that you finished the exercise, you should delete the cloud resources you cr 1. Navigate to the resource group you created and view the contents of the resources used in this exercise. 1. On the toolbar, select **Delete resource group**. 1. Enter the resource group name and confirm that you want to delete it. + +> **CAUTION:** Deleting a resource group deletes all resources contained within it. If you chose an existing resource group for this exercise, any existing resources outside the scope of this exercise will also be deleted. diff --git a/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md b/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md index 363fd3e..df4795a 100644 --- a/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md +++ b/Instructions/basic/03-implement-real-time-monitoring-azure-monitor.md @@ -136,3 +136,5 @@ Now that you finished the exercise, you should delete the cloud resources you cr 1. Navigate to the resource group you created and view the contents of the resources used in this exercise. 1. On the toolbar, select **Delete resource group**. 1. Enter the resource group name and confirm that you want to delete it. + +> **CAUTION:** Deleting a resource group deletes all resources contained within it. If you chose an existing resource group for this exercise, any existing resources outside the scope of this exercise will also be deleted. diff --git a/Instructions/intermediate/01-implement-ci-cd-with-github-actions-and-iac-with-bicep.md b/Instructions/intermediate/01-implement-ci-cd-with-github-actions-and-iac-with-bicep.md index ca186c2..8c5a4f8 100644 --- a/Instructions/intermediate/01-implement-ci-cd-with-github-actions-and-iac-with-bicep.md +++ b/Instructions/intermediate/01-implement-ci-cd-with-github-actions-and-iac-with-bicep.md @@ -257,6 +257,8 @@ Now that you finished the exercise, you should delete the cloud resources you cr 1. On the toolbar, select **Delete resource group**. 1. Enter the resource group name and confirm that you want to delete it. +> **CAUTION:** Deleting a resource group deletes all resources contained within it. If you chose an existing resource group for this exercise, any existing resources outside the scope of this exercise will also be deleted. + You don't need to clean up your GitHub repo or project, as they will remain available for you to use as a reference and portfolio item. If you want to delete the repo, you can do so by following this documentation: [Deleting a repository](https://docs.github.com/repositories/creating-and-managing-repositories/deleting-a-repository). diff --git a/Instructions/intermediate/02-implement-microsoft-dev-box.md b/Instructions/intermediate/02-implement-microsoft-dev-box.md index bfbad1e..ccebca5 100644 --- a/Instructions/intermediate/02-implement-microsoft-dev-box.md +++ b/Instructions/intermediate/02-implement-microsoft-dev-box.md @@ -317,6 +317,8 @@ Now that you finished the exercise, you should delete the cloud resources you cr 1. On the toolbar, select **Delete resource group**. 1. Enter the resource group name and confirm that you want to delete it. +> **CAUTION:** Deleting a resource group deletes all resources contained within it. If you chose an existing resource group for this exercise, any existing resources outside the scope of this exercise will also be deleted. + You don't need to clean up your GitHub repo or project, as they will remain available for you to use as a reference and portfolio item. If you want to delete the repo, you can do so by following this documentation: [Deleting a repository](https://docs.github.com/repositories/creating-and-managing-repositories/deleting-a-repository). diff --git a/Instructions/intermediate/03-customize-microsoft-dev-box.md b/Instructions/intermediate/03-customize-microsoft-dev-box.md index 4d6550c..0242d7e 100644 --- a/Instructions/intermediate/03-customize-microsoft-dev-box.md +++ b/Instructions/intermediate/03-customize-microsoft-dev-box.md @@ -541,6 +541,8 @@ Now that you finished the exercise, you should delete the cloud resources you cr 1. On the toolbar, select **Delete resource group**. 1. Enter the resource group name and confirm that you want to delete it. +> **CAUTION:** Deleting a resource group deletes all resources contained within it. If you chose an existing resource group for this exercise, any existing resources outside the scope of this exercise will also be deleted. + You don't need to clean up your GitHub repo or project, as they will remain available for you to use as a reference and portfolio item. If you want to delete the repo, you can do so by following this documentation: [Deleting a repository](https://docs.github.com/repositories/creating-and-managing-repositories/deleting-a-repository). diff --git a/index.md b/index.md index f50902b..a1091f6 100644 --- a/index.md +++ b/index.md @@ -17,13 +17,13 @@ Some exercises may have additional, or different, requirements. Those will conta {% assign exercises = site.pages | where_exp:"page", "page.url contains '/Instructions'" %} {% assign grouped_exercises = exercises | group_by: "lab.topic" %} -{% assign topic_order = "Basic,Intermediate,Advanced,Expert" | split: "," %} +{% assign topic_order = "Basic,Intermediate,Advanced" | split: "," %} {% assign sorted_groups = "" | split: "" %} {% for topic in topic_order %} - {% assign matching_group = grouped_exercises | where: "name", topic | first %} - {% if matching_group %} - {% assign sorted_groups = sorted_groups | push: matching_group %} - {% endif %} +{% assign matching_group = grouped_exercises | where: "name", topic | first %} +{% if matching_group %} +{% assign sorted_groups = sorted_groups | push: matching_group %} +{% endif %} {% endfor %}