← Workflows

阅读中文版本

Enforce Resource Tagging Across a Cloud Account

Agree a four-tag baseline, measure coverage, backfill existing resources, then block new untagged resources with a policy while an exception process stays open.

intermediate~45 mincloudgovernancecost

Objective

Make owner, environment, cost center and data classification mandatory on every cloud resource without blocking legitimate delivery work.

Environment

  • Cloud organization or subscription hierarchy where policies can be attached at the account or OU level
  • Read access to the resource inventory and billing cost allocation data
  • A tag taxonomy approved by finance, security and engineering
  • A backfill mechanism such as the provider tag editor or an inventory export plus API script
  • An exception request path with a named approver

Steps

1. Agree the tag taxonomy

Define four mandatory keys, allowed values and casing rules, and publish examples for compute, storage, network and managed services.

Expected state: A single taxonomy document is approved and linked from the engineering handbook.

2. Measure current coverage

Export the resource inventory and calculate the percentage of resources with each mandatory tag, grouped by account and service.

Expected state: A coverage baseline exists and the largest untagged groups are ranked by cost and risk.

3. Backfill existing resources

Apply tags from the ownership and billing data through the tag editor or an idempotent script, recording every change in a manifest.

Expected state: Coverage for existing resources exceeds ninety-five percent and the manifest can reverse each change.

4. Run the policy in audit mode

Attach the tagging policy with deny statements disabled, review the would-have-blocked events for two weeks, and fix false positives.

Expected state: Audit events show only genuine violations and delivery teams have seen the upcoming enforcement date.

5. Enforce and handle exceptions

Enable the deny policy on the production organizational unit and route exception requests through a time-boxed approval with a compensating tag value.

Expected state: New untagged resources are rejected while approved exceptions carry an expiry date.

6. Report and iterate

Publish a monthly coverage and exception report, review tags that are missing or wrong, and retire exception values at expiry.

Expected state: Coverage stays above the target and the exception list shrinks each month.

Decision points

Should enforcement start with deny or with reporting only?

  • Enforce deny immediately for all resources
  • Run audit mode for two weeks, then deny

Run audit mode first; it reveals templates, autoscaling groups and vendor integrations that cannot easily pass tags and would fail at 3 a.m.

Where should the tagging policy be attached?

  • At the organization root for uniform coverage
  • Only on production accounts first

Start on the production organizational unit, prove the exception process, then extend to the root.

Should tags be used for access control?

  • Use tags for cost allocation and ownership only
  • Use tags as an attribute in access control policies

Only use tags for access control when users cannot edit the relevant tag keys; otherwise a user can grant themselves access by retagging a resource.

Expected outcome

New resources cannot be created without the four mandatory tags, existing resources are backfilled, and every exception has an owner and an expiry date.

Verification

Attempt to create an untagged instance in the production account and confirm it is denied, then run a coverage query that shows the tagged percentage by account.

Cleanup

Remove temporary backfill credentials, archive the manifest, close expired exceptions and keep the monthly coverage report.

Four tags, one gate

Tagging fails when the taxonomy is large and optional. Pick four keys that answer the questions finance, security and operations actually ask: owner, environment, cost-center and data-classification. Everything else is useful metadata but not enforcement-worthy. Document allowed values and casing, because Prod and production are the same environment to humans and two different environments to a cost report.

Measure before enforcing

Export the inventory and rank untagged resources by monthly cost and by exposure. A single untagged internet-facing load balancer matters more than fifty untagged development disks. Backfill from billing and ownership data, write every change to a manifest so the operation is reversible, and never guess an owner: send the resource to the platform team instead.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RequireOwnerTagOnEc2",
      "Effect": "Deny",
      "Action": "ec2:RunInstances",
      "Resource": "*",
      "Condition": {
        "Null": { "aws:RequestTag/owner": "true" }
      }
    }
  ]
}

Safety checks

Never select resources for cleanup by a missing tag alone; export an explicit list and have the owner confirm it. Check that the policy does not block break-glass automation or the backup service, and test it in a non-production account first. If tags feed access control, restrict who can edit those tag keys, or users can grant themselves access by retagging a resource.

Roll out in two stages

Attach the policy with enforcement disabled and review the would-have-blocked events for two weeks. Fix launch templates, autoscaling groups and vendor-created resources before they fail in production. Then enable the deny statement on the production organizational unit, publish the effective date, and open a time-boxed exception path. The policy above only covers EC2 creation; extend it service by service so each addition can be reviewed.

Rollback and removal

Detaching the policy from the organizational unit restores creation immediately, and backfilled tags can be removed using the manifest. Removing a tag that feeds cost allocation loses historical grouping for that month, so export the billing view before any cleanup. Tagging itself is additive and safe; the irreversible risk is deleting resources during a cleanup sweep that selected on a missing tag instead of an explicit list.