Share via


Tag Azure Red Hat OpenShift resources using Azure Policy

This article shows you how to use Azure Policy to apply tags to the resources in an Azure Red Hat OpenShift cluster's managed resource group. You create three JSON files to create a policy definition and policy assignment at the subscription scope. You deploy a cluster that uses the policy's tags and use a policy remediation task to apply tags to cluster resources.

Prerequisites

Create JSON files

Use a text editor like Microsoft Visual Studio Code, to copy and paste the following code and create three JSON files in your current working directory. These files are used to create your policy definition and policy assignment.

Create rules file

Create the rules.json file.

{
  "if": {
    "anyOf": [
      {
        "allOf": [
          {
            "value": "[resourceGroup().name]",
            "equals": "[parameters('resourceGroupName')]"
          }
        ]
      },
      {
        "allOf": [
          {
            "field": "name",
            "equals": "[parameters('resourceGroupName')]"
          },
          {
            "field": "type",
            "equals": "Microsoft.Resources/subscriptions/resourceGroups"
          }
        ]
      }
    ]
  },
  "then": {
    "details": {
      "operations": [
        {
          "condition": "[not(equals(parameters('tag0')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag0')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag0')['tag'][1]]"
        },
        {
          "condition": "[not(equals(parameters('tag1')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag1')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag1')['tag'][1]]"
        },
        {
          "condition": "[not(equals(parameters('tag2')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag2')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag2')['tag'][1]]"
        },
        {
          "condition": "[not(equals(parameters('tag3')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag3')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag3')['tag'][1]]"
        },
        {
          "condition": "[not(equals(parameters('tag4')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag4')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag4')['tag'][1]]"
        },
        {
          "condition": "[not(equals(parameters('tag5')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag5')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag5')['tag'][1]]"
        },
        {
          "condition": "[not(equals(parameters('tag6')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag6')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag6')['tag'][1]]"
        },
        {
          "condition": "[not(equals(parameters('tag7')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag7')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag7')['tag'][1]]"
        },
        {
          "condition": "[not(equals(parameters('tag8')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag8')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag8')['tag'][1]]"
        },
        {
          "condition": "[not(equals(parameters('tag9')['tag'][0], ''))]",
          "field": "[concat('tags[', parameters('tag9')['tag'][0], ']')]",
          "operation": "addOrReplace",
          "value": "[parameters('tag9')['tag'][1]]"
        }
      ],
      "roleDefinitionIds": [
        "/providers/Microsoft.Authorization/roleDefinitions/4a9ae827-6dc8-4573-8ac7-8239d42aa03f"
      ]
    },
    "effect": "modify"
  }
}

Create parameter definitions

Create the param-defs.json file.

{
  "tag0": {
    "type": "Object",
    "metadata": {
      "displayName": "tag0"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "tag1": {
    "type": "Object",
    "metadata": {
      "displayName": "tag1"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "tag2": {
    "type": "Object",
    "metadata": {
      "displayName": "tag2"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "tag3": {
    "type": "Object",
    "metadata": {
      "displayName": "tag3"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "tag4": {
    "type": "Object",
    "metadata": {
      "displayName": "tag4"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "tag5": {
    "type": "Object",
    "metadata": {
      "displayName": "tag5"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "tag6": {
    "type": "Object",
    "metadata": {
      "displayName": "tag6"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "tag7": {
    "type": "Object",
    "metadata": {
      "displayName": "tag7"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "tag8": {
    "type": "Object",
    "metadata": {
      "displayName": "tag8"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "tag9": {
    "type": "Object",
    "metadata": {
      "displayName": "tag9"
    },
    "defaultValue": {
      "tag": [
        "",
        ""
      ]
    },
    "schema": {
      "type": "object",
      "properties": {
        "tag": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "maxItems": 2,
          "minItems": 2
        }
      }
    }
  },
  "resourceGroupName": {
    "type": "String",
    "metadata": {
      "displayName": "Resource Group Name",
      "description": "The name of the resource group whose resources you'd like to require the tag on"
    }
  }
}

Create the param-values.json file.

{
  "tag0": {
    "value": {
      "tag": [
        "<your tag key>",
        "<your tag value>"
      ]
    }
  },
  "resourceGroupName": {
    "value": "<your cluster's managed resource group name>"
  }
}

This param-values.json file is the only one of the three files that must be modified. In the content, specify the values for the tags you want applied to the cluster's resources. For this example, replace the following values:

  • <your tag key>: demoKey
  • <your tag value>: demoResourceGroupTag
  • <your cluster's managed resource group name>: demoMRG

The param-values.json file content only shows a value for the tag0 parameter. The policy allows up to 10 tags. To set more than one tag, add values for parameters tag1 through tag 9. Applying more than 10 tags to resources in the managed resource group isn't supported.

Set environment variables

Open a Bash shell, sign in to Azure, and create variables.

If you're using Azure CLI on your computer, from your Bash session, sign in to your Azure subscription. For more information, see Authenticate to Azure using Azure CLI.

az login

Create environment variables used in later steps. You can use the values provided or create your own values.

export AZURE_SUBSCRIPTION_ID=$(az account list --query [].id --output tsv)
export POLICY_DEFINITION=demoPolicyDefName
export CLUSTER=demoCluster
export MANAGED_RESOURCE_GROUP=demoMRG
export POLICY_ASSIGNMENT="${POLICY_DEFINITION}-${CLUSTER}"
export LOCATION=centralus
Variable name Description
AZURE_SUBSCRIPTION_ID The Azure subscription where resources are created. The command gets the ID from the Azure subscription you're signed into.
POLICY_DEFINITION The name of your policy definition to apply resource tags. For this example, demoPolicyDefName.
CLUSTER Your Azure Red Hat OpenShift cluster's name. For this example, demoCluster.
MANAGED_RESOURCE_GROUP The managed resource group that contains your cluster's resources. For this example, demoMRG.
POLICY_ASSIGNMENT Name created by joining the POLICY_DEFINITION and CLUSTER variable names.
LOCATION Region where the policy assignment's managed identity is created. For this example, centralus. For more information about the managed identity, see Configure the managed identity.

Create the policy definition and assignment

  1. To create the policy definition, run the following command.

    az policy definition create \
      --name $POLICY_DEFINITION \
      --mode All \
      --rules rules.json \
      --params param-defs.json
    
  2. To create the policy assignment, run the following command.

     az policy assignment create \
       --name $POLICY_ASSIGNMENT \
       --policy $POLICY_DEFINITION \
       --scope "/subscriptions/${AZURE_SUBSCRIPTION_ID}" \
       --location $LOCATION \
       --mi-system-assigned \
       --role "Tag Contributor" \
       --identity-scope "/subscriptions/${AZURE_SUBSCRIPTION_ID}" \
       --params param-values.json
    

Create the cluster

Follow the instructions in create a cluster. In your deployment command, az aro create, include the parameter --cluster-resource-group $MANAGED_RESOURCE_GROUP. The command should look like the following example.

az aro create \
  --resource-group $RESOURCEGROUP \
  --name $CLUSTER \
  --vnet $VIRTUALNETWORK \
  --master-subnet master-subnet \
  --worker-subnet worker-subnet \
  --version <x.y.z> \
  --cluster-resource-group $MANAGED_RESOURCE_GROUP

The policy doesn't apply any tags to resources in the cluster resource group. Tags are only applied to the resources in the managed resource group, in this example, demoMRG.

Remediate tags using Azure Policy

You can remediate previously assigned tags and add new tags using an Azure Policy remediation task. The demoMRG managed resource group and its resources have the tag demoKey: demoResourceTag.

Open the file param-values.json and modify existing parameters values and add new parameter values in the following example.

{
  "tag0": {
    "value": {
      "tag": [
        "demoKeyUpdate",
        "demoResourceGroupTagUpdate"
      ]
    }
  },
  "tag1": {
    "value": {
      "tag": [
        "demoKeyTag1",
        "demoResourceGroupTag1"
      ]
    }
  },
  "resourceGroupName": {
    "value": "demoMRG"
  }
}

When you run the commands to update the parameter values and run the remediation task, the policy applies the tags to resources in the managed resource group.

  1. Run the following command to update the policy assignment's parameter values.

    az policy assignment update \
      --name $POLICY_ASSIGNMENT \
      --params param-values.json
    
  2. Trigger the remediation task.

    az policy remediation create \
      --name demoRemediation \
      --resource-group $MANAGED_RESOURCE_GROUP \
      --policy-assignment $POLICY_ASSIGNMENT
    

    Allow the remediation task time to run and observe the tags being updated on the managed resource group and its resources. A remediation task doesn't remove tags from resources it only adds or updates tags.

Next steps