Enforce Tagging Policies (Azure & OCI)

Automate the enforcement of tagging policies across Azure and Oracle Cloud Infrastructure using PowerShell and Python scripts.

Spread the FinOps flavor!

Overview

Consistent resource tagging is crucial for effective cloud cost management, governance, and operations. These scripts provide a robust solution for enforcing tagging policies across both Azure and Oracle Cloud Infrastructure (OCI) environments.

The Azure script uses PowerShell and Azure Policy to enforce tags on Resource Groups, while the OCI script uses Python and OCI IAM Policies to enforce tags on Compartments and resources. Both scripts help ensure that newly created resources adhere to your organization's tagging standards.

Why Enforce Tagging?

Enforcing tagging policies helps you:

  • Accurately allocate costs to teams, projects, or environments
  • Automate resource management tasks (e.g., backups, shutdowns)
  • Improve security posture by identifying resource ownership
  • Meet compliance requirements

Key Features

Multi-Cloud Support

Provides dedicated scripts for both Azure (PowerShell) and OCI (Python) environments.

Policy Enforcement

Creates native cloud policies (Azure Policy, OCI IAM Policy) to deny creation of non-compliant resources.

Compliance Reporting

Generates reports on the compliance status of existing resources against the defined tagging policies.

Automated Remediation

Creates remediation scripts to help bring existing non-compliant resources into compliance.

Customizable Tags

Easily define the set of required tags for your organization's specific needs.

Dry Run Mode

Test the policy creation and assignment process without making any actual changes to your environment.

Azure PowerShell Script

The Azure script utilizes PowerShell and Azure Policy to enforce tagging on Resource Groups. It creates individual policies for each required tag, groups them into an initiative, and assigns it to the specified scope (Subscription, Resource Group, or Management Group).

Prerequisites

Ensure the following Azure PowerShell modules are installed:

Install-Module Az.Accounts -Force
Install-Module Az.Resources -Force
Install-Module Az.PolicyInsights -Force

Connect to your Azure account:

Connect-AzAccount

You need permissions to create and assign Azure Policy definitions (e.g., Resource Policy Contributor role).

Usage

Basic Usage (Default Tags: Environment, Owner, CostCenter, Project):

.\azure-tagging-policy.ps1

Specify Custom Required Tags:

.\azure-tagging-policy.ps1 -RequiredTags @("Environment", "Owner", "Department")

Apply to Specific Subscription:

.\azure-tagging-policy.ps1 -SubscriptionId "your-subscription-id"

Apply to Specific Resource Group Scope:

.\azure-tagging-policy.ps1 -PolicyAssignmentScope "resourcegroup" -ScopeId "my-resource-group"

Apply to Management Group:

.\azure-tagging-policy.ps1 -PolicyAssignmentScope "managementgroup" -ScopeId "my-mg-id"

Dry Run (See what would be created):

.\azure-tagging-policy.ps1 -DryRun

What It Creates

  1. Individual Policy Definitions: One policy per required tag (e.g., `require-rg-tag-environment`)
  2. Policy Set Definition (Initiative): Groups all tag policies together (e.g., `require-rg-tagging-initiative`)
  3. Policy Assignment: Assigns the initiative to your specified scope (e.g., `rg-tagging-assignment`)
  4. Compliance Report (Console): Shows current compliance status of resource groups in scope
  5. Remediation Script: PowerShell script to help fix non-compliant resource groups

Output Files

  • remediation-script.ps1: Script to add missing tags to existing non-compliant resource groups. Requires manual input for tag values.

OCI Python Script

The OCI script utilizes Python and OCI IAM Policies to enforce tagging on Compartments and optionally on specific resource types. It creates a dedicated tag namespace and keys for governance tags.

Prerequisites

Install the OCI Python SDK:

pip install oci

Set up your OCI configuration file (usually at ~/.oci/config) or use the OCI CLI setup:

oci setup config

You need permissions to manage tag namespaces, tag keys, and IAM policies in the target compartment (usually the tenancy root).

Usage

Basic Usage (Default Tags: Environment, Owner, CostCenter, Project):

python3 oci-tagging-policy.py

Specify Custom Required Tags:

python3 oci-tagging-policy.py --required-tags Environment Owner Department

Use Different OCI Profile:

python3 oci-tagging-policy.py --profile PRODUCTION

Use Custom Config File:

python3 oci-tagging-policy.py --config-file /path/to/config

Dry Run (See what would be created):

python3 oci-tagging-policy.py --dry-run

Target Specific Compartment (for policy creation/compliance check):

python3 oci-tagging-policy.py --compartment-id ocid1.compartment.oc1..example

Specify Tag Namespace:

python3 oci-tagging-policy.py --namespace "MyOrgGovernanceTags"

What It Creates

  1. Tag Namespace: Container for governance tags (e.g., `GovernanceTags`)
  2. Tag Keys: Individual required tag definitions within the namespace
  3. Compartment Tagging Policy: IAM policy preventing compartment creation without required tags
  4. Resource Tagging Policy (Optional): IAM policy preventing creation of specific resource types without required tags
  5. Compliance Report (JSON): Shows current compliance status of compartments
  6. Remediation Script: Python script to help fix non-compliant compartments

Output Files

  • oci_remediation_script.py: Script to add missing tags to existing non-compliant compartments. Requires manual input for tag values.
  • oci_tagging_policy_report.json: Detailed JSON report containing compliance status and details of created policies/tags.

Share This Guide

If this recipe hit the spot, pass it along to your cloud crew and the wider kitchen!

Compliance Monitoring

Regularly monitor the compliance status of your resources against the enforced tagging policies.

Azure Compliance

Use Azure Policy insights to check compliance:

# Check policy compliance state for tagging policies
Get-AzPolicyState -SubscriptionId "your-subscription-id" |  
    Where-Object {$_.PolicyDefinitionName -like "*require-rg-tag*"} |  
    Select-Object ResourceId, ComplianceState, PolicyDefinitionName

# Get overall compliance summary for the subscription
Get-AzPolicyStateSummary -SubscriptionId "your-subscription-id"

You can also view compliance status in the Azure Portal under Policy > Compliance.

OCI Compliance

Re-run the OCI Python script in dry-run mode to get an updated compliance report:

# Re-run compliance check for the tenancy
python3 oci-tagging-policy.py --dry-run

# Check compliance for a specific compartment
python3 oci-tagging-policy.py --compartment-id ocid1.compartment.oc1..example --dry-run

Review the generated oci_tagging_policy_report.json file for detailed compliance status.

Remediation

Both scripts generate remediation scripts to help you bring existing non-compliant resources into compliance.

Manual Review Required

The generated remediation scripts require manual review and input. You need to provide the correct tag values for each non-compliant resource before running the scripts.

Azure Remediation

Edit the generated remediation-script.ps1 file, replace 'REPLACE_WITH_VALUE' placeholders with actual tag values, and then run the script:

.\remediation-script.ps1

Alternatively, manually add tags to resource groups using the Azure Portal or PowerShell:

Set-AzResourceGroup -Name "my-rg" -Tag @{
    "Environment" = "Production"
    "Owner" = "john.doe@company.com"
    "CostCenter" = "IT-001"
    "Project" = "WebApp"
}

OCI Remediation

Edit the generated oci_remediation_script.py file, replace placeholders with actual tag values, and then run the script:

python3 oci_remediation_script.py

Alternatively, manually add tags to compartments using the OCI Console or OCI CLI:

oci iam compartment update  
    --compartment-id ocid1.compartment.oc1..example  
    --defined-tags '{"GovernanceTags":{"Environment":"Production","Owner":"john.doe"}}'

Testing Your Policies

After applying the policies, test them by attempting to create resources without the required tags. The creation should be denied.

Azure Testing

Attempt to create a resource group without required tags (should fail):

New-AzResourceGroup -Name "test-rg-no-tags" -Location "East US"

Create a resource group with required tags (should succeed):

New-AzResourceGroup -Name "test-rg-with-tags" -Location "East US" -Tag @{
    "Environment" = "Test"
    "Owner" = "admin@company.com"
    "CostCenter" = "IT-001"
    "Project" = "Testing"
}

OCI Testing

Attempt to create a compartment without required tags (should fail):

oci iam compartment create  
    --compartment-id ocid1.tenancy.oc1..example  
    --name "test-compartment-no-tags"  
    --description "Test compartment without tags"

Create a compartment with required tags (should succeed):

oci iam compartment create  
    --compartment-id ocid1.tenancy.oc1..example  
    --name "test-compartment-with-tags"  
    --description "Test compartment with tags"  
    --defined-tags '{"GovernanceTags":{"Environment":"Test","Owner":"admin"}}'

Best Practices

Tag Strategy

  1. Keep it simple: Start with 3-5 essential tags (e.g., Environment, Owner, CostCenter, Project).
  2. Be consistent: Use the same tag names and casing across Azure and OCI where possible.
  3. Document values: Maintain a list of acceptable tag values for each key.
  4. Regular reviews: Review and update your tagging strategy quarterly or as needed.

Recommended Tags:

  • Environment: Production, Staging, Development, Test, QA, Sandbox
  • Owner: Email address or team alias of the responsible party
  • CostCenter: Department or cost center code for financial tracking
  • Project: Name of the project the resource belongs to
  • Application: Name of the application or service the resource supports
  • DataClassification: Sensitivity level of the data (e.g., Public, Internal, Confidential, Restricted)

Governance

  1. Start small: Begin enforcement in development or test environments.
  2. Gradual rollout: Apply policies to production environments after thorough testing and communication.
  3. Monitor compliance: Set up regular compliance reporting and alerts.
  4. Automate remediation: Integrate remediation scripts into regular maintenance processes.
  5. Train teams: Ensure all cloud users understand the tagging requirements and processes.

Troubleshooting

Common Azure Issues

  • Permission errors: Ensure the account running the script has the necessary roles (e.g., Resource Policy Contributor, Owner) at the target scope.
  • Policy conflicts: Check for existing Azure policies that might conflict with the tagging policies.
  • Assignment scope errors: Verify the `-PolicyAssignmentScope` and `-ScopeId` parameters are correct for your target.
  • Policy definition not found: Ensure the script successfully created the policy definitions before attempting assignment.

Common OCI Issues

  • Authentication errors: Verify your OCI config file (~/.oci/config) is correct and the specified profile exists. Check API key validity.
  • Permission errors: Ensure the user has permissions to manage IAM policies, tag namespaces, and tag keys in the root compartment or target compartment.
  • Tenancy/Compartment access: Confirm the user has access to the target compartments for policy creation and compliance checks.
  • Namespace conflicts: If using a custom namespace, ensure it doesn't conflict with existing namespaces.

Getting Help

  • Azure: Use Get-Help with PowerShell cmdlets (e.g., Get-Help New-AzPolicyDefinition -Full). Check Azure documentation for Azure Policy.
  • OCI: Refer to the OCI Python SDK documentation and OCI IAM policy documentation. Check script error messages for details.
  • Both: Enable verbose logging or add print statements to the scripts for more detailed error information.

Share This Guide

If this recipe hit the spot, pass it along to your cloud crew and the wider kitchen!

Was this documentation helpful?

Have suggestions for improving this document? Contact us.