Hey I am looking to assign Azure Policy which will deny creation of Network Interfaces without NSG attached.
I looked with build-in role and couldn't find anything related. Maybe someone have script that does the job.
Thanks for your help in advance.
I tried to create the azure policy to deny creation of network interface without NSG
I have created the policy definition named network
In the policy rule write the below json script to create the policy rules to deny the virtual network without NSG rules
I took the example reference from git URL #withstu
{
"name": "Deny-Subnet-Without-Nsg",
"type": "Microsoft.Authorization/policyDefinitions",
"apiVersion": "2022-11-22",
"scope": null,
"properties": {
"policyType": "Custom",
"mode": "All",
"displayName": "Subnets should have a Network Security Group",
"description": " policy will deny the creation of a network/subnet with out an NSG.",
"metadata": {
"version": "1.1.0",
"category": "Network"
},
"parameters": {
"effect": {
"type": "String",
"allowedValues": [
"Audit",
"Deny",
"Disabled"
],
"defaultValue": "Deny",
"metadata": {
"displayName": "Effect",
"description": " disable the execution of the policy"
}
},
"excludedSubnets": {
"type": "Array",
"metadata": {
"displayName": "Excluded Subnets",
"description": "subnets excluded from this policy"
},
"defaultValue": [
"GatewaySubnet",
"AzureFirewallSubnet",
"AzureFirewallManagementSubnet"
]
}
},
"policyRule": {
"if": {
"anyOf": [
{
"allOf": [
{
"equals": "Microsoft.Network/virtualNetworks",
"field": "type"
},
{
"exists": "false",
"field": "Microsoft.Network/virtualNetworks/subnets[*].networkSecurityGroup.id"
}
]
},
{
"allOf": [
{
"equals": "Microsoft.Network/virtualNetworks/subnets",
"field": "type"
},
{
"field": "name",
"notIn": "[parameters('excludedSubnets')]"
},
{
"exists": "false",
"field": "Microsoft.Network/virtualNetworks/subnets/networkSecurityGroup.id"
}
]
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
}
}
}
I have assigned the policy to the policy definition
In left side of the menu click on Assignment => click on assign policy and added the appropriate fields to create
After assigning the polices it will take 30 minutes to reflect
I am trying to creating the virtual network , I got the error because of deny subnet without NSG
Related
Hello I am trying to deploy this template via azure devops and get this error:
'The template resource '' of type 'microsoft.insights/workbooks' at line '1' and column '1512' is not valid. The name property cannot be null or empty. Please see https://aka.ms/arm-template/#resources for usage details.'." AdditionalInfo=[{"info":{"lineNumber":1,"linePosition":1512,"path":"properties.template.resources[0]"},"type":"TemplateViolation"}]
Template:
{
"contentVersion": "1.0.0.0",
"parameters": {
"workbookDisplayName": {
"type": "string",
"defaultValue": "Azure Firewall Workbook",
"metadata": {
"description": "The friendly name for the workbook that is used in the Gallery or Saved List. This name must be unique within a resource group."
}
},
"workbookType": {
"type": "string",
"allowedValues": [
"workbook",
"sentinel"
],
"defaultValue": "workbook",
"metadata": {
"description": "The gallery that the workbook will been shown under. Supported values include workbook, tsg, etc. Usually, this is 'workbook'"
}
},
"DiagnosticsWorkspaceName": {
"type": "string",
"defaultValue": "WorkspaceName",
"metadata": {
"description": "Provide the workspace name for your Network Diagnostic logs"
}
},
"DiagnosticsWorkspaceSubscription": {
"type": "string",
"defaultValue": "WorkspaceSubscriptionID",
"metadata": {
"description": "Provide the workspace subscription GUID for your Network Diagnostic logs"
}
},
"DiagnosticsWorkspaceResourceGroup": {
"type": "string",
"defaultValue": "ResourceGroupName",
"metadata": {
"description": "Provide the workspace resourcegroupname for your Network Diagnostic logs"
}
},
"workbookId": {
"type": "string",
"defaultValue": "[newGuid()]",
"metadata": {
"description": "The unique guid for this workbook instance"
}
}
},
"variables": {
"workbookSourceId": "[concat('/subscriptions/',parameters('DiagnosticsWorkspaceSubscription'),'/resourcegroups/', parameters('DiagnosticsWorkspaceResourceGroup'), '/providers/Microsoft.OperationalInsights/workspaces/',parameters('DiagnosticsWorkspaceName'))]"
},
"resources": [
{
"name": "[parameters('workbookId')]",
"type": "microsoft.insights/workbooks",
"location": "[resourceGroup().location]",
"apiVersion": "2018-06-17-preview",
"dependsOn": [],
"kind": "shared",
"properties": {
"displayName": "[parameters('workbookDisplayName')]"}",
"version": "1.0",
"sourceId": "[variables('workbookSourceId')]",
"category": "[parameters('workbookType')]"
}
}
],
"outputs": {
"workbookId": {
"type": "string",
"value": "[resourceId( 'microsoft.insights/workbooks', parameters('workbookId'))]"
}
},
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#"
}
Looks like there are some syntactical errors in the above shared ARM template .
"properties": {
"displayName": "[parameters('workbookDisplayName')]"}",
"version": "1.0",
"sourceId": "[variables('workbookSourceId')]",
"category": "[parameters('workbookType')]"
}
As per the Azure documentation for the Microsoft.Insights/Workbooks sourceID,Category & Version are the parameters of the properties block.
When we have loaded the above shared Json template/ARM template in our VisualStudioCode,the intellisense has found few syntactical errors & also thrown error stating serializedData parameter is mandatory in the properities block of Microsoft.Insights/Workbooks.
Here is the ARM template post fixing those errors & tried deploying in our local environment which got successfully deployed without any issues.
{
"contentVersion": "1.0.0.0",
"parameters": {
"workbookDisplayName": {
"type": "string",
"defaultValue": "Azure Firewall Workbook",
"metadata": {
"description": "The friendly name for the workbook that is used in the Gallery or Saved List. This name must be unique within a resource group."
}
},
"workbookType": {
"type": "string",
"allowedValues": [
"workbook",
"sentinel"
],
"defaultValue": "workbook",
"metadata": {
"description": "The gallery that the workbook will been shown under. Supported values include workbook, tsg, etc. Usually, this is 'workbook'"
}
},
"DiagnosticsWorkspaceName": {
"type": "string",
"defaultValue": "WorkspaceName",
"metadata": {
"description": "Provide the workspace name for your Network Diagnostic logs"
}
},
"DiagnosticsWorkspaceSubscription": {
"type": "string",
"defaultValue": "WorkspaceSubscriptionID",
"metadata": {
"description": "Provide the workspace subscription GUID for your Network Diagnostic logs"
}
},
"DiagnosticsWorkspaceResourceGroup": {
"type": "string",
"defaultValue": "ResourceGroupName",
"metadata": {
"description": "Provide the workspace resourcegroupname for your Network Diagnostic logs"
}
},
"workbookId": {
"type": "string",
"defaultValue": "[newGuid()]",
"metadata": {
"description": "The unique guid for this workbook instance"
}
}
},
"variables": {
"workbookSourceId": "[concat('/subscriptions/',parameters('DiagnosticsWorkspaceSubscription'),'/resourcegroups/', parameters('DiagnosticsWorkspaceResourceGroup'), '/providers/Microsoft.OperationalInsights/workspaces/',parameters('DiagnosticsWorkspaceName'))]"
},
"resources": [
{
"name": "[parameters('workbookId')]",
"type": "microsoft.insights/workbooks",
"location": "[resourceGroup().location]",
"apiVersion": "2018-06-17-preview",
"dependsOn": [],
"kind": "shared",
"properties" : {
"displayName": "[parameters('workbookDisplayName')]",
"sourceId": "[variables('workbookSourceId')]",
"category": "[parameters('workbookType')]",
"serializedData" : "",
"version" : "1.0"
}
}
],
"outputs": {
"workbookId": {
"type": "string",
"value": "[resourceId( 'microsoft.insights/workbooks', parameters('workbookId'))]"
}
},
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"
}
Note:
In the above shared template, we observed that the schema version in the deployment template you are using is 2015-01-01 its always suggested to use latest version 2019-04-01
Here is the output sample for our reference:
I am trying to create a policy for Azure CIS, and getting the following error when I attempt to deploy it via powershell on the management group level - im trying to figure out what is missing as it says invalid template.
It looks like the error is related to something to do with the scope, but not sure what exactly is going on:
New-AzManagementGroupDeployment : 1:19:17 AM - The deployment 'cis1.23-azurepolicy' failed with error(s). Showing 1 out of 1 error(s).
Status Message: Unable to process template language expressions for resource
'/providers/Microsoft.Management/managementGroups/MGName/providers/Microsoft.Authorization/policyDefinitions/CIS1.23-EnsureNoCustomerOwnerRoles' at line '23' and
column '9'. 'The deployment metadata 'SUBSCRIPTION' is not valid.' (Code:InvalidTemplate)
Here is the template:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"effect": {
"type": "string",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": [
"Audit",
"Disabled"
],
"defaultValue": "Audit"
}
},
"variables": {},
"resources": [
{
"name": "CIS1.23-EnsureNoCustomerOwnerRoles",
"type": "Microsoft.Authorization/policyDefinitions",
"apiVersion": "2018-03-01",
"properties": {
"policyType": "Custom",
"displayName": "CIS 1.23 Custom Owner Roles should not exist (Not Scored)",
"description": "This policy checks that Custom Roles with Owner privileges are removed",
"mode": "all",
"metadata": {
"category": "Identity"
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "Enable or disable the execution of the policy"
},
"allowedValues": [
"Audit",
"Disabled"
],
"defaultValue": "Audit"
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Authorization/roleDefinitions"
},
{
"field": "Microsoft.Authorization/roleDefinitions/type",
"equals": "CustomRole"
},
{
"anyOf": [
{
"not": {
"field": "Microsoft.Authorization/roleDefinitions/permissions[*].actions[*]",
"notEquals": "*"
}
},
{
"not": {
"field": "Microsoft.Authorization/roleDefinitions/permissions.actions[*]",
"notEquals": "*"
}
}
]
},
{
"anyOf": [
{
"not": {
"field": "Microsoft.Authorization/roleDefinitions/assignableScopes[*]",
"notIn": [
"[concat(subscription().id,'/')]",
"[subscription().id]",
"/"
]
}
},
{
"not": {
"field": "Microsoft.Authorization/roleDefinitions/assignableScopes[*]",
"notLike": "/providers/Microsoft.Management/*"
}
}
]
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
}
}
}
You are deploying the ARM template to a management group, but you are referencing the ARM template subscription() function. The subscription() function is only valid when deploying to a subscription or resource group. When deploying to a management group then there is no subscription that could be referenced.
To resolve this you need to deploy this policy to a subscription, not to a management group.
Usually in an ARM Infrastructure as Code, there is a main JSON and a parameters JSON. Trying to figure out if the Azure Policy needs to be in a separate JSON template or can it exist in a main JSON template?
Azure Policy definition is just another resource in the ARM engine:
{
"type": "Microsoft.Authorization/policyDefinitions",
"name": "allowed-role-definitions-def",
"apiVersion": "2018-03-01",
"properties": {
"policyType": "Custom",
"displayName": "Allowed Role Definitions",
"description": "This policy defines a white list of role deifnitions that can be used in IAM",
"mode": "all",
"parameters": {
"roleDefinitionIds": {
"type": "array",
"metadata": {
"description": "The list of role definition Ids",
"displayName": "Approved Role Definitions"
}
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Authorization/roleAssignments"
},
{
"not": {
"field": "Microsoft.Authorization/roleAssignments/roleDefinitionId",
"in": "[parameters('roleDefinitionIds')]"
}
}
]
},
"then": {
"effect": "deny"
}
}
}
}
this has to a be a subscription level deployment (not resource group).
https://blog.tyang.org/2018/06/06/using-arm-templates-to-deploying-azure-policy-definitions-that-requires-input-parameters/
Is there a way to apply RBAC rules at the resource level via ARM? I was able to follow this Microsoft guide to add a user/role at the resource group level, but not at the resource. In particular, I am trying to add a new reader role to AppInsights via ARM. However, when I adjust the scope, the template just fails with this error:
"error": {
"code": "InvalidCreateRoleAssignmentRequest",
"message": "The request to create role assignment '{guid}' is not valid. Role assignment scope '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/Microsoft.Insights/components/{resourceGroupName}' must match the scope specified on the URI '/subscriptions/{resourceGroupName}/resourcegroups/{resourceGroupName}'."
}
I am left wondering what the scope variable is for if it cannot be changed. Is there some other place I should be modifying the scope to get this working?
Thanks in advance!
The key is to drop the scope property, and instead nest the role assignment under the desired resource by using Microsoft.FooResource/BarSubType/providers/roleAssignments as the type, and using the following format for the name: {resourceName}/Microsoft.Authorization/{uniqueRoleAssignmentGuid}. Note that the GUID should be stable but unique to this role assignment, one easy option is guid(subscription().subscriptionId, 'some-sub-identifier-if-you-wish').
Here is a template that shows you how to apply RBAC to a single resource, using a user-assigned managed identity defined in the same template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": { "type": "string" },
"userAssignedIdentityName": { "type": "string" }
},
"variables": {
"ContributorRoleDefinition": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
},
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"name": "[parameters('userAssignedIdentityName')]",
"location": "[resourceGroup().location]",
"apiVersion": "2018-11-30"
},
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[parameters('storageAccountName')]",
"location": "[resourceGroup().location]",
"apiVersion": "2016-12-01",
"sku": { "name": "Standard_LRS" },
"kind": "Storage",
"resources": [
{
"type": "Microsoft.Storage/storageAccounts/providers/roleAssignments",
"apiVersion": "2017-05-01",
"name": "[concat(parameters('storageAccountName'), '/Microsoft.Authorization/', guid(subscription().subscriptionId, 'foo'))]",
"properties": {
"roleDefinitionId": "[variables('ContributorRoleDefinition')]",
"principalId": "[reference(parameters('userAssignedIdentityName'), '2018-11-30').principalId]"
},
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userAssignedIdentityName'))]"
]
}
]
}
]
}
Source: https://www.henrybeen.nl/creating-an-authorization-rule-using-an-arm-template/
You apply RBAC rules at the resource level via an ARM and there is example template that applies RBAC rules at Azure VM here:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"principalId": {
"type": "string",
"metadata": {
"description": "Principal ID associated with the subscription ID"
}
},
"virtualMachineName": {
"type": "string",
"metadata": {
"description": "Name of the virtual machine"
}
},
"builtInRoleType": {
"type": "string",
"metadata": {
"description": "Built In Role Type for the Virtual Machine"
},
"allowedValues": [
"Owner",
"Contributor",
"Reader",
"Virtual Machine Contributor"
]
},
"guid": {
"type": "string",
"metadata": {
"description": "A new GUID used to identify the role"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
}
},
"variables": {
"Owner": "[concat('/subscriptions/',subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]",
"Contributor": "[concat('/subscriptions/',subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
"Reader": "[concat('/subscriptions/',subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]",
"Virtual Machine Contributor": "[concat('/subscriptions/',subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'd73bb868-a0df-4d4d-bd69-98a00b01fccb')]",
"resourceName": "[concat(parameters('virtualMachineName'), '/Microsoft.Authorization/', parameters('guid'))]"
},
"resources": [
{
"type": "Microsoft.Compute/virtualMachines/providers/roleAssignments",
"apiVersion": "2017-05-01",
"name": "[variables('resourceName')]",
"properties": {
"roleDefinitionId": "[variables(parameters('builtInRoleType'))]",
"principalId": "[parameters('principalId')]"
}
}
]
}
Hope this will help you.
Microsoft has finally provided documentation explaining this:
https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-template#resource-scope
It is possible to apply RBAC on resource level using ARM.
The example what you referred shows how to apply RBAC on a particular resource group, where the scope is the path of the resource group.
Here, you are trying to assign a role to a particular resource. Changing the scope from resource group to resource (AppInsights) will work.
From the exception, I can see that the path of the resource may not be in the expected format.
The path of AppInsights should be in the following format,
/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/microsoft.insights/components/{insightName}
Hope framing the scope like this helps!
Agree that the documentation on this issue is less than useful. I have an array of Role IDs that I wanted to add as Owners at the App Insight resource, without making the users Owners at the Resource Group level. I didn't want to use the nested resource approach as I wanted to iterate over an array of objects to dynamically create the roles, so after tweaking the type, name, and scope attributes, the following resource block is what ended up working for me:
{
"comments": "Add the Application Insights resource",
"apiVersion": "2014-04-01",
"name": "[variables('appInsightsName')]",
"type": "Microsoft.Insights/components",
"location": "[resourceGroup().location]",
"properties": {
"ApplicationId": "[variables('appInsightsName')]"
}
},
{
"comments": "Add the IAM roles to the App Insights resource",
"condition": "[parameters('isProduction')]",
"type": "Microsoft.Insights/components/providers/roleAssignments",
"name": "[concat(variables('appInsightsName'),'/Microsoft.Authorization/',guid(parameters('roleAssignments')[copyIndex()].principalId))]",
"apiVersion": "2017-05-01",
"location": "[resourceGroup().location]",
"properties": {
"roleDefinitionId": "[concat(subscription().Id, '/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", // Owner Role
"principalId": "[parameters('roleAssignments')[copyIndex()].principalId]",
"scope": "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]"
},
"copy": {
"name": "appInsightsRoleAssignments",
"count": "[length(parameters('roleAssignments'))]"
},
"dependsOn": [
"[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]"
]
}
According to https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#property-iteration it should be possible to create multiple values on a resource using copy but I can't make it work. Here is my code...
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appServiceName": {
"type": "string",
"metadata": {
"description": "Name of app service to apply SSL to."
}
},
"certificateName": {
"type": "string",
"metadata": {
"description": "User friendly certificate resource name"
}
},
"appServicePlan": {
"type": "string",
"metadata": {
"description": "App Service Plan Name"
}
},
"keyVaultId": {
"type": "string",
"metadata": {
"description": "Existing Key Vault resource Id with an access policy to allow Microsoft.Web RP to read Key Vault secrets (Checkout README.md for more information)"
}
},
"hostname": {
"type": "array",
"metadata": {
"description": "Custom hostname for creating SSL binding. This hostname should already be assigned to the Web App"
}
}
},
"resources": [
{
"apiVersion": "2017-03-30",
"type": "Microsoft.Web/sites",
"name": "[parameters('appServiceName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/certificates', parameters('certificateName'))]"
],
"properties": {
"copy": [
{
"name": "hostnames",
"count": "[length(parameters('hostname'))]",
"input": {
"name": "[copyIndex('hostnames')]",
"properties": {
"hostNameSslStates": [
{
"name": "[[copyIndex(hostname)]]",
"sslState": "SniEnabled",
"thumbprint": "[reference(resourceId('Microsoft.Web/certificates', parameters('certificateName'))).Thumbprint]",
"toUpdate": true
}
]
}
}
}
]
}
},
{
"type": "Microsoft.Web/certificates",
"name": "[parameters('certificateName')]",
"apiVersion": "2016-03-01",
"location": "[resourceGroup().location]",
"properties": {
"keyVaultId": "[parameters('keyVaultId')]",
"keyVaultSecretName": "[parameters('certificateName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms',parameters('appServicePlan'))]"
}
}
]
}
And it returns Error: Code=InvalidTemplate; Message=Deployment template l
anguage expression evaluation failed: 'Unable to parse language expression 'copyIndex(hostname)]': expecte
d token 'LeftParenthesis' and actual 'RightParenthesis'.'. Please see https://aka.ms/arm-template-expressi
ons for usage details.
Any ideas what am I doing wrong?
Thanks in advance!
the error gives is away:
change "[[copyIndex(hostname)]]", to "[copyIndex('hostname')]"
you even have it right in other places, why not here?
and you probably want to do this:
"[parameters('hostname')[copyIndex('hostname')]]"