Search code examples
azureterraformazure-rm-templateazure-policy

Azure portal allow deployment only through ARM templates or Terraform


I have been looking everywhere but I cannot find a solution to this problem.

In azure I have a productionsubscription, to which I would like to deny any sort of manual deployments and allow only deployment with arm templates OR terraform.

using azure group management policies, I did put in place the definition of blocking all sort of deployment not allowed. But this not only denies the deployment from the portal, but it does block the deployment with arms or terraform.

Can anyone help to understand how can I allow deployment as code, and block all the portal deployment?

Thank you very much for any help you can provide and if my question is not clear, please feel free to ask more info


Solution

  • Thank you Daniel Mann. Posting your suggestion as an answer to help other community members.

    As Daniel suggested, "Don't give users Contributor permissions and do all deployments through service principals."

    You can add a role assignment to an existing service principal using ARM templates.

    Subscription deployments with ARM templates

    For example:

    {
      "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
      "contentVersion": "1.0.0.0",
      "metadata": {
        "_generator": {
          "name": "bicep",
          "version": "0.4.1.14562",
          "templateHash": "17666923867108240565"
        }
      },
      "parameters": {
        "rgName": {
          "type": "string",
          "metadata": {
            "description": "Name of the resourceGroup to create"
          }
        },
        "rgLocation": {
          "type": "string",
          "metadata": {
            "description": "Location for the resourceGroup"
          }
        },
        "principalId": {
          "type": "string",
          "metadata": {
            "description": "principalId of the user that will be given contributor access to the resourceGroup"
          }
        },
        "roleDefinitionId": {
          "type": "string",
          "defaultValue": "b24988ac-6180-42a0-ab88-20f7382dd24c",
          "metadata": {
            "description": "roleDefinition to apply to the resourceGroup - default is contributor"
          }
        },
        "roleAssignmentName": {
          "type": "string",
          "defaultValue": "[guid(parameters('principalId'), parameters('roleDefinitionId'), parameters('rgName'))]",
          "metadata": {
            "description": "Unique name for the roleAssignment in the format of a guid"
          }
        }
      },
      "functions": [],
      "resources": [
        {
          "type": "Microsoft.Resources/resourceGroups",
          "apiVersion": "2019-10-01",
          "name": "[parameters('rgName')]",
          "location": "[parameters('rgLocation')]",
          "tags": {
            "Note": "subscription level deployment"
          },
          "properties": {}
        },
        {
          "type": "Microsoft.Resources/deployments",
          "apiVersion": "2019-10-01",
          "name": "applyLock",
          "resourceGroup": "[parameters('rgName')]",
          "properties": {
            "expressionEvaluationOptions": {
              "scope": "inner"
            },
            "mode": "Incremental",
            "parameters": {
              "principalId": {
                "value": "[parameters('principalId')]"
              },
              "roleDefinitionId": {
                "value": "[parameters('roleDefinitionId')]"
              },
              "roleAssignmentName": {
                "value": "[parameters('roleAssignmentName')]"
              }
            },
            "template": {
              "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
              "contentVersion": "1.0.0.0",
              "metadata": {
                "_generator": {
                  "name": "bicep",
                  "version": "0.4.1.14562",
                  "templateHash": "12740078983609655962"
                }
              },
              "parameters": {
                "principalId": {
                  "type": "string",
                  "metadata": {
                    "description": "principalId of the user that will be given contributor access to the resourceGroup"
                  }
                },
                "roleDefinitionId": {
                  "type": "string",
                  "metadata": {
                    "description": "roleDefinition to apply to the resourceGroup - default is contributor"
                  }
                },
                "roleAssignmentName": {
                  "type": "string",
                  "metadata": {
                    "description": "Unique name for the roleAssignment in the format of a guid"
                  }
                }
              },
              "functions": [],
              "resources": [
                {
                  "type": "Microsoft.Authorization/locks",
                  "apiVersion": "2016-09-01",
                  "name": "DontDelete",
                  "properties": {
                    "level": "CanNotDelete",
                    "notes": "Prevent deletion of the resourceGroup"
                  }
                },
                {
                  "type": "Microsoft.Authorization/roleAssignments",
                  "apiVersion": "2020-04-01-preview",
                  "name": "[guid(parameters('roleAssignmentName'))]",
                  "properties": {
                    "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('roleDefinitionId'))]",
                    "principalId": "[parameters('principalId')]"
                  }
                }
              ]
            }
          },
          "dependsOn": [
            "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('rgName'))]"
          ]
        }
      ]
    }
    

    You can refer to Is there a way to use ARM Template to create an Azure Service Principal?, Assign Azure roles using Azure Resource Manager templates, and Automatic Service Principal creation in the Azure deployment