diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-03/solution-03.md b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-03/solution-03.md index d6f76e6ed..fe7598f41 100644 --- a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-03/solution-03.md +++ b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-03/solution-03.md @@ -59,9 +59,11 @@ Azure Storage currently allows setting **Minimum TLS Version = TLS 1.0, 1.1, or ### Azure Portal steps #### Require secure transfer for a new storage account -1. Open the **Create storage account** pane in the Azure portal. -2. In the **Advanced** page, select the **Enable secure transfer** checkbox. -3. Create storage account blade +1. In the top center search bar in the Azure portal, search for **Storage accounts** +1. Click on **Create** +1. Select your own resource group, provide a unique name for the **Storage account name** and select "**Azure Blob Storage or Azure Data Lake Storage Gen2** for the **Preferred storage type** parameter +1. Click next and in the **Advanced** page, select the **Require secure transfer for REST API operations** checkbox if not already enabled. +1. Leave the rest of the parameters as-is and click **Review + create** ![desc](./images/storage_01.png) @@ -86,12 +88,13 @@ Goal: ensure all storage accounts enforce **Minimum TLS Version = TLS 1.2**. ### Azure Portal steps -1. Open **Azure Policy** in the Portal. +1. In the Azure Portal, navigate to **Policy** 2. Select **Definitions**, search for **"Storage accounts should have the specified minimum TLS version"** (Policy ID `fe83a0eb-a853-422d-aac2-1bffd182c5d0`). 3. Choose **Assign**. -4. Set **Scope** to the subscription or resource group. -5. Under **Parameters**, set **Minimum TLS version** to `TLS 1.2` and (optionally) effect to `Deny`. -6. Complete **Review + Create**, then select **Create**. +4. Set **Scope** to the subscription and your **Labuser-xxx** resource group. +5. Uncheck the box: **Only show parameters that need input or review** +6. Under **Parameters**, set **Minimum TLS version** to `TLS 1.2` and (optionally) effect to `Deny`. +7. Complete **Review + Create**, then select **Create**. ![Azure Policy](./images/policy_01.png) @@ -186,6 +189,8 @@ az role assignment create \ #### Create a Container +Use the Azure Portal to create a new container or use CLI below + ```bash # Create a blob storage container # Create a container named "test-container" @@ -221,6 +226,8 @@ StorageBlobLogs ![Log Analytics](./images/log_analytics_02.png) +Look for TLS 1.0/1.1 usage. + > **Tip:** If you observe TLS 1.0/1.1 usage, upgrade client frameworks (e.g., .NET, Java, Python SDKs), avoid hardcoded protocol versions, and rely on OS defaults that negotiate TLS 1.2+ ([learn.microsoft.com](https://learn.microsoft.com/azure/storage/common/transport-layer-security-configure-minimum-version)). ## Results & acceptance criteria diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-04/images/attestation-provider.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-04/images/attestation-provider.png new file mode 100644 index 000000000..84298a94d Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-04/images/attestation-provider.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-04/solution-04.md b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-04/solution-04.md index 8c261e17b..457a86966 100644 --- a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-04/solution-04.md +++ b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-04/solution-04.md @@ -151,16 +151,11 @@ ATTESTATION_NAME="attest${HASH_SUFFIX}" > [!WARNING] > If your Azure Cloud Shell session times out (e.g. during a break), the variables defined above will be lost and must be re-defined before continuing. We recommend saving them in a local text file on your machine so you can quickly copy and paste them back into a new session. -### Step 2: Create Resource Group and Key Vault +### Step 2: Create Key Vault -Create the resource group and Key Vault with RBAC-based permissions: +Create a Key Vault with RBAC-based permissions: ```bash -# Create Resource Group -az group create \ - --name $RESOURCE_GROUP \ - --location $LOCATION - # Create Key Vault with Azure RBAC permission model az keyvault create \ --name $KEYVAULT_NAME \ @@ -263,12 +258,12 @@ az network vnet subnet create \ Create the Confidential VM with AMD SEV-SNP hardware encryption: ```bash -# Create Confidential VM (North Europe) - No public IP +# Create Confidential VM - No public IP az vm create \ --resource-group $RESOURCE_GROUP \ --name "vm-ubuntu-cvm" \ --location $LOCATION \ - --size "Standard_DC2as_v5" \ + --size "Standard_DC2as_v6" \ --admin-username $ADMIN_USERNAME \ --ssh-key-value "$SSH_PUBLIC_KEY" \ --authentication-type ssh \ @@ -288,6 +283,7 @@ az vm identity assign \ ``` 💡 **Key Configuration Details**: + - `--security-type "ConfidentialVM"` - Enables hardware-based confidential computing - `--os-disk-security-encryption-type "VMGuestStateOnly"` - Encrypts VM guest state with platform-managed keys - `--enable-secure-boot true` - Protects boot integrity @@ -299,24 +295,25 @@ az vm identity assign \ Create Azure Bastion for secure remote access: ```bash -# Create Public IP for Bastion (North Europe) +# Create Public IP for Bastion az network public-ip create \ --resource-group $RESOURCE_GROUP \ - --name "bastion-northeurope-ip" \ + --name "bastion-ip" \ --location $LOCATION \ --sku "Standard" \ --allocation-method "Static" -# Create Azure Bastion (Basic SKU) for North Europe +# Create Azure Bastion (Basic SKU) + +echo "Bastion deployment initiated (this may take 5-10 minutes)" + az network bastion create \ --resource-group $RESOURCE_GROUP \ - --name "bastion-northeurope" \ + --name "bastion" \ --location $LOCATION \ --vnet-name "vm-ubuntu-cvm-vnet" \ - --public-ip-address "bastion-northeurope-ip" \ + --public-ip-address "bastion-ip" \ --sku "Basic" - -echo "Bastion deployment in North Europe initiated (this may take 5-10 minutes)" ``` ⏱️ **Deployment Time**: Azure Bastion typically takes 5-10 minutes to deploy. You can proceed with reviewing the next sections while waiting. @@ -329,10 +326,10 @@ echo "Bastion deployment in North Europe initiated (this may take 5-10 minutes)" ### Step 1: Connect via Azure Bastion -> **📝 Note: These commands run ON the Linux VM itself after connecting via Bastion (not on your local machine)** +> **📝 Note: These commands run ON the Linux VM itself after connecting via Bastion (not on your local machine or in Azure Cloud Shell)** 1. Navigate to the Azure Portal -2. Go to **Virtual Machines** > **vm-ubuntu-cvm** +2. Go to **Virtual Machines** > **vm-ubuntu-cvm** (select the one in your resource group) 3. Click **Connect** > **Connect via Bastion** 4. **Authentication Type**: SSH Private Key from Azure Key Vault 5. **Username**: `azureuser` @@ -391,14 +388,29 @@ sudo dpkg -i azguestattestation1_1.1.2_amd64.deb ### Step 1: Build the Attestation Client +Install prerequisites by running these commands: + +```bash +sudo apt install cmake + +sudo apt-get update -y && sudo apt-get install -y build-essential + +sudo apt-get install -y libcurl4-openssl-dev libjsoncpp-dev libboost-all-dev nlohmann-json3-dev jq +``` + +### Generate build files + ```bash # Navigate to the sample app directory cd confidential-computing-cvm-guest-attestation/cvm-attestation-sample-app/ # Generate build files with CMake cmake . +``` -# Compile the application +### Compile the application + +```bash make ``` @@ -408,7 +420,7 @@ make To use the dedicated Attestation Provider you created in Task 2 Step 4, you need to pass its URI using the `-a` argument. -**Retrieve Your Attestation URI via Azure CLI** +#### Retrieve Your Attestation URI via Azure CLI from your Azure CLI session in Cloud Shell or your local machine ```bash # Retrieve your attestation provider URI @@ -417,7 +429,17 @@ ATTESTATION_URI=$(az attestation show \ --resource-group $RESOURCE_GROUP \ --query "attestUri" \ -o tsv) +echo $ATTESTATION_URI +``` + +Alternatively, you may also retrieve the URL from the Azure portal (navigate to your resource group and click on the Attestation provider resource): + +![Attestation Client - Specified Provider](./images/attestation-provider.png) + +#### Run attestation with your custom provider (inside the Linux VM) +```bash +ATTESTATION_URI= # Run attestation with your custom provider sudo ./AttestationClient -a $ATTESTATION_URI -o token | jq -R 'split(".") | .[0],.[1] | @base64d | fromjson' ``` @@ -453,7 +475,7 @@ The JWT token contains multiple claims that cryptographically prove the VM's sec ### Production Implementation Pattern -In a production scenario, your application would implement attestation checks before processing sensitive data: +In a production scenario, your application would implement attestation checks before processing sensitive data (this is just an example for inspiration, do not run this on the Linux server): ```python # Pseudocode - Production attestation pattern @@ -490,22 +512,6 @@ def process_sensitive_data(customer_data): --- -## Task 6: Clean Up Resources - -💡 **Delete all resources to avoid ongoing charges.** - -### Delete Resource Group - -To delete all resources created in this challenge: - -```bash -az group delete --name $RESOURCE_GROUP --yes --no-wait -``` - -⚠️ **Warning**: This command will permanently delete all resources in the resource group including the VM, Key Vault, Bastion, and all associated resources. - ---- - ## Key Takeaways In this challenge, you successfully implemented and validated Azure Confidential Computing with guest attestation. Here are the key concepts and best practices: diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/images/aks-02.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/images/aks-02.png new file mode 100644 index 000000000..0e4f341c2 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/images/aks-02.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/images/aks-03.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/images/aks-03.png new file mode 100644 index 000000000..4654290ce Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/images/aks-03.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/images/aks.png b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/images/aks.png new file mode 100644 index 000000000..2addc9644 Binary files /dev/null and b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/images/aks.png differ diff --git a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/solution-05.md b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/solution-05.md index ac8d460f0..a5f3efe43 100644 --- a/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/solution-05.md +++ b/03-Azure/01-03-Infrastructure/01_Sovereign_Cloud/walkthrough/challenge-05/solution-05.md @@ -122,20 +122,18 @@ az feature show --namespace Microsoft.ContainerService --name AzureLinuxCVMPrevi az provider register --namespace Microsoft.ContainerService ``` +> [!WARNING] +> For all Microsoft-hosted events, these features and providers below are already registered. Ignore any error messages due to lack of permissions. + --- -## Task 2: Create Resource Group and AKS Cluster +## Task 2: Create Azure Kubernetes Service cluster 💡 **Deploy the foundational AKS cluster with a standard system node pool. You'll add the Confidential VM node pool in the next task.** -### Step 1: Create Resource Group and AKS Cluster +### Step 1: Create AKS cluster ```bash -# Create Resource Group -az group create \ - --name $RESOURCE_GROUP \ - --location $LOCATION - # Create an AKS cluster az aks create --resource-group $RESOURCE_GROUP --name $AKS_CLUSTER_NAME --node-count 1 --location $LOCATION --generate-ssh-keys @@ -143,6 +141,10 @@ az aks create --resource-group $RESOURCE_GROUP --name $AKS_CLUSTER_NAME --node-c az aks get-credentials --resource-group $RESOURCE_GROUP --name $AKS_CLUSTER_NAME ``` +At this point, you should see an AKS cluster in your resource group: + +![AKS](./images//aks.png) + --- ## Task 3: Add Confidential VM Node Pool @@ -155,6 +157,10 @@ az aks get-credentials --resource-group $RESOURCE_GROUP --name $AKS_CLUSTER_NAME az aks nodepool add --resource-group $RESOURCE_GROUP --cluster-name $AKS_CLUSTER_NAME --name cvmnodepool --node-count 1 --node-vm-size Standard_DC2as_v5 ``` +At this point, you should see another AKS node pool in your cluster: + +![AKS](./images//aks-02.png) + --- ## Task 4: Verify Confidential Node Pool Configuration @@ -179,12 +185,12 @@ az aks nodepool list --resource-group $RESOURCE_GROUP --cluster-name $AKS_CLUSTE ### Step 1: Deploy the Attestation Pod -1. The attestation pod YAML file is located at `walkthrough/challenge-5/resources/cvm-attestation-pod.yaml` in this repository. +1. The attestation pod YAML file is located at `walkthrough/challenge-5/resources/cvm-attestation-pod.yaml` in this repository (if using Cloud Shell, upload the file via the **Manage files** menu option). -2. Apply the YAML file using the relative path from the repository root: +2. Apply the YAML file using the file from the repository: ```bash -kubectl apply -f walkthrough/challenge-5/resources/cvm-attestation-pod.yaml +kubectl apply -f cvm-attestation-pod.yaml ``` 2. Check pod status: @@ -193,6 +199,8 @@ kubectl apply -f walkthrough/challenge-5/resources/cvm-attestation-pod.yaml kubectl get pods ``` +![AKS](./images//aks-03.png) + 3. Get the attestation report by checking logs: ```bash