Documentation Index

Fetch the complete documentation index at: https://azure-cost-management-playbook.turbo360.com/llms.txt

Use this file to discover all available pages before exploring further.

Limit access to Azure Cost Management

Prev Next

If you are an MSP you may be implementing custom tooling or 3rd party tooling to help you or your customer manage costs.  In this scenario you may also have the following 2 scenarios:

  1. You include a discount on the Azure prices in what you show your customer

  2. You may include an uplift on the Azure prices but include some managed services which are included into the Azure costs

In both of these cases your charge to the customer will be slightly different to the costs that are displayed in the Azure Portal.

The Challenge


If the customer goes into the Azure Portal and looks at the cost management tooling then they will see a different cost the the one you are including in your bill to the customer.

This will then result in many queries from your customer about the Azure bill being different to what you are charging.  There are usually legitimate reasons for this.  If your bill is cheaper the customer is unlikely to raise this but if you have services included with those costs and an uplift then you are going to need to deal with this.

In this case this is where MSP’s often have reports and tooling that they provide to a customer but often these tools need access to Azure within the provider scope of the Cost Management and Billing area.

The challenge here is that you want to achieve the following:

  1. Limit your customers access to Azure Cost Management to minimize confusion

  2. Give access to your team for Azure Cost Management so they can troubleshoot if necessary

  3. Let your tooling access Azure Cost Management

The problem here is that access to Azure Cost Management is available at subscription level as part of the default reader role so your user assignments will get this by default.

Approach


The ideal approach would be to create a custom RBAC role which has an explicit deny and then just add users to it, but unfortunately that is not how RBAC works in Azure.  If I have an Owner on a subscription but also am added to the a custom role giving me a deny then the Owner role takes precedence and allows me to see Azure Cost Management.

The best way to achieve to achieve what you are looking for is to create some custom RBAC roles which you will use for your customers but to deny Azure Cost Management Access.

Being Pragmatic the most likely roles you will want to create are:

  • Custom Owner which Denies ACM

  • Custom Contributor which Denies ACM

  • Custom Reader which Denies ACM

You will then be able to create the roles with an assignable scope at the tenant root management group and then reuse these roles across your Azure Environment.

There are a few other roles to consider which ill talk about in a bit more detail below but in general I think the above 3 roles will cover what is needed.

The most common roles which have cost management and billing within them are listed below:

Role Name

Scope

Cost Permissions

Notes

🧾 Cost Management Reader

Subscription / MG / RG

Microsoft.CostManagement/*/read

Full cost visibility, no write access

💰 Cost Management Contributor

Subscription / MG / RG

Microsoft.CostManagement/*

Full cost management control (budgets, exports, views, etc.)

📊 Billing Reader

Billing account / enrollment / subscription

Microsoft.Billing/*/read and Microsoft.CostManagement/*/read

Can view billing invoices and usage data

💼 Billing Account Contributor

Billing account scope

Microsoft.Billing/* and Microsoft.CostManagement/*

Can manage billing data and costs

🧾 Reader

Resource / subscription

Includes */read, which implicitly covers some CostManagement read actions at that resource scope (but not always subscription-level)

👑 Owner / Contributor

Any scope

Full permissions including Microsoft.CostManagement/*

Can view and modify cost resources

You can see that the main ones are Reader, Owner, Contributor.  The other roles are specifically for billing which will be straightforward not to use.

There are also some less common roles which do include cost management elements to them and if you needed to you will be able to clone these roles too and add deny actions to them.

Role

Why it has Cost Management actions

Enrollment Reader / Contributor

Access to Enterprise Agreement billing and cost data

Billing Profile Reader / Contributor

For MCA accounts — can view cost and invoices

Reservation Reader / Contributor

Can view reservation costs and recommendations

CSP (Partner Center roles)

Delegated roles can view cost data if AOBO or BillingReader permissions exist

The idea here is you create some custom versions of the 3 main roles and if you assign users to them at any level it will block the cost management blade.  The user will get a message like below.

Custom Roles


To help you setup some custom roles we have provided the json below which you can import into your tenant.  You might want to modify the name so that rather than saying “Reader without ACM and Billing” it says something like “Reader - Custom Acme” so its is easy to see its your custom role for your MSP or end customer.

If you need to create any additional roles you can just clone them and add the deny operations below.

Note that most of the other roles in Azure do not include the cost management providers so assigning someone a role like VM Contributor would not affect anything to do with cost management, its just those top level roles which you need to replace.

Reader without ACM

{
    "properties": {
        "roleName": "Reader without ACM and Billing",
        "description": "Deny permissions on ACM and Billing while allowing other read-only access.",
        "assignableScopes": [
            "/providers/Microsoft.Management/managementGroups/{Your ID}"
        ],
        "permissions": [
            {
                "actions": [
                    "*/read"
                ],
                "notActions": [
                    "Microsoft.CostManagement/*",
                    "Microsoft.Billing/*"
                ],
                "dataActions": [],
                "notDataActions": [
                    "Microsoft.CostManagement/*",
                    "Microsoft.Billing/*"
                ]
            }
        ]
    }
}

Contributor without ACM

{
    "properties": {
        "roleName": "Contributor without ACM and Billing",
        "description": "Deny permissions on ACM and Billing while allowing other contributor access.",
        "assignableScopes": [
            "/providers/Microsoft.Management/managementGroups/{Your ID}"
        ],
        "permissions": [
            {
                "actions": [
                    "*"
                ],
                "notActions": [
                    "Microsoft.CostManagement/*",
                    "Microsoft.Billing/*",
                    "Microsoft.Authorization/*/Delete",
                    "Microsoft.Authorization/*/Write",
                    "Microsoft.Authorization/elevateAccess/Action",
                    "Microsoft.Blueprint/blueprintAssignments/write",
                    "Microsoft.Blueprint/blueprintAssignments/delete",
                    "Microsoft.Compute/galleries/share/action",
                    "Microsoft.Purview/consents/write",
                    "Microsoft.Purview/consents/delete",
                    "Microsoft.Resources/deploymentStacks/manageDenySetting/action",
                    "Microsoft.Subscription/cancel/action",
                    "Microsoft.Subscription/enable/action"
                ],
                "dataActions": [],
                "notDataActions": [
                    "Microsoft.CostManagement/*",
                    "Microsoft.Billing/*"
                ]
            }
        ]
    }
}

Owner without ACM

{
    "properties": {
        "roleName": "Owner without ACM and Billing",
        "description": "Deny permissions on ACM and Billing while allowing other owner access.",
        "assignableScopes": [
            "/providers/Microsoft.Management/managementGroups/{your ID}"
        ],
        "permissions": [
            {
                "actions": [
                    "*"
                ],
                "notActions": [
                    "Microsoft.CostManagement/*",
                    "Microsoft.Billing/*"
                ],
                "dataActions": [],
                "notDataActions": [
                    "Microsoft.CostManagement/*",
                    "Microsoft.Billing/*"
                ]
            }
        ]
    }
}