Sample - Audit if specified applications aren't installed inside Linux VMs

This Policy Guest Configuration initiative creates an audit event when the specified applications aren't installed inside Linux virtual machines. The ID of this built-in initiative is /providers/Microsoft.Authorization/policySetDefinitions/c937dcb4-4398-4b39-8d63-4a6be432252e.

Important

All Guest Configuration initiatives are composed of audit and deployIfNotExists policy definitions. Assigning only one of the policy definitions cause Guest Configuration not to work correctly.

You can assign this sample using:

If you don't have an Azure subscription, create a free account before you begin.

Components of the initiative

This Guest Configuration initiative is made up of the following policies:

  • audit - Audit when applications aren't installed inside Linux VMs
    • ID: /providers/Microsoft.Authorization/policyDefinitions/fee5cb2b-9d9b-410e-afe3-2902d90d0004
  • deployIfNotExists - Deploy VM extension to audit when applications aren't installed inside Linux VMs
    • ID: /providers/Microsoft.Authorization/policyDefinitions/4d1c04de-2172-403f-901b-90608c35c721

Initiative definition

The initiative is created by joining the audit and deployIfNotExists definitions together and the initiative Parameters. This is the JSON of the definition.

{
    "properties": {
        "displayName": "Audit Linux VMs that do not have the specified applications installed",
        "description": "This initiative deploys the policy requirements and audits Linux virtual machines that do not have the specified applications installed. For more information on guest configuration policies, please visit https://aka.ms/gcpol",
        "parameters": {
            "applicationName": {
                "type": "String",
                "metadata": {
                    "displayName": "Application names",
                    "description": "A semicolon-separated list of the names of the applications that should be installed. e.g. python; powershell"
                }
            }
        },
        "policyDefinitions": [
            {
                "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/fee5cb2b-9d9b-410e-afe3-2902d90d0004"
            },
            {
                "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/4d1c04de-2172-403f-901b-90608c35c721",
                "parameters": {
                    "applicationName": {
                        "value": "[parameters('applicationName')]"
                    }
                }
            }
        ]
    }
}

Initiative parameters

Name Type Description
applicationName String Application names. Example: 'python', 'powershell', or a comma-separated list such as 'python,powershell'. Use * for wildcard matching, like 'power*'.

When creating an assignment via PowerShell or Azure CLI, the parameter values can be passed as JSON in either a string or via a file using -PolicyParameter (PowerShell) or --params (Azure CLI). PowerShell also supports -PolicyParameterObject which requires passing the cmdlet a Name/Value hashtable where Name is the parameter name and Value is the single value or array of values being passed during assignment.

In this example parameter, the installation of applications python and powershell is audited.

{
    "applicationName": {
        "value": "python,powershell"
    }
}

Only the deployIfNotExists policy definition makes use of the initiative parameters.

audit definition

The JSON defining the rules of the audit policy definition.

{
    "if": {
        "allOf": [
            {
                "field": "type",
                "equals": "Microsoft.GuestConfiguration/guestConfigurationAssignments"
            },
            {
                "field": "name",
                "equals": "installed_application_linux"
            },
            {
                "field": "Microsoft.GuestConfiguration/guestConfigurationAssignments/complianceStatus",
                "notEquals": "Compliant"
            }
        ]
    },
    "then": {
        "effect": "audit"
    }
}

deployIfNotExists definition

The JSON defining the rules of the deployIfNotExists policy definition.

{
    "if": {
        "allOf": [
            {
                "field": "type",
                "equals": "Microsoft.Compute/virtualMachines"
            },
            {
                "anyOf": [
                    {
                        "field": "Microsoft.Compute/imagePublisher",
                        "in": [
                            "microsoft-aks",
                            "AzureDatabricks",
                            "qubole-inc",
                            "datastax",
                            "couchbase",
                            "scalegrid",
                            "checkpoint",
                            "paloaltonetworks"
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "OpenLogic"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "like": "CentOS*"
                            },
                            {
                                "field": "Microsoft.Compute/imageSKU",
                                "notLike": "6*"
                            }
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "RedHat"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "equals": "RHEL"
                            },
                            {
                                "field": "Microsoft.Compute/imageSKU",
                                "notLike": "6*"
                            }
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "RedHat"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "equals": "osa"
                            }
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "credativ"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "equals": "Debian"
                            },
                            {
                                "field": "Microsoft.Compute/imageSKU",
                                "notLike": "7*"
                            }
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "Suse"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "like": "SLES*"
                            },
                            {
                                "field": "Microsoft.Compute/imageSKU",
                                "notLike": "11*"
                            }
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "Canonical"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "equals": "UbuntuServer"
                            },
                            {
                                "field": "Microsoft.Compute/imageSKU",
                                "notLike": "12*"
                            }
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "microsoft-dsvm"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "in": [
                                    "linux-data-science-vm-ubuntu",
                                    "azureml"
                                ]
                            }
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "cloudera"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "equals": "cloudera-centos-os"
                            },
                            {
                                "field": "Microsoft.Compute/imageSKU",
                                "notLike": "6*"
                            }
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "cloudera"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "equals": "cloudera-altus-centos-os"
                            }
                        ]
                    },
                    {
                        "allOf": [
                            {
                                "field": "Microsoft.Compute/imagePublisher",
                                "equals": "microsoft-ads"
                            },
                            {
                                "field": "Microsoft.Compute/imageOffer",
                                "like": "linux*"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    "then": {
        "effect": "deployIfNotExists",
        "details": {
            "type": "Microsoft.GuestConfiguration/guestConfigurationAssignments",
            "name": "installed_application_linux",
            "roleDefinitionIds": [
                "/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
            ],
            "deployment": {
                "properties": {
                    "mode": "incremental",
                    "parameters": {
                        "vmName": {
                            "value": "[field('name')]"
                        },
                        "location": {
                            "value": "[field('location')]"
                        },
                        "configurationName": {
                            "value": "installed_application_linux"
                        },
                        "ApplicationName": {
                            "value": "[parameters('ApplicationName')]"
                        }
                    },
                    "template": {
                        "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
                        "contentVersion": "1.0.0.0",
                        "parameters": {
                            "vmName": {
                                "type": "string"
                            },
                            "location": {
                                "type": "string"
                            },
                            "configurationName": {
                                "type": "string"
                            },
                            "ApplicationName": {
                                "type": "string"
                            }
                        },
                        "resources": [
                            {
                                "apiVersion": "2018-11-20",
                                "type": "Microsoft.Compute/virtualMachines/providers/guestConfigurationAssignments",
                                "name": "[concat(parameters('vmName'), '/Microsoft.GuestConfiguration/', parameters('configurationName'))]",
                                "location": "[parameters('location')]",
                                "properties": {
                                    "guestConfiguration": {
                                        "name": "[parameters('configurationName')]",
                                        "version": "1.*",
                                        "configurationParameter": [
                                            {
                                                "name": "[ChefInSpec]InstalledApplicationLinuxResource1;AttributesYmlContent",
                                                "value": "[concat('packages: [', parameters('ApplicationName'), ']')]"
                                            }
                                        ]
                                    }
                                }
                            },
                            {
                                "apiVersion": "2017-03-30",
                                "type": "Microsoft.Compute/virtualMachines",
                                "identity": {
                                    "type": "SystemAssigned"
                                },
                                "name": "[parameters('vmName')]",
                                "location": "[parameters('location')]"
                            },
                            {
                                "apiVersion": "2015-05-01-preview",
                                "name": "[concat(parameters('vmName'), '/AzurePolicyforLinux')]",
                                "type": "Microsoft.Compute/virtualMachines/extensions",
                                "location": "[parameters('location')]",
                                "properties": {
                                    "publisher": "Microsoft.GuestConfiguration",
                                    "type": "ConfigurationforLinux",
                                    "typeHandlerVersion": "1.0",
                                    "autoUpgradeMinorVersion": true
                                },
                                "dependsOn": [
                                    "[concat('Microsoft.Compute/virtualMachines/',parameters('vmName'),'/providers/Microsoft.GuestConfiguration/guestConfigurationAssignments/',parameters('configurationName'))]"
                                ]
                            }
                        ]
                    }
                }
            }
        }
    }
}

The deployIfNotExists policy definition defines the Azure images the policy has been validated on:

Publisher Offer SKU
OpenLogic CentOS* All except 6*
RedHat RHEL All except 6*
RedHat osa All
credativ Debian All except 7*
Suse SLES* All except 11*
Canonical UbuntuServer All except 12*
microsoft-dsvm linux-data-science-vm-ubuntu All
microsoft-dsvm azureml All
cloudera cloudera-centos-os All except 6*
cloudera cloudera-altus-centos-os All
microsoft-ads linux* All
microsoft-aks All All
AzureDatabricks All All
qubole-inc All All
datastax All All
couchbase All All
scalegrid All All
checkpoint All All
paloaltonetworks All All

The deployment portion of the rule passes the installedApplication parameter to the Guest Configuration agent on the virtual machine. This configuration enables the agent to perform the validations and report compliance back through the audit policy definition.

Azure portal

After the audit and deployIfNotExists definitions are created in the portal, it's recommended to group them into an initiative for assignment.

Create copy of audit definition

Deploy the Policy sample to Azure Deploy the Policy sample to Azure Gov

Using these buttons to deploy via the portal creates a copy of the audit policy definition. Without the paired deployIfNotExists policy definition, the Guest Configuration won't work correctly.

Create copy of deployIfNotExists definition

Deploy the Policy sample to Azure Deploy the Policy sample to Azure Gov

Using these buttons to deploy via the portal creates a copy of the deployIfNotExists policy definition. Without the paired audit policy definition, the Guest Configuration won't work correctly.

Azure PowerShell

This sample requires Azure PowerShell. Run Get-Module -ListAvailable Az to find the version. If you need to install or upgrade, see Install Azure PowerShell module.

Run the Connect-AzAccount cmdlet to connect to Azure.

Deploy with Azure PowerShell

Copy and assign the initiative

These steps create a copy of the initiative that includes the built-in policies for both audit and deployIfNotExists and assigns the initiative to a resource group.

# Create the policy initiative (Subscription scope)
$initDef = New-AzPolicySetDefinition -Name 'guestconfig-installed-application-linux' -DisplayName 'GuestConfig - Audit that an application is installed inside Linux VMs' -description 'This initiative will both deploy the policy requirements and audit that the specified application is installed inside Linux virtual machines.' -Policy 'https://raw.githubusercontent.com/Azure/azure-policy/master/samples/GuestConfiguration/installed-application-linux/azurepolicyset.definitions.json' -Parameter 'https://raw.githubusercontent.com/Azure/azure-policy/master/samples/GuestConfiguration/installed-application-linux/azurepolicyset.parameters.json' -Mode All

# Set the scope to a resource group; may also be a resource, subscription, or management group
$scope = Get-AzResourceGroup -Name 'YourResourceGroup'

# Set the initiative parameter (JSON format)
$initParam = '{ "applicationName": { "value": "python,powershell" } }'

# Create the initiative assignment
$assignment = New-AzPolicyAssignment -Name 'guestconfig-installed-application-linux-assignment' -DisplayName 'GuestConfig - Python and PowerShell apps on Linux' -Scope $scope.ResourceID -PolicySetDefinition $initDef -PolicyParameter $initParam -AssignIdentity -Location 'westus2'

# Get the system-assigned managed identity created by the assignment with -AssignIdentity
$saIdentity = $assignment.Identity.principalId

# Give the system-assigned managed identity the 'Contributor' role on the scope (needed by deployIfNotExists)
$roleAssignment = New-AzRoleAssignment -ObjectId $saIdentity -Scope $scope.ResourceId -RoleDefinitionName 'Contributor'

Run the following commands to remove the previous assignment and definition:

# Remove the initiative assignment
Remove-AzPolicyAssignment -Id $assignment.ResourceId

# Remove the 'Contributor' role from the system-assigned managed identity
Remove-AzRoleAssignment -ObjectId $saIdentity -Scope $scope.ResourceId -RoleDefinitionName 'Contributor'

# Remove the initiative definition
Remove-AzPolicySetDefinition -Id $initDef

Copy and assign the audit definition

These steps create a copy of the audit definition and assign it to a resource group. This definition will not work correctly without the paired deployIfNotExists definition also being assigned.

# Create the policy definition (Subscription scope)
$definition = New-AzPolicyDefinition -Name 'guestconfig-installed-application-linux-audit' -DisplayName 'GuestConfig - Audit that an application is installed inside Linux VMs' -description 'This policy audits that the specified application is installed inside Linux virtual machines. This policy should only be used along with its corresponding deploy policy in an initiative/policy set.' -Policy 'https://raw.githubusercontent.com/Azure/azure-policy/master/samples/GuestConfiguration/installed-application-linux/audit/azurepolicy.rules.json' -Mode All

# Set the scope to a resource group; may also be a resource, subscription, or management group
$scope = Get-AzResourceGroup -Name 'YourResourceGroup'

# Create the policy assignment
$assignment = New-AzPolicyAssignment -Name 'guestconfig-installed-application-linux-audit-assignment' -DisplayName 'GuestConfig - Python and PowerShell apps on Linux' -Scope $scope.ResourceID -PolicyDefinition $definition

Run the following commands to remove the previous assignment and definition:

# Remove the policy definition
Remove-AzPolicyAssignment -Id $assignment.ResourceId

# Remove the policy definition
Remove-AzPolicyDefinition -Id $definition

Copy and assign the deployIfNotExists definition

These steps create a copy of the deployIfNotExists definition and assign it to a resource group. This definition will not work correctly without the paired audit definition also being assigned.

# Create the policy definition (Subscription scope)
$definition = New-AzPolicyDefinition -Name 'guestconfig-installed-application-linux-deployIfNotExists' -DisplayName 'GuestConfig - Deploy VM extension to audit that an application is installed inside Linux VMs' -description 'Include this rule to deploy the VM extension for Microsoft Guest Configuration, the VM extension for Microsoft Azure Managed Service Identity, and the content required to audit that an application is installed inside Linux virtual machines. This policy should only be used along with its corresponding audit policy in an initiative/policy set.' -Policy 'https://raw.githubusercontent.com/Azure/azure-policy/master/samples/GuestConfiguration/installed-application-linux/deployIfNotExists/azurepolicy.rules.json' -Parameter 'https://raw.githubusercontent.com/Azure/azure-policy/master/samples/GuestConfiguration/installed-application-linux/deployIfNotExists/azurepolicy.parameters.json' -Mode All

# Set the scope to a resource group; may also be a resource, subscription, or management group
$scope = Get-AzResourceGroup -Name 'YourResourceGroup'

# Set the definition parameter (JSON format)
$policyParam  = '{ "applicationName": { "value": "python,powershell" } }'

# Create the policy assignment
$assignment = New-AzPolicyAssignment -Name 'guestconfig-installed-application-linux-deployIfNotExists-assignment' -DisplayName 'GuestConfig - Deploy VM extension to audit that Python and PowerShell are installed inside Linux VMs' -Scope $scope.ResourceID -PolicyDefinition $definition -PolicyParameter $policyParam -AssignIdentity -Location 'westus2'

# Get the system-assigned managed identity created by the assignment with -AssignIdentity
$saIdentity = $assignment.Identity.principalId

# Give the system-assigned managed identity the 'Contributor' role on the scope (needed by deployIfNotExists)
$roleAssignment = New-AzRoleAssignment -ObjectId $saIdentity -Scope $scope.ResourceId -RoleDefinitionName 'Contributor'

Run the following commands to remove the previous assignment and definition:

# Remove the policy assignment
Remove-AzPolicyAssignment -Id $assignment.ResourceId

# Remove the 'Contributor' role from the system-assigned managed identity
Remove-AzRoleAssignment -ObjectId $saIdentity -Scope $scope.ResourceId -RoleDefinitionName 'Contributor'

# Remove the policy definition
Remove-AzPolicyDefinition -Id $definition

Azure PowerShell explanation

The deploy and remove scripts use the following commands. Each command in the following table links to command-specific documentation:

Command Notes
New-AzPolicySetDefinition Creates an Azure Policy initiative.
New-AzPolicyDefinition Creates an Azure Policy definition.
Get-AzResourceGroup Gets a single resource group.
New-AzPolicyAssignment Creates a new Azure Policy assignment for an initiative or definition.
New-AzRoleAssignment Gives an existing role assignment to the specific principal.
Remove-AzPolicyAssignment Removes an existing Azure Policy assignment.
Remove-AzPolicySetDefinition Removes an initiative.
Remove-AzPolicyDefinition Removes a definition.

Next steps