From c2b3bda53c9271c217fb3179e46bd3e486ac7c35 Mon Sep 17 00:00:00 2001 From: Guillaume Da Silva Date: Thu, 26 Feb 2026 16:04:18 +0100 Subject: [PATCH 1/2] docs(azure): document permission requirements and resource-group scoping Add comprehensive Azure permission requirements documentation covering: - Subscription-level vs resource-group-scoped permission models - Step-by-step guide to scope permissions after initial deployment - Azure CLI commands for permission scoping - Required Azure resource provider pre-registration - Entra ID (Azure AD) requirements for application registration - Custom node resource group naming - Troubleshooting guide for common permission issues Also updates: - azure-credentials snippet to mention User Access Administrator role and link to the new permissions page - AKS overview page to link to permission requirements - docs.json navigation to include the new page Co-Authored-By: Claude Opus 4.6 --- .../integrations/kubernetes/aks/overview.mdx | 3 + .../kubernetes/aks/permissions.mdx | 283 ++++++++++++++++++ docs/docs.json | 3 +- docs/snippets/azure-credentials.mdx | 5 +- 4 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 docs/configuration/integrations/kubernetes/aks/permissions.mdx diff --git a/docs/configuration/integrations/kubernetes/aks/overview.mdx b/docs/configuration/integrations/kubernetes/aks/overview.mdx index 60f49df..03d257d 100644 --- a/docs/configuration/integrations/kubernetes/aks/overview.mdx +++ b/docs/configuration/integrations/kubernetes/aks/overview.mdx @@ -28,6 +28,9 @@ Qovery integrates with Azure Kubernetes Service (AKS) for managed Kubernetes on ## Setup Guides + + Azure permission models and resource-group scoping + Connect existing AKS cluster diff --git a/docs/configuration/integrations/kubernetes/aks/permissions.mdx b/docs/configuration/integrations/kubernetes/aks/permissions.mdx new file mode 100644 index 0000000..1b7bf73 --- /dev/null +++ b/docs/configuration/integrations/kubernetes/aks/permissions.mdx @@ -0,0 +1,283 @@ +--- +title: "Azure Permission Requirements" +description: "Understand the Azure permissions Qovery needs and how to scope them to resource groups" +--- + +Qovery requires specific Azure permissions to provision and manage AKS clusters. You can choose between two permission models depending on your security requirements. + +## Permission Models + + + + Simplest approach. The Service Principal has roles at the subscription level. **Required for initial cluster provisioning.** + + + After initial deployment, scope permissions down to specific resource groups for tighter security. + + + +## Option 1: Subscription-Level Permissions (Default) + +This is the default and simplest approach. During initial cluster setup, the Service Principal is assigned the following roles at the **subscription level**: + +| Role | Purpose | +|------|---------| +| **Contributor** | Create and manage all Azure resources (AKS, VMs, VNets, Load Balancers, Storage, etc.) | +| **User Access Administrator** | Assign roles to managed identities created by AKS | + + +Subscription-level permissions are **required for the initial cluster provisioning**. You can scope them down to resource groups after the first successful deployment. + + +## Option 2: Resource-Group-Scoped Permissions + +After the initial cluster deployment completes successfully, you can restrict the Service Principal permissions to only the specific resource groups that Qovery manages. This follows the principle of least privilege. + +### Steps to Scope Permissions + + + + Deploy your cluster with subscription-level permissions (Option 1). Wait for the cluster to reach **Running** status in the Qovery console. + + + + Qovery creates two resource groups during deployment: + + **Main resource group:** + ``` + qovery- + ``` + You can find the cluster short ID in the Qovery console on the cluster settings page. + + **Node resource group (managed by AKS):** + ``` + MC_qovery-__ + ``` + If you configured a [custom node resource group name](#custom-node-resource-group-name), it will use that name instead. + + + You can find both resource groups in the [Azure Portal](https://portal.azure.com/#view/HubsExtension/BrowseResourceGroups) by searching for `qovery-`. + + + + + Before removing subscription-level permissions, you must pre-register the required Azure resource providers. See the [Resource Provider Registration](#pre-register-required-azure-resource-providers) section below. + + + + In the Azure Portal: + 1. Go to **Subscriptions** > select your subscription + 2. Click **Access control (IAM)** + 3. Click **Role assignments** + 4. Find the Qovery Service Principal entries + 5. Remove both the **Contributor** and **User Access Administrator** role assignments at subscription level + + + + For **each** of the two resource groups (main and node), add the following roles: + + 1. Go to the resource group in Azure Portal + 2. Click **Access control (IAM)** + 3. Click **Add** > **Add role assignment** + 4. Assign **Contributor** role to the Qovery Service Principal + 5. Repeat to assign **User Access Administrator** role + + + You must add both roles to **both** resource groups. Missing a role or resource group will cause deployment failures. + + + + + Trigger a redeployment of the cluster from the Qovery console to verify everything works correctly with the scoped permissions. + + + +### Using Azure CLI + +You can also scope permissions using the Azure CLI: + +```bash +# Set your variables +SP_OBJECT_ID="" +SUBSCRIPTION_ID="" +MAIN_RG="qovery-" +NODE_RG="MC_qovery-__" + +# Remove subscription-level roles +az role assignment delete \ + --assignee "$SP_OBJECT_ID" \ + --role "Contributor" \ + --scope "/subscriptions/$SUBSCRIPTION_ID" + +az role assignment delete \ + --assignee "$SP_OBJECT_ID" \ + --role "User Access Administrator" \ + --scope "/subscriptions/$SUBSCRIPTION_ID" + +# Add roles scoped to the main resource group +az role assignment create \ + --assignee "$SP_OBJECT_ID" \ + --role "Contributor" \ + --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$MAIN_RG" + +az role assignment create \ + --assignee "$SP_OBJECT_ID" \ + --role "User Access Administrator" \ + --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$MAIN_RG" + +# Add roles scoped to the node resource group +az role assignment create \ + --assignee "$SP_OBJECT_ID" \ + --role "Contributor" \ + --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$NODE_RG" + +az role assignment create \ + --assignee "$SP_OBJECT_ID" \ + --role "User Access Administrator" \ + --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$NODE_RG" +``` + +## Pre-Register Required Azure Resource Providers + +When using resource-group-scoped permissions, the Service Principal cannot register resource providers at the subscription level. You must pre-register them as a one-time admin operation before scoping down permissions. + + +Resource provider registration is a **subscription-level** operation. It must be done by a user or service principal with subscription-level access **before** you remove subscription-level role assignments. + + +### Required Resource Providers + +| Resource Provider | Purpose | +|-------------------|---------| +| `Microsoft.ContainerService` | AKS cluster management | +| `Microsoft.Network` | Virtual networks, load balancers, NAT gateways | +| `Microsoft.Compute` | Virtual machine scale sets for node pools | +| `Microsoft.Storage` | Managed disks and storage accounts | +| `Microsoft.ManagedIdentity` | Managed identities used by AKS | +| `Microsoft.Authorization` | Role assignments for managed identities | +| `Microsoft.OperationsManagement` | Container Insights and monitoring solutions | +| `Microsoft.OperationalInsights` | Log Analytics workspaces | + +### Registration Commands + +Run these commands in Azure Cloud Shell (Bash) or any terminal with the Azure CLI installed: + +```bash +az provider register --namespace Microsoft.ContainerService +az provider register --namespace Microsoft.Network +az provider register --namespace Microsoft.Compute +az provider register --namespace Microsoft.Storage +az provider register --namespace Microsoft.ManagedIdentity +az provider register --namespace Microsoft.Authorization +az provider register --namespace Microsoft.OperationsManagement +az provider register --namespace Microsoft.OperationalInsights +``` + +### Verify Registration Status + +Check that all providers are registered: + +```bash +az provider show --namespace Microsoft.ContainerService --query "registrationState" -o tsv +az provider show --namespace Microsoft.Network --query "registrationState" -o tsv +az provider show --namespace Microsoft.Compute --query "registrationState" -o tsv +az provider show --namespace Microsoft.Storage --query "registrationState" -o tsv +az provider show --namespace Microsoft.ManagedIdentity --query "registrationState" -o tsv +az provider show --namespace Microsoft.Authorization --query "registrationState" -o tsv +az provider show --namespace Microsoft.OperationsManagement --query "registrationState" -o tsv +az provider show --namespace Microsoft.OperationalInsights --query "registrationState" -o tsv +``` + +All providers should show `Registered`. Registration can take a few minutes to complete. + +## Entra ID Requirements + +Qovery requires the **Cloud Application Administrator** role in Microsoft Entra ID (formerly Azure Active Directory) to create and manage application registrations. + +### What Qovery Uses Entra ID For + +| Action | Description | +|--------|-------------| +| **Application Registration** | Creates an App Registration for authentication with your Azure subscription | +| **Short-Lived Credentials** | Generates credentials with a 4-hour expiration for each deployment | +| **No Stored Secrets** | No long-lived secrets are stored; credentials are regenerated on demand | + + +The 4-hour credential expiration provides strong security by limiting the window of exposure. Credentials are automatically regenerated for each deployment operation. + + +## Custom Node Resource Group Name + +By default, AKS creates a node resource group with the naming convention: + +``` +MC_qovery-__ +``` + +You can specify a custom name for the node resource group to make it predictable and simplify permission scoping. This is particularly useful when using resource-group-scoped permissions because you can pre-create the resource group and assign permissions before deployment. + +### How to Configure + +Set the custom node resource group name in the cluster advanced settings in the Qovery console. Refer to the [Cluster Advanced Settings](/configuration/cluster-advanced-settings) documentation for details. + + +The custom node resource group name can only be set **before** the initial cluster deployment. It cannot be changed after the cluster is created. + + +## Troubleshooting + + + + **Symptoms:** Cluster update or application deployment fails with authorization errors. + + **Solutions:** + 1. Verify that both **Contributor** and **User Access Administrator** roles are assigned on **both** resource groups + 2. Check that all required resource providers are registered (see [Pre-Register Required Azure Resource Providers](#pre-register-required-azure-resource-providers)) + 3. Ensure the Service Principal object ID matches the one used by Qovery + 4. Wait a few minutes after assigning roles -- Azure role assignments can take up to 5 minutes to propagate + + + + **Symptoms:** Errors mentioning resource provider not registered. + + **Solutions:** + 1. Re-register the missing resource provider using the commands above + 2. Resource provider registration requires subscription-level access -- use a subscription admin to run the registration + 3. Verify registration status with `az provider show --namespace --query "registrationState"` + + + + **Symptoms:** You cannot find the AKS node resource group in the Azure Portal. + + **Solutions:** + 1. In the Azure Portal, go to your AKS cluster resource + 2. Under **Properties**, look for the **Node resource group** field + 3. Alternatively, run: `az aks show --resource-group qovery- --name --query "nodeResourceGroup" -o tsv` + + + + **Symptoms:** Errors related to application registration or credential creation. + + **Solutions:** + 1. Verify the service principal has **Cloud Application Administrator** role in Entra ID + 2. Check that the Entra ID tenant matches the one configured in Qovery + 3. Contact your Azure AD administrator to grant the required Entra ID role + + + +## Related Resources + + + + Step-by-step Azure installation guide + + + AKS cluster configuration reference + + + Manage cloud provider credentials + + + Advanced cluster configuration options + + diff --git a/docs/docs.json b/docs/docs.json index cb6beaa..c6fb432 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -226,7 +226,8 @@ "group": "Azure AKS", "pages": [ "configuration/integrations/kubernetes/aks/overview", - "configuration/integrations/kubernetes/aks/managed" + "configuration/integrations/kubernetes/aks/managed", + "configuration/integrations/kubernetes/aks/permissions" ] }, { diff --git a/docs/snippets/azure-credentials.mdx b/docs/snippets/azure-credentials.mdx index c51e40d..a2b1b11 100644 --- a/docs/snippets/azure-credentials.mdx +++ b/docs/snippets/azure-credentials.mdx @@ -103,6 +103,7 @@ Qovery needs credentials to manage resources in your Azure subscription. We use Qovery requires these Azure permissions to manage your infrastructure: - **Contributor Role**: Full access to create and manage resources (AKS, VMs, VNets, Load Balancers, etc.) + - **User Access Administrator Role**: Assign roles to managed identities created by AKS - **Resource Group Management**: Create and manage resource groups - **Azure Kubernetes Service**: Create and manage AKS clusters - **Virtual Network**: Configure VNets, subnets, NSGs, and NAT Gateways @@ -110,7 +111,9 @@ Qovery needs credentials to manage resources in your Azure subscription. We use - **Storage**: Create and manage Managed Disks for persistent storage - **DNS**: Configure DNS zones and records - The service principal created by the script is assigned the **Contributor** role at the subscription level, which provides all necessary permissions. + The service principal created by the script is assigned the **Contributor** and **User Access Administrator** roles at the subscription level. After the initial deployment, you can optionally scope these permissions down to specific resource groups. + + See [Azure Permission Requirements](/configuration/integrations/kubernetes/aks/permissions) for details on permission models, resource-group scoping, and required resource provider registration. From e4422810abcd29c2d0ca9a8f7546833208069ae5 Mon Sep 17 00:00:00 2001 From: Guillaume Da Silva Date: Thu, 26 Feb 2026 16:16:47 +0100 Subject: [PATCH 2/2] Update docs: node_resource_group is now forced to deterministic name Reflect that Qovery now automatically sets node_resource_group to {resource_group_name}-nodes instead of relying on Azure default naming or user configuration. --- .../kubernetes/aks/permissions.mdx | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/docs/configuration/integrations/kubernetes/aks/permissions.mdx b/docs/configuration/integrations/kubernetes/aks/permissions.mdx index 1b7bf73..e1417f6 100644 --- a/docs/configuration/integrations/kubernetes/aks/permissions.mdx +++ b/docs/configuration/integrations/kubernetes/aks/permissions.mdx @@ -51,9 +51,9 @@ After the initial cluster deployment completes successfully, you can restrict th **Node resource group (managed by AKS):** ``` - MC_qovery-__ + qovery--nodes ``` - If you configured a [custom node resource group name](#custom-node-resource-group-name), it will use that name instead. + Qovery automatically sets this deterministic name during cluster creation. You can find both resource groups in the [Azure Portal](https://portal.azure.com/#view/HubsExtension/BrowseResourceGroups) by searching for `qovery-`. @@ -101,7 +101,7 @@ You can also scope permissions using the Azure CLI: SP_OBJECT_ID="" SUBSCRIPTION_ID="" MAIN_RG="qovery-" -NODE_RG="MC_qovery-__" +NODE_RG="qovery--nodes" # Remove subscription-level roles az role assignment delete \ @@ -206,23 +206,19 @@ Qovery requires the **Cloud Application Administrator** role in Microsoft Entra The 4-hour credential expiration provides strong security by limiting the window of exposure. Credentials are automatically regenerated for each deployment operation. -## Custom Node Resource Group Name +## Node Resource Group Naming -By default, AKS creates a node resource group with the naming convention: +Qovery automatically sets the AKS node resource group name to a deterministic value: ``` -MC_qovery-__ +qovery--nodes ``` -You can specify a custom name for the node resource group to make it predictable and simplify permission scoping. This is particularly useful when using resource-group-scoped permissions because you can pre-create the resource group and assign permissions before deployment. +This predictable naming makes it easy to pre-scope Service Principal permissions to both resource groups **before** the initial deployment, enabling you to start with resource-group-scoped permissions from day one. -### How to Configure - -Set the custom node resource group name in the cluster advanced settings in the Qovery console. Refer to the [Cluster Advanced Settings](/configuration/cluster-advanced-settings) documentation for details. - - -The custom node resource group name can only be set **before** the initial cluster deployment. It cannot be changed after the cluster is created. - + +The node resource group name is set automatically by Qovery and cannot be customized. This ensures a consistent and predictable naming convention across all Qovery-managed AKS clusters. + ## Troubleshooting