Skip to content

give me examples of business, technical and operational requirements for setting up basic finops capabiliry in a greenfield Azure implementation

We need to provide examples of business, technical, and operational requirements for setting up a basic FinOps capability in a greenfield Azure implementation. The context is a new Azure environment with no existing cloud usage. FinOps (Cloud Financial Management) aims to manage and optimize cloud costs. So we need to define what requirements would be needed to establish a basic FinOps practice. We should categorize them into business, technical, and operational requirements.

  • Business requirements: High-level goals from business perspective, like cost visibility, budgeting, accountability, etc.
  • Technical requirements: Specific Azure services, tools, configurations needed to enable cost management, tagging, monitoring, etc.
  • Operational requirements: Processes, roles, workflows for ongoing cost management, optimization, reporting.

Let’s outline examples for each.

We can think of a basic FinOps capability as including:

  • Cost allocation (tagging, resource organization)
  • Budgeting and alerts
  • Cost reporting and visualization
  • Optimization (right-sizing, reserved instances, etc.)
  • Governance and policies

We need to be specific to Azure: Azure Cost Management, Azure Policy, Azure budgets, Azure Advisor, Azure Resource Graph, tagging, management groups, subscriptions, etc.

We should also consider that it’s greenfield, so we have opportunity to set things up correctly from start.

We’ll provide a list of examples for each category.

Here are examples of business, technical, and operational requirements to establish a basic FinOps capability in a new (greenfield) Azure implementation.

Business Requirements

These define the goals and value expectations from a financial management perspective.

#

Requirement

Description

1

Cost Visibility

Provide business stakeholders with clear, timely visibility into Azure spending, broken down by department, project, or application.

2

Budgetary Control

Establish monthly/quarterly budgets for each cost center and receive alerts when spending approaches or exceeds thresholds.

3

Showback/Chargeback

Enable allocation of cloud costs to the appropriate internal teams or customers for accountability and financial transparency.

4

Forecasting Accuracy

Maintain a process to forecast future cloud spend based on historical trends and planned changes, with variance reporting.

5

Optimization Targets

Set periodic goals for reducing waste (e.g., idle resources, oversized services) and increasing usage of committed use discounts.

6

Governance Alignment

Ensure cloud spending aligns with corporate financial policies, procurement rules, and compliance requirements.

7

Cross‑functional Collaboration

Foster collaboration between finance, engineering, and operations to balance cost, performance, and innovation.

Technical Requirements

These specify the Azure services, configurations, and tools needed to enable cost management.

#

Requirement

Description

1

Resource Hierarchy

Design an Azure management group and subscription structure that mirrors the organization (e.g., by business unit, environment, application) to enable logical cost aggregation.

2

Tagging Strategy

Define and enforce a mandatory set of resource tags (e.g., CostCenter, Owner, Environment, Project) to allow cost allocation and filtering in reports.

3

Azure Policy for Tags

Implement Azure Policy rules that require specific tags at resource creation and optionally inherit missing tags from resource groups.

4

Cost Management + Billing

Enable and configure Azure Cost Management, including access to billing data, cost views, and budgets for all subscriptions.

5

Budgets and Alerts

Create budgets at management group, subscription, or resource group scope with email and action group alerts for threshold breaches.

6

Advisor Integration

Enable Azure Advisor to generate cost recommendations (e.g., right‑sizing, reserved instance purchases) and integrate them into regular reviews.

7

Workbook/Dashboard

Build custom Azure workbooks or dashboards in Azure Monitor that display key FinOps metrics (spend by tag, forecast, top resources) for different audiences.

8

Reserved Instance Planning

Configure Azure to provide reserved instance recommendations and track coverage percentage.

9

Access Control

Use Azure RBAC to grant appropriate permissions (e.g., Cost Management Reader) to finance and engineering teams without giving full billing access.

10

Automated Remediation

(Optional) Set up automation (e.g., Azure Functions, Logic Apps) to stop or deallocate underutilized resources based on tags or schedules.

Operational Requirements

These define the people, processes, and workflows to sustain and mature the FinOps practice.

#

Requirement

Description

1

FinOps Roles & Responsibilities

Assign a cloud financial manager (or center of excellence) and designate cost owners for each business unit / application.

2

Cost Review Cadence

Hold recurring (e.g., weekly or bi‑weekly) cost reviews with engineers and finance to analyze anomalies, discuss optimization, and track progress.

3

Tagging Governance

Establish a process to validate tag compliance regularly and remediate untagged or incorrectly tagged resources.

4

Budget Management Workflow

Define how new budgets are requested, approved, and updated; link budget changes to project planning.

5

Optimization Lifecycle

Create a process to:
• Identify waste using Azure Advisor and Cost Management
• Triage recommendations (apply, dismiss, schedule)
• Track implemented savings.

6

Anomaly Detection Process

Set up procedures to investigate unexpected cost spikes – including root cause analysis and corrective action documentation.

7

Reserved Instance Strategy

Establish a quarterly review of RI/ savings plan coverage, purchase approvals, and commitment alignment with projected usage.

8

Reporting & Communication

Publish a monthly FinOps report to stakeholders summarizing spend vs. budget, savings achieved, and forecasts.

9

Training & Enablement

Provide basic FinOps and Azure cost management training to engineers, emphasising cost‑aware design and tagging discipline.

10

Tooling Evolution

Periodically assess whether native Azure tools suffice or if third‑party FinOps platforms are needed as the environment grows.

These requirements can be adapted based on the organization’s size, culture, and maturity goals. Starting with a greenfield Azure environment allows these FinOps fundamentals to be embedded from day one, preventing costly waste and ensuring financial accountability scales with the cloud footprint.

Azure FinOps Tag Enforcement Policy
 
 
 
 
show me how to enforce Azure mandatory tags and allowed values for FinOps Azure Policy Implementation. The mandatory tags are: Cost Centre, Environment, Owber, ApplicationID
 
 
 
 
 
 
 
 
 
Read 9 web pages
 

Hmm, the user is asking for a practical implementation guide to enforce specific mandatory tags (Cost Centre, Environment, Owber, ApplicationID) with allowed values using Azure Policy for FinOps purposes. The question appears technical and implementation-focused, likely from a cloud architect, FinOps practitioner, or Azure administrator setting up governance.

I’ll structure my answer to cover both the Azure Policy implementation approach and how it fits into the broader FinOps framework. The response should include actual policy code, best practices for enforcement, and considerations for rollout.

Looking at the search results, I find several highly relevant sources. The Microsoft FinOps Toolkit documentation  provides excellent guidance on cloud policy and governance as part of the FinOps Framework, emphasizing the importance of tagging for allocation, chargeback, and workload management. Another Microsoft Learn article  reinforces these concepts with similar authoritative weight.

For the actual policy implementation, a Microsoft Q&A thread  contains a working policy definition that enforces a tag with predefined allowed values, using the in operator with an array parameter. This is directly applicable to the user’s requirement. A community hub post  shows PowerShell automation for FinOps tagging enforcement, demonstrating practical deployment methods.

The KodeKloud notes  provide an excellent tutorial on grouping multiple tagging policies into an initiative, which is exactly what the user needs for managing four tags together. The step-by-step approach for assignment and testing is valuable.

Some search results are less useful. The Infracost glossary  provides general information but lacks the specific implementation details needed. The Valorem Reply blog  discusses tagging concepts but focuses more on cost reporting architecture than policy enforcement.

I’ll recommend the initiative approach since managing four separate policies would be cumbersome. The policy rule structure from  can be adapted with multiple allOf conditions. For allowed values, I’ll suggest parameterizing them for flexibility. I’ll also include PowerShell automation from  and guidance on using deny versus audit effects from . The rollout strategy of starting with audit before enforce is sound advice.

The response will combine the authoritative Microsoft sources for FinOps context  with practical implementation examples  to give the user a complete solution from strategy to code to deployment.

 

Enforcing a tagging strategy with allowed values is a foundational step in any FinOps practice, enabling accurate cost allocation and showback/chargeback models . To enforce your specific tags—Cost Centre, Environment, Owner, and ApplicationID—you have two primary approaches: creating individual policies or a single, combined initiative.

For ease of management and to ensure consistent enforcement, it is best practice to group these related tags into a single Policy Initiative (also known as a Policy Set) . This allows you to assign one package to your management group or subscription rather than managing four separate assignments.

Here is the JSON code for a custom Azure Policy Initiative that enforces these four tags with their respective allowed values.

Azure Policy Initiative: Enforce FinOps Mandatory Tags

This initiative combines four individual policy definitions. Each policy rule checks for the existence of a specific tag and validates its value against a predefined list. If a resource is missing a required tag or has a non-approved value, the deployment is blocked ("effect": "deny") .

json
{
    "properties": {
        "displayName": "FinOps Enforce Mandatory Tags with Allowed Values",
        "policyType": "Custom",
        "description": "Policy initiative to enforce the mandatory tags: Cost Centre, Environment, Owner, and ApplicationID with their allowed values for FinOps cost tracking.",
        "metadata": {
            "version": "1.0.0",
            "category": "Tags"
        },
        "parameters": {
            "costCentreAllowedValues": {
                "type": "Array",
                "metadata": {
                    "displayName": "Allowed values for Cost Centre",
                    "description": "List of allowed Cost Centre codes, e.g., Marketing, R&D, Sales."
                },
                "allowedValues": [
                    "Marketing",
                    "R&D",
                    "Sales",
                    "IT",
                    "Finance"
                ]
            },
            "environmentAllowedValues": {
                "type": "Array",
                "metadata": {
                    "displayName": "Allowed values for Environment",
                    "description": "List of allowed Environment types, e.g., Prod, Dev, Test."
                },
                "allowedValues": [
                    "Prod",
                    "Dev",
                    "Test",
                    "UAT",
                    "DR"
                ]
            },
            "ownerAllowedValues": {
                "type": "Array",
                "metadata": {
                    "displayName": "Allowed values for Owner",
                    "description": "List of allowed Owner team names or email aliases."
                },
                "allowedValues": [
                    "TeamAlpha",
                    "TeamBeta",
                    "PlatformTeam",
                    "DataTeam"
                ]
            },
            "applicationIdAllowedValues": {
                "type": "Array",
                "metadata": {
                    "displayName": "Allowed values for ApplicationID",
                    "description": "List of allowed Application IDs."
                },
                "allowedValues": [
                    "ERP-SAP",
                    "CRM-Dynamics",
                    "Web-App",
                    "Data-Lake"
                ]
            }
        },
        "policyDefinitions": [
            {
                "policyDefinitionReferenceId": "EnforceCostCentreTag",
                "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/your-policy-definition-id-for-tag-enforcement",
                "parameters": {
                    "tagName": {
                        "value": "Cost Centre"
                    },
                    "allowedTagValues": {
                        "value": "[parameters('costCentreAllowedValues')]"
                    }
                },
                "groupNames": []
            },
            {
                "policyDefinitionReferenceId": "EnforceEnvironmentTag",
                "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/your-policy-definition-id-for-tag-enforcement",
                "parameters": {
                    "tagName": {
                        "value": "Environment"
                    },
                    "allowedTagValues": {
                        "value": "[parameters('environmentAllowedValues')]"
                    }
                },
                "groupNames": []
            },
            {
                "policyDefinitionReferenceId": "EnforceOwnerTag",
                "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/your-policy-definition-id-for-tag-enforcement",
                "parameters": {
                    "tagName": {
                        "value": "Owner"
                    },
                    "allowedTagValues": {
                        "value": "[parameters('ownerAllowedValues')]"
                    }
                },
                "groupNames": []
            },
            {
                "policyDefinitionReferenceId": "EnforceApplicationIDTag",
                "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/your-policy-definition-id-for-tag-enforcement",
                "parameters": {
                    "tagName": {
                        "value": "ApplicationID"
                    },
                    "allowedTagValues": {
                        "value": "[parameters('applicationIdAllowedValues')]"
                    }
                },
                "groupNames": []
            }
        ]
    }
}

Note: You will need to replace "/providers/Microsoft.Authorization/policyDefinitions/your-policy-definition-id-for-tag-enforcement" with the actual Resource ID of a core “Require tag and its value” policy. You can use a built-in one or the custom definition shown below.

Underlying Policy Definition: Require Tag and Its Value

The initiative above references a standard policy definition. If you don’t have one, here is the custom JSON for the underlying policy that performs the actual check and denial .

json
{
    "properties": {
        "displayName": "Require a specific tag and its value on resources",
        "policyType": "Custom",
        "mode": "Indexed",
        "description": "Enforces a required tag and its value. Does not apply to resource groups.",
        "metadata": {
            "version": "1.0.0",
            "category": "Tags"
        },
        "parameters": {
            "tagName": {
                "type": "String",
                "metadata": {
                    "displayName": "Tag Name",
                    "description": "Name of the tag, such as 'Cost Centre'."
                }
            },
            "allowedTagValues": {
                "type": "Array",
                "metadata": {
                    "displayName": "Allowed Tag Values",
                    "description": "The list of allowed values for the tag."
                }
            }
        },
        "policyRule": {
            "if": {
                "not": {
                    "field": "[concat('tags[', parameters('tagName'), ']')]",
                    "in": "[parameters('allowedTagValues')]"
                }
            },
            "then": {
                "effect": "deny"
            }
        }
    }
}

Implementation and FinOps Best Practices

Once you have defined your Initiative, you need to assign it to the desired scope (e.g., a Management Group or Subscription) and integrate it into your FinOps workflow.

  1. Define Allowed Values via Parameters: When assigning the initiative, you will be prompted to fill in the parameters. This is where you define the specific allowedValues for your organization, such as your specific Cost Centre codes or Environment types. Using parameters makes the policy reusable across different departments or subscriptions without editing the core JSON .

  2. Start with Audit Before Deny: To avoid disrupting existing workflows, it is highly recommended to start with an Audit effect. This will report on non-compliant resources without blocking them. Once you are confident in your tagging strategy and have communicated with your teams, you can switch the effect to Deny by modifying the underlying policy definition .

  3. Combine with Inheritance Policies: For a more robust FinOps implementation, consider adding another policy to your initiative that inherits tags from the resource group to the resources within it. This reduces the burden on developers and ensures that all resources created in a properly tagged resource group are automatically compliant .

  4. Automate Deployment: Deploy your policy initiative using Infrastructure as Code (IaC) tools like Bicep, ARM templates, or Terraform, and integrate it into your CI/CD pipelines (e.g., using Azure DevOps or GitHub Actions) .

Summary of Tags for FinOps

 
 
Tag NameFinOps PurposeExample Allowed Values
Cost CentreAllocates costs to the correct department or business unit for chargeback/showback .MarketingR&DITFinance
EnvironmentIdentifies the workload stage for cost optimization (e.g., turning off non-prod resources) .ProdDevTestUATDR
OwnerIdentifies the team or individual responsible for the resource for cost investigation and anomaly alerts .TeamAlphaTeamBetaPlatformTeam
ApplicationIDGroups resources belonging to a specific application for granular cost analysis and reporting .ERP-SAPCRM-DynamicsWeb-App
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
show the above again using bicep codes instead of json
 
 
 
 
 
 
 
 
 

We need to provide Bicep code to enforce Azure mandatory tags (Cost Centre, Environment, Owner, ApplicationID) with allowed values, as part of a FinOps policy implementation. The user wants Bicep instead of JSON. We should provide Bicep modules or resources that define custom policy definitions and a policy initiative (set). The Bicep should be deployable.

We’ll structure the answer:

  • Explanation of approach: using Bicep to create custom policy definitions and a policy set definition (initiative). Include parameters for allowed values.

  • Provide Bicep code:

    • Define a reusable policy definition for “require tag and allowed values” (like the JSON earlier) as a Bicep module or resource.

    • Then define the policy set (initiative) that includes four instances of that definition, each with parameters for tag name and allowed values.

    • The allowed values can be passed as parameters to the Bicep deployment.

  • Show assignment if needed, but maybe just the definition.

  • Mention deployment commands and considerations.

We need to ensure the Bicep is correct: using Microsoft.Authorization/policyDefinitions and Microsoft.Authorization/policySetDefinitions.

We’ll also include metadata, parameters, and policy rule.

Let’s craft the Bicep.

We might need to handle the policy definition ID reference in the initiative. In Bicep, we can use existing or reference the resource by symbolic name. We’ll create the policy definition resource and then reference it in the policy set using its id. We’ll have to use resource declarations.

Plan:

  • param for allowed values for each tag (arrays).

  • resource for policyDefinition: e.g., requireTagAndValuePolicy of type Microsoft.Authorization/policyDefinitions.

  • resource for policySetDefinition: type Microsoft.Authorization/policySetDefinitions, with policyDefinitions property containing an array of objects referencing the policy definition ID and parameters.

We need to ensure the policy definition ID is correctly formed: usually subscription(/subscriptions/{subscriptionId})/providers/Microsoft.Authorization/policyDefinitions/{name}. In Bicep, we can use requireTagAndValuePolicy.id.

We’ll also handle the policy rule expression with concat and field.

We’ll output the policy set definition ID if needed.

Let’s write the Bicep.

We might also provide an example of assignment, but the user asked to “enforce” which likely means creating the definition and initiative, then they can assign. We’ll show the initiative creation.

We should also mention that they need to deploy to a subscription or management group. Probably subscription scope.

Let’s write the code.

 

Below is a Bicep template that creates a custom Azure Policy Initiative (set) to enforce your mandatory tags Cost CentreEnvironmentOwner, and ApplicationID with allowed values. The template defines:

  • One reusable policy definition for enforcing a tag with allowed values.

  • A policy set definition that references this policy four times, once per tag, with tag‑specific allowed values passed as parameters.

You can deploy this Bicep file to a subscription (or management group) to establish the foundation for your FinOps tagging governance.

bicep
// Parameters: Allowed values for each mandatory tag
@description('List of allowed values for Cost Centre tag, e.g. [ "Marketing", "R&D", "Sales", "IT", "Finance" ]')
param costCentreAllowedValues array
@description('List of allowed values for Environment tag, e.g. [ "Prod", "Dev", "Test", "UAT", "DR" ]')
param environmentAllowedValues array
@description('List of allowed values for Owner tag, e.g. [ "TeamAlpha", "TeamBeta", "PlatformTeam", "DataTeam" ]')
param ownerAllowedValues array
@description('List of allowed values for ApplicationID tag, e.g. [ "ERP-SAP", "CRM-Dynamics", "Web-App", "Data-Lake" ]')
param applicationIdAllowedValues array
// Custom policy definition: Require a specific tag and its value
resource requireTagAndValuePolicy 'Microsoft.Authorization/policyDefinitions@2021-06-01' = {
  name: 'require-tag-and-value'
  properties: {
    displayName: 'Require a specific tag and its value on resources'
    policyType: 'Custom'
    mode: 'Indexed'   // Evaluates resource types that support tags
    description: 'Denies creation or update of a resource if it does not have the specified tag with a value from the allowed list.'
    metadata: {
      version: '1.0.0'
      category: 'Tags'
    }
    parameters: {
      tagName: {
        type: 'String'
        metadata: {
          displayName: 'Tag Name'
          description: 'Name of the tag, such as Cost Centre'
        }
      }
      allowedTagValues: {
        type: 'Array'
        metadata: {
          displayName: 'Allowed Tag Values'
          description: 'List of allowed values for the tag'
        }
      }
    }
    policyRule: {
      if: {
        not: {
          field: '[concat(\'tags[\', parameters(\'tagName\'), \']\')]'
          in: '[parameters(\'allowedTagValues\')]'
        }
      }
      then: {
        effect: 'deny'
      }
    }
  }
}
// Policy set (initiative) that includes the four mandatory tags
resource finOpsTagInitiative 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = {
  name: 'finops-enforce-mandatory-tags'
  properties: {
    displayName: 'FinOps Enforce Mandatory Tags with Allowed Values'
    description: 'Enforces the presence and allowed values of Cost Centre, Environment, Owner, and ApplicationID tags.'
    policyType: 'Custom'
    metadata: {
      version: '1.0.0'
      category: 'Tags'
    }
    parameters: {
      costCentreAllowedValues: {
        type: 'Array'
        metadata: {
          displayName: 'Allowed values for Cost Centre'
          description: 'List of allowed Cost Centre codes'
        }
      }
      environmentAllowedValues: {
        type: 'Array'
        metadata: {
          displayName: 'Allowed values for Environment'
          description: 'List of allowed Environment types'
        }
      }
      ownerAllowedValues: {
        type: 'Array'
        metadata: {
          displayName: 'Allowed values for Owner'
          description: 'List of allowed Owner team names'
        }
      }
      applicationIdAllowedValues: {
        type: 'Array'
        metadata: {
          displayName: 'Allowed values for ApplicationID'
          description: 'List of allowed Application IDs'
        }
      }
    }
    policyDefinitions: [
      {
        policyDefinitionId: requireTagAndValuePolicy.id
        parameters: {
          tagName: {
            value: 'Cost Centre'
          }
          allowedTagValues: {
            value: '[parameters(\'costCentreAllowedValues\')]'
          }
        }
      }
      {
        policyDefinitionId: requireTagAndValuePolicy.id
        parameters: {
          tagName: {
            value: 'Environment'
          }
          allowedTagValues: {
            value: '[parameters(\'environmentAllowedValues\')]'
          }
        }
      }
      {
        policyDefinitionId: requireTagAndValuePolicy.id
        parameters: {
          tagName: {
            value: 'Owner'
          }
          allowedTagValues: {
            value: '[parameters(\'ownerAllowedValues\')]'
          }
        }
      }
      {
        policyDefinitionId: requireTagAndValuePolicy.id
        parameters: {
          tagName: {
            value: 'ApplicationID'
          }
          allowedTagValues: {
            value: '[parameters(\'applicationIdAllowedValues\')]'
          }
        }
      }
    ]
  }
}

Deployment Instructions

  1. Save the code to a file, e.g., finops-tag-policy.bicep.

  2. Prepare a parameters file (optional) or pass values directly. Example parameters file (finops-tag-policy.parameters.json):

    json
    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "costCentreAllowedValues": { "value": [ "Marketing", "R&D", "Sales", "IT", "Finance" ] },
        "environmentAllowedValues": { "value": [ "Prod", "Dev", "Test", "UAT", "DR" ] },
        "ownerAllowedValues": { "value": [ "TeamAlpha", "TeamBeta", "PlatformTeam", "DataTeam" ] },
        "applicationIdAllowedValues": { "value": [ "ERP-SAP", "CRM-Dynamics", "Web-App", "Data-Lake" ] }
      }
    }
  3. Deploy to a subscription (or management group) using Azure CLI or PowerShell:

    Azure CLI (subscription scope):

    bash
    az deployment sub create \
      --name enforceFinOpsTags \
      --location westus \
      --template-file finops-tag-policy.bicep \
      --parameters @finops-tag-policy.parameters.json

    PowerShell:

    powershell
    New-AzSubscriptionDeployment `
      -Name enforceFinOpsTags `
      -Location westus `
      -TemplateFile finops-tag-policy.bicep `
      -TemplateParameterFile finops-tag-policy.parameters.json

    For management group scope, use az deployment mg create or New-AzManagementGroupDeployment and adjust the scope.

Next Steps

  • Assign the Initiative – After deployment, navigate to Azure Policy, find the initiative named FinOps Enforce Mandatory Tags with Allowed Values, and assign it to the desired scope (management group, subscription, or resource group). During assignment, you can again specify the allowed values (they will default to the ones provided during definition).

  • Consider audit‑first – If you are unsure about the impact, modify the underlying policy definition’s effect from deny to audit before deploying. You can do this by changing the then.effect in requireTagAndValuePolicy to 'audit'. After confirming no unexpected non‑compliant resources, change it back to deny.

  • Combine with inheritance – To reduce manual tagging effort, add another policy that copies tags from the resource group to resources. This can be added as an extra definition inside the same initiative.

This Bicep template gives you a reusable, code‑first approach to enforce your FinOps tagging strategy consistently across your Azure environment.

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
for the examples above show how tags can be inherited from resource groups
 
 
 
 
 
 
 
 
 

We need to show how tags can be inherited from resource groups, complementing the previous enforcement policies. The user wants to see examples of inheritance, likely as part of the FinOps tagging strategy. We should provide Bicep code that adds a policy to inherit tags from the resource group. This can be a separate policy definition within the same initiative or a separate initiative.

We’ll explain the concept: using a policy with “modify” effect to add tags from the resource group to resources that are missing them. But careful: inheritance can be done with “modify” or “deployIfNotExists”. For tags, a common built-in policy is “Inherit a tag from the resource group” which uses modify effect to add the tag if missing. We can either reference the built-in definition or create a custom one.

The user wants to see examples, so we’ll provide Bicep code for adding such a policy to the initiative. Since the previous Bicep already defined an initiative, we can extend it to include a policy for tag inheritance.

We need to show how tags can be inherited from resource groups. We’ll create a separate policy definition for inheritance (or use built-in) and add it to the initiative. We’ll also discuss parameters for tag name.

We’ll provide an updated Bicep that includes the inheritance policy. But the user might want just an example, not necessarily merging with previous. We can show both.

We’ll also mention that inheritance can be used to reduce manual tagging effort, ensuring that resources automatically get the resource group’s tags. This is common in FinOps to ensure consistent tagging without burdening developers.

Let’s structure the response:

  • Introduction: Tag inheritance helps propagate tags from resource groups to resources.

  • Show a policy definition for inheritance (modify effect).

  • Show how to add it to the initiative (or as a separate assignment).

  • Provide Bicep code snippet.

  • Explain parameters and usage.

  • Mention caution: inheritance policies typically only add tags if missing, not overwrite existing ones.

  • Combine with enforcement policies to ensure all resources have required tags.

We’ll keep it concise but informative.

 

To complement the enforcement of mandatory tags, you can implement tag inheritance from resource groups. This ensures that any resource created in a properly tagged resource group automatically receives the required tags, reducing manual effort and preventing compliance gaps.

Below is a Bicep example that adds a tag‑inheritance policy to the previously created initiative. The policy uses the modify effect to copy a specified tag from the resource group to the resource if the resource does not already have that tag.

Updated Bicep Initiative with Tag Inheritance

This Bicep template extends the earlier initiative by including a built‑in policy definition for tag inheritance. The built‑in policy ID is:

/providers/Microsoft.Authorization/policyDefinitions/cd3aa116-8754-49c9-a813-ad46512ece54

If you prefer to define a custom inheritance policy, an example is also provided.

bicep
// Parameters (same as before)
param costCentreAllowedValues array
param environmentAllowedValues array
param ownerAllowedValues array
param applicationIdAllowedValues array
// Optional: parameter to specify which tag to inherit (if using a custom inheritance policy)
param inheritTagName string = 'Environment'  // Example: inherit Environment tag
// Reference to the built‑in policy for inheriting a tag from the resource group
resource builtInInheritTagPolicy 'Microsoft.Authorization/policyDefinitions@2021-06-01' existing = {
  name: 'cd3aa116-8754-49c9-a813-ad46512ece54'
}
// Custom policy definition: Require a specific tag and its value (same as before)
resource requireTagAndValuePolicy 'Microsoft.Authorization/policyDefinitions@2021-06-01' = {
  name: 'require-tag-and-value'
  properties: {
    displayName: 'Require a specific tag and its value on resources'
    policyType: 'Custom'
    mode: 'Indexed'
    description: 'Denies creation or update of a resource if it does not have the specified tag with a value from the allowed list.'
    metadata: { version: '1.0.0', category: 'Tags' }
    parameters: {
      tagName: { type: 'String', metadata: { displayName: 'Tag Name' } }
      allowedTagValues: { type: 'Array', metadata: { displayName: 'Allowed Tag Values' } }
    }
    policyRule: {
      if: { not: { field: '[concat(\'tags[\', parameters(\'tagName\'), \']\')]', in: '[parameters(\'allowedTagValues\')]' } }
      then: { effect: 'deny' }
    }
  }
}
// Policy set (initiative) with both enforcement and inheritance
resource finOpsTagInitiative 'Microsoft.Authorization/policySetDefinitions@2021-06-01' = {
  name: 'finops-enforce-mandatory-tags'
  properties: {
    displayName: 'FinOps Enforce Mandatory Tags with Allowed Values'
    description: 'Enforces mandatory tags (Cost Centre, Environment, Owner, ApplicationID) and inherits a tag from the resource group.'
    policyType: 'Custom'
    metadata: { version: '1.0.0', category: 'Tags' }
    parameters: {
      costCentreAllowedValues: { type: 'Array', metadata: { displayName: 'Allowed values for Cost Centre' } }
      environmentAllowedValues: { type: 'Array', metadata: { displayName: 'Allowed values for Environment' } }
      ownerAllowedValues: { type: 'Array', metadata: { displayName: 'Allowed values for Owner' } }
      applicationIdAllowedValues: { type: 'Array', metadata: { displayName: 'Allowed values for ApplicationID' } }
    }
    policyDefinitions: [
      // Four enforcement policies (same as before)
      {
        policyDefinitionId: requireTagAndValuePolicy.id
        parameters: { tagName: { value: 'Cost Centre' }, allowedTagValues: { value: '[parameters(\'costCentreAllowedValues\')]' } }
      }
      {
        policyDefinitionId: requireTagAndValuePolicy.id
        parameters: { tagName: { value: 'Environment' }, allowedTagValues: { value: '[parameters(\'environmentAllowedValues\')]' } }
      }
      {
        policyDefinitionId: requireTagAndValuePolicy.id
        parameters: { tagName: { value: 'Owner' }, allowedTagValues: { value: '[parameters(\'ownerAllowedValues\')]' } }
      }
      {
        policyDefinitionId: requireTagAndValuePolicy.id
        parameters: { tagName: { value: 'ApplicationID' }, allowedTagValues: { value: '[parameters(\'applicationIdAllowedValues\')]' } }
      }
      // Add inheritance policy (using built‑in)
      {
        policyDefinitionId: builtInInheritTagPolicy.id
        parameters: {
          tagName: { value: 'Environment' }   // Specify which tag to inherit
        }
      }
    ]
  }
}

Custom Inheritance Policy Definition (Optional)

If you prefer to create your own inheritance policy instead of using the built‑in one, here is a custom definition with the modify effect:

bicep
resource customInheritTagPolicy 'Microsoft.Authorization/policyDefinitions@2021-06-01' = {
  name: 'inherit-tag-from-resourcegroup'
  properties: {
    displayName: 'Inherit a tag from the resource group if missing'
    policyType: 'Custom'
    mode: 'Indexed'
    description: 'Adds the specified tag from the resource group to a resource if the resource does not have that tag.'
    metadata: { version: '1.0.0', category: 'Tags' }
    parameters: {
      tagName: {
        type: 'String'
        metadata: { displayName: 'Tag Name', description: 'Name of the tag to inherit, e.g. Environment' }
      }
    }
    policyRule: {
      if: {
        allOf: [
          {
            field: '[concat(\'tags[\', parameters(\'tagName\'), \']\')]'
            exists: 'false'
          }
          {
            value: '[resourceGroup().tags[parameters(\'tagName\')]]'
            notEquals: ''
          }
        ]
      }
      then: {
        effect: 'modify'
        details: {
          roleDefinitionIds: [
            '/providers/microsoft.authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c'  // Contributor
          ]
          operations: [{
            operation: 'addOrReplace'
            field: '[concat(\'tags[\', parameters(\'tagName\'), \']\')]'
            value: '[resourceGroup().tags[parameters(\'tagName\')]]'
          }]
        }
      }
    }
  }
}

Then you would reference customInheritTagPolicy.id in the initiative instead of the built‑in ID.

How It Works

  • Inheritance policy – When a resource is created or updated, the policy checks if the resource lacks the specified tag. If the resource group has that tag, the policy adds it to the resource (using the modify effect).

  • Enforcement policies – After inheritance, the enforcement policies validate that the resource now has the required tag with an allowed value. If not, the creation/update is denied.

Deployment and Assignment

Deploy the Bicep template as described previously. After deployment, assign the initiative to the desired scope. During assignment, you can also override the allowed values and the inherited tag name if you parameterized it.

Benefits for FinOps

  • Consistency – Resources automatically receive the same tags as their resource group, reducing manual errors.

  • Simplified onboarding – Teams only need to tag resource groups correctly; all resources inside inherit the tags.

  • Cost allocation – Ensures that all resources, even those created by automated processes, have the necessary tags for accurate cost reporting.

By combining inheritance with enforcement, you build a robust tagging governance framework that supports your FinOps practices.

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
lastly show me how to best go about auditing tag hygiene
 
 
 
 
 
 
 
 
 

We need to provide guidance on auditing tag hygiene in Azure, specifically in the context of FinOps. The user has already seen policy enforcement and inheritance. Now they want to know the best way to audit tag hygiene. This involves checking existing resources for compliance with tagging standards, identifying untagged or incorrectly tagged resources, and reporting.

We should cover:

  • Using Azure Policy’s compliance dashboard to see which resources are non-compliant with the tag policies.

  • Using Azure Resource Graph (ARG) queries to get a detailed inventory of tags across resources.

  • Creating custom workbooks in Azure Monitor to visualize tag coverage.

  • Using tools like Azure Cost Management + Billing to analyze costs by tags (which requires tags to be present).

  • Automating audits via scripts (PowerShell, CLI) and integrating with reporting tools.

  • Establishing a regular cadence for audits and remediation processes.

The answer should be practical, step-by-step, and include examples (ARG queries, PowerShell). Also mention best practices: start with audit effect, set compliance thresholds, involve stakeholders.

Let’s craft a comprehensive response.

 

To effectively audit tag hygiene in Azure, you need a combination of continuous compliance checks and ad‑hoc inventory queries. This allows you to identify untagged or incorrectly tagged resources, measure progress, and enforce accountability. Below are the best practices and tools for auditing tags as part of your FinOps practice.

1. Use Azure Policy Compliance Dashboard (Continuous Auditing)

If you have already assigned the tag enforcement policies (even with audit effect), the Azure Policy compliance dashboard gives you a real‑time view of non‑compliant resources.

  • Navigate to Azure Policy > Compliance.

  • Select your initiative (e.g., “FinOps Enforce Mandatory Tags”).

  • You’ll see the compliance state per policy and per resource.

  • Drill down to see exactly which resources are missing tags or have non‑allowed values.

Best Practice: Start with audit effect, review compliance regularly, and only switch to deny after the majority of resources are compliant.

2. Query Azure Resource Graph (ARG) for Detailed Tag Inventory

Azure Resource Graph enables fast, complex queries across your entire Azure estate. Use it to generate reports on tag coverage.

Example ARG Queries (run in Azure Portal, CLI, or PowerShell)

a) List all resources missing a specific tag (e.g., Cost Centre)

kusto
resources
| where type !~ 'microsoft.resources/subscriptions/resourcegroups'
| where tags has 'Cost Centre' == false
| project subscriptionId, resourceGroup, name, type, location

b) Show all resources with their tags, including missing ones

kusto
resources
| where type !~ 'microsoft.resources/subscriptions/resourcegroups'
| extend costCentre = tags.['Cost Centre'], environment = tags.['Environment'], owner = tags.['Owner'], applicationId = tags.['ApplicationID']
| project subscriptionId, resourceGroup, name, type, costCentre, environment, owner, applicationId
| order by subscriptionId, resourceGroup

c) Count compliance by tag

kusto
resources
| where type !~ 'microsoft.resources/subscriptions/resourcegroups'
| summarize total = count(),
            missingCostCentre = countif(tags.['Cost Centre'] == ''),
            missingEnvironment = countif(tags.['Environment'] == ''),
            missingOwner = countif(tags.['Owner'] == ''),
            missingAppId = countif(tags.['ApplicationID'] == '')

You can run these queries in:

  • Azure Portal (Search for “Azure Resource Graph Explorer”)

  • Azure CLIaz graph query -q "your query"

  • PowerShellSearch-AzGraph -Query "your query"

3. Build a Tag Compliance Workbook in Azure Monitor

Create a reusable, interactive dashboard to visualize tag hygiene metrics.

  • Go to Azure Monitor > Workbooks > Create a new workbook.

  • Add a query step using Azure Resource Graph.

  • Use the queries above to create tables, charts, and KPIs (e.g., percentage of resources with each tag).

  • Set up parameters (e.g., subscription picker) to make it dynamic.

  • Share the workbook with finance and operations teams.

4. Integrate with Azure Cost Management

Azure Cost Management + Billing allows you to filter and group costs by tags – but only if the tags are applied to resources and inherit to cost data.

  • Go to Cost Management > Cost analysis.

  • Add a filter by tag (e.g., “Cost Centre”) to see costs per department.

  • Use the Group by feature to break down costs by tag values.

If you see costs that are not allocated (i.e., untagged resources), you’ve identified a hygiene gap. You can create anomaly alerts for unexpected spending that may be linked to untagged resources.

5. Automate Regular Audits with PowerShell or CLI

For recurring audits, script the process and output to CSV or integrate with a reporting system.

PowerShell Example (using Az.ResourceGraph module)

powershell
# Install module if needed
Install-Module -Name Az.ResourceGraph
# Query for all resources with their tags
$query = @"
resources
| where type !~ 'microsoft.resources/subscriptions/resourcegroups'
| extend costCentre = tags.['Cost Centre'], environment = tags.['Environment'], owner = tags.['Owner'], applicationId = tags.['ApplicationID']
| project subscriptionId, resourceGroup, name, type, costCentre, environment, owner, applicationId
"@
$results = Search-AzGraph -Query $query
$results | Export-Csv -Path "TagAudit_$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation

Schedule this script (e.g., via Azure Automation, Logic Apps, or a CI/CD pipeline) to run weekly and email the report to stakeholders.

6. Remediation Strategies

Auditing alone doesn’t fix non‑compliance. Combine audits with a clear remediation process:

  • Automated remediation – Use Azure Policy’s deployIfNotExists or modify effects to automatically add missing tags (e.g., inherit from resource group).

  • Manual remediation – For resources that can’t be auto‑tagged, assign owners and track tickets.

  • Tag governance playbook – Document who is responsible for applying tags, how to handle exceptions, and the escalation path.

7. Establish a Tag Hygiene Scorecard

Create a monthly scorecard that shows:

  • Percentage of resources with all mandatory tags.

  • Percentage of cost covered by tagged resources.

  • Top untagged resource types.

  • Trends over time.

Share this with leadership to drive accountability and celebrate improvements.

Summary: Recommended Workflow

 
 
StepTool / MethodPurpose
1. BaselineARG query + WorkbookUnderstand current tag coverage
2. Continuous auditAzure Policy (audit effect)Track new non‑compliant resources
3. Cost impactCost Management + tagsIdentify untagged spending
4. Regular reportingPowerShell + CSV / Power BIShare with stakeholders
5. RemediationPolicy modify effect / manual tasksFix gaps
6. GovernanceScorecard + playbookMaintain hygiene

By combining these techniques, you ensure that your Azure environment maintains the tag hygiene required for accurate FinOps cost allocation, showback, and optimization.