diff --git a/cloud-access/azure-rbac.mdx b/cloud-access/azure-rbac.mdx
new file mode 100644
index 00000000..301293ce
--- /dev/null
+++ b/cloud-access/azure-rbac.mdx
@@ -0,0 +1,224 @@
+---
+title: 'Azure RBAC Custom Roles'
+description: 'How to set up Azure custom roles for OpenOps Benchmark using RBAC'
+icon: 'microsoft'
+---
+
+import JoinCommunity from '/snippets/join-community.mdx'
+
+OpenOps provides Azure custom role definitions to create RBAC roles in your Azure subscriptions with the necessary permissions to run benchmark assessments and collect cost optimization data.
+
+## Available Custom Roles
+
+### OpenOps Azure Benchmark Reader
+
+Creates the `OpenOps Azure Benchmark Reader` custom role with read-only permissions for running Azure cost optimization benchmarks. This role includes:
+
+* **Compute resources**: Virtual machines, managed disks, snapshots, and images
+* **Networking**: Network interfaces and public IP addresses
+* **App Services**: Web apps, App Service Plans, and App Service Environments
+* **Databases**: Azure SQL servers, databases, and elastic pools
+* **Cost and billing**: Cost Management queries, consumption usage details, and billing properties
+* **Monitoring**: Azure Monitor metrics
+* **Optimization**: Azure Advisor recommendations and metadata
+
+**[Download Bicep template](https://openops.s3.us-east-2.amazonaws.com/OpenOpsAzureBenchmarkReader.role-definition.bicep)** | **[Download JSON template](https://openops.s3.us-east-2.amazonaws.com/OpenOpsAzureBenchmarkReader.role-definition.json)**
+
+**Parameters:** AssignableScopes (required)
+
+## Installation Steps
+
+Before creating the custom role, you must configure the `AssignableScopes` parameter to specify where this role can be assigned.
+
+### Configure AssignableScopes
+
+Choose the appropriate scope for your deployment:
+
+
+
+ **JSON:**
+ ```json
+ "AssignableScopes": [
+ "/subscriptions/11111111-1111-1111-1111-111111111111"
+ ]
+ ```
+
+ **Bicep parameter:**
+ ```bash
+ --parameters assignableScopes='["/subscriptions/11111111-1111-1111-1111-111111111111"]'
+ ```
+
+
+
+ Use this when you want the role available in specific subscriptions but not across the entire management group.
+
+ **JSON:**
+ ```json
+ "AssignableScopes": [
+ "/subscriptions/11111111-1111-1111-1111-111111111111",
+ "/subscriptions/22222222-2222-2222-2222-222222222222",
+ "/subscriptions/33333333-3333-3333-3333-333333333333"
+ ]
+ ```
+
+ **Bicep parameter:**
+ ```bash
+ --parameters assignableScopes='["/subscriptions/11111111-1111-1111-1111-111111111111","/subscriptions/22222222-2222-2222-2222-222222222222","/subscriptions/33333333-3333-3333-3333-333333333333"]'
+ ```
+
+
+
+ Use this only if you want the custom role available across the entire management group scope.
+
+ **JSON:**
+ ```json
+ "AssignableScopes": [
+ "/providers/Microsoft.Management/managementGroups/my-management-group"
+ ]
+ ```
+
+ **Bicep parameter:**
+ ```bash
+ --parameters assignableScopes='["/providers/Microsoft.Management/managementGroups/my-management-group"]'
+ ```
+
+
+
+### Option 1: Deploy with Bicep (Recommended)
+
+1. Update the `assignableScopes` parameter in the command below with your subscription ID(s):
+
+```bash
+az deployment sub create \
+ --name openops-azure-benchmark-reader-role \
+ --location westus2 \
+ --template-file "./OpenOps Azure Benchmark Reader.role-definition.bicep" \
+ --parameters assignableScopes='["/subscriptions/"]'
+```
+
+2. For multiple subscriptions:
+
+```bash
+az deployment sub create \
+ --name openops-azure-benchmark-reader-role \
+ --location westus2 \
+ --template-file "./OpenOps Azure Benchmark Reader.role-definition.bicep" \
+ --parameters assignableScopes='["/subscriptions/sub-1","/subscriptions/sub-2"]'
+```
+
+**Notes:**
+* This is a subscription-scoped deployment. For management group scope, see the [management group configuration](#management-group-scope) above
+
+### Option 2: Deploy with Azure CLI and JSON
+
+1. Edit the `AssignableScopes` field in `OpenOps Azure Benchmark Reader.role-definition.json` with your subscription ID(s).
+
+2. Create the role:
+
+```bash
+az role definition create \
+ --role-definition "./OpenOps Azure Benchmark Reader.role-definition.json"
+```
+
+3. To update an existing role:
+
+```bash
+az role definition update \
+ --role-definition "./OpenOps Azure Benchmark Reader.role-definition.json"
+```
+
+## Assign the Role to a Service Principal
+
+After creating the custom role, assign it to the service principal that OpenOps uses to connect to Azure.
+
+### Assign at subscription scope
+
+```bash
+az role assignment create \
+ --assignee-object-id "" \
+ --assignee-principal-type ServicePrincipal \
+ --role "OpenOps Azure Benchmark Reader" \
+ --scope "/subscriptions/11111111-1111-1111-1111-111111111111"
+```
+
+### Assign in multiple subscriptions
+
+Run the assignment once per subscription:
+
+```bash
+az role assignment create \
+ --assignee-object-id "" \
+ --assignee-principal-type ServicePrincipal \
+ --role "OpenOps Azure Benchmark Reader" \
+ --scope "/subscriptions/11111111-1111-1111-1111-111111111111"
+```
+
+```bash
+az role assignment create \
+ --assignee-object-id "" \
+ --assignee-principal-type ServicePrincipal \
+ --role "OpenOps Azure Benchmark Reader" \
+ --scope "/subscriptions/22222222-2222-2222-2222-222222222222"
+```
+
+### Assign at management group scope
+
+```bash
+az role assignment create \
+ --assignee-object-id "" \
+ --assignee-principal-type ServicePrincipal \
+ --role "OpenOps Azure Benchmark Reader" \
+ --scope "/providers/Microsoft.Management/managementGroups/my-management-group"
+```
+
+## Verification
+
+Verify the role definition was created:
+
+```bash
+az role definition list \
+ --name "OpenOps Azure Benchmark Reader" \
+ -o json
+```
+
+Check role assignments for your service principal:
+
+```bash
+az role assignment list \
+ --assignee "" \
+ --all \
+ -o table
+```
+
+## Cost Management Access
+
+For subscription-scope cost queries, the role includes `Microsoft.CostManagement/query/action` for the POST query API.
+
+Azure Cost Management access commonly requires related read permissions in billing and cost surfaces. This role includes:
+
+* `Microsoft.CostManagement/query/action`
+* `Microsoft.CostManagement/*/read`
+* `Microsoft.Consumption/*/read`
+* `Microsoft.Billing/billingPeriods/read`
+* `Microsoft.Billing/billingProperty/read`
+* `Microsoft.Resources/subscriptions/read`
+* `Microsoft.Resources/subscriptions/resourceGroups/read`
+
+
+If you update the role and still get `RBACAccessDenied`, wait a few minutes and retry. Azure RBAC propagation is not always immediate.
+
+For subscriptions under EA or certain billing setups, cost visibility may also depend on billing-side settings such as view charges access.
+
+
+## Important Notes
+
+* `AssignableScopes` is required for all Azure custom roles
+* A management group is above subscriptions in the Azure hierarchy
+* If you use multiple subscriptions in `AssignableScopes`, the role is limited to those subscriptions only
+* Role creation requires permission to manage custom roles for every scope listed in `AssignableScopes`
+
+## Modification
+
+You're welcome to download and modify the role definition according to your needs. Note that some OpenOps benchmark workflows may not function properly if required permissions are removed.
+
+
diff --git a/cloud-access/azure/OpenOps Azure Benchmark Reader.role-definition.bicep b/cloud-access/azure/OpenOps Azure Benchmark Reader.role-definition.bicep
new file mode 100644
index 00000000..07f1db5d
--- /dev/null
+++ b/cloud-access/azure/OpenOps Azure Benchmark Reader.role-definition.bicep
@@ -0,0 +1,56 @@
+targetScope = 'subscription'
+
+@description('Scopes where this custom role can be assigned. Defaults to the current subscription.')
+param assignableScopes array = [
+ subscription().id
+]
+
+var roleDefinitionGuid = '97fd4ee5-cfe4-4d11-a798-2d9d8a4f153f'
+var roleName = 'OpenOps Azure Benchmark Reader'
+var roleDescription = 'Read-only benchmark, cost, and Azure Advisor recommendation role for OpenOps Azure Benchmark.'
+var actions = [
+ 'Microsoft.Advisor/metadata/read'
+ 'Microsoft.Advisor/recommendations/read'
+ 'Microsoft.Billing/billingPeriods/read'
+ 'Microsoft.Billing/billingProperty/read'
+ 'Microsoft.Compute/disks/read'
+ 'Microsoft.Compute/images/read'
+ 'Microsoft.Compute/snapshots/read'
+ 'Microsoft.Compute/virtualMachines/read'
+ 'Microsoft.Consumption/*/read'
+ 'Microsoft.CostManagement/*/read'
+ 'Microsoft.CostManagement/query/action'
+ 'Microsoft.Insights/metrics/read'
+ 'Microsoft.Network/networkInterfaces/read'
+ 'Microsoft.Network/publicIPAddresses/read'
+ 'Microsoft.Resources/subscriptions/read'
+ 'Microsoft.Resources/subscriptions/resourceGroups/read'
+ 'Microsoft.Sql/servers/databases/read'
+ 'Microsoft.Sql/servers/elasticPools/read'
+ 'Microsoft.Sql/servers/read'
+ 'Microsoft.Web/hostingEnvironments/read'
+ 'Microsoft.Web/serverfarms/read'
+ 'Microsoft.Web/sites/read'
+]
+
+resource customRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' = {
+ name: roleDefinitionGuid
+ properties: {
+ roleName: roleName
+ description: roleDescription
+ type: 'CustomRole'
+ permissions: [
+ {
+ actions: actions
+ notActions: []
+ dataActions: []
+ notDataActions: []
+ }
+ ]
+ assignableScopes: assignableScopes
+ }
+}
+
+output roleDefinitionId string = roleDefinitionGuid
+output roleDefinitionResourceId string = customRole.id
+output roleDefinitionName string = customRole.properties.roleName
diff --git a/cloud-access/azure/OpenOps Azure Benchmark Reader.role-definition.json b/cloud-access/azure/OpenOps Azure Benchmark Reader.role-definition.json
new file mode 100644
index 00000000..fc71af5b
--- /dev/null
+++ b/cloud-access/azure/OpenOps Azure Benchmark Reader.role-definition.json
@@ -0,0 +1,35 @@
+{
+ "Name": "OpenOps Azure Benchmark Reader",
+ "IsCustom": true,
+ "Description": "Read-only benchmark, cost, and Azure Advisor recommendation role for OpenOps Azure Benchmark.",
+ "Actions": [
+ "Microsoft.Advisor/metadata/read",
+ "Microsoft.Advisor/recommendations/read",
+ "Microsoft.Billing/billingPeriods/read",
+ "Microsoft.Billing/billingProperty/read",
+ "Microsoft.Compute/disks/read",
+ "Microsoft.Compute/images/read",
+ "Microsoft.Compute/snapshots/read",
+ "Microsoft.Compute/virtualMachines/read",
+ "Microsoft.Consumption/*/read",
+ "Microsoft.CostManagement/*/read",
+ "Microsoft.CostManagement/query/action",
+ "Microsoft.Insights/metrics/read",
+ "Microsoft.Network/networkInterfaces/read",
+ "Microsoft.Network/publicIPAddresses/read",
+ "Microsoft.Resources/subscriptions/read",
+ "Microsoft.Resources/subscriptions/resourceGroups/read",
+ "Microsoft.Sql/servers/databases/read",
+ "Microsoft.Sql/servers/elasticPools/read",
+ "Microsoft.Sql/servers/read",
+ "Microsoft.Web/hostingEnvironments/read",
+ "Microsoft.Web/serverfarms/read",
+ "Microsoft.Web/sites/read"
+ ],
+ "NotActions": [],
+ "DataActions": [],
+ "NotDataActions": [],
+ "AssignableScopes": [
+ "/subscriptions/"
+ ]
+}
diff --git a/docs.json b/docs.json
index c89f86bc..6ebfc57c 100644
--- a/docs.json
+++ b/docs.json
@@ -40,6 +40,12 @@
"getting-started/user-management"
]
},
+ {
+ "group": "FinOps Benchmark",
+ "pages": [
+ "finops-benchmark/overview"
+ ]
+ },
{
"group": "Workflow Management",
"pages": [
@@ -61,7 +67,8 @@
"pages": [
"cloud-access/supported-cloud-providers",
"cloud-access/access-levels-permissions",
- "cloud-access/aws-cf-role-stack"
+ "cloud-access/aws-cf-role-stack",
+ "cloud-access/azure-rbac"
]
},
{
diff --git a/finops-benchmark/overview.mdx b/finops-benchmark/overview.mdx
new file mode 100644
index 00000000..df8e0b0f
--- /dev/null
+++ b/finops-benchmark/overview.mdx
@@ -0,0 +1,55 @@
+---
+title: 'Benchmark'
+description: 'Automated cloud assessment that computes a cost efficiency score and a breakdown of savings opportunities.'
+icon: 'chart-column'
+---
+
+import JoinCommunity from '/snippets/join-community.mdx'
+
+**Benchmark** helps you run an **automated cloud assessment** across the provider you use with OpenOps. You choose your connection, scope, and which cost and efficiency checks to include. OpenOps automatically creates the workflows, runs them, and collects findings so you can prioritize savings and cleanup in one place.
+
+
+## What you get
+
+* A **library of checks** tuned to your selected provider - for example utilization and waste, rightsizing, and savings across compute, storage, databases, and related services.
+* A **benchmark report** in [Analytics](/reporting-analytics/analytics) so you can review KPIs and trends.
+
+## Running a benchmark
+
+1. Click **Run a Benchmark** on the OpenOps home page to start.
+2. Select your **cloud provider**. If you have no connection yet, create one when prompted.
+
+
+3. Choose the **connection** the benchmark should use.
+
+
+For **AWS**, OpenOps must be able to assume a role that includes the **read-only permissions** defined in the Benchmark CloudFormation stack. Use the link beside this step in the wizard to open the stack details. If that role is missing or incomplete, benchmark workflows can fail. For installation steps and templates, see [AWS CloudFormation role stacks](/cloud-access/aws-cf-role-stack).
+
+
+For **Azure**, OpenOps must be able to use a service principal with the **OpenOps Azure Benchmark Reader** custom role assigned at the appropriate scope (subscription or management group). This role includes read-only permissions for compute, networking, databases, cost management, and Azure Advisor. If the role is not assigned or lacks required permissions, benchmark workflows can fail. For installation steps and role definitions, see [Azure RBAC custom roles](/cloud-access/azure-rbac).
+
+
+4. Select **accounts or subscriptions** and **regions** to include.
+
+
+5. Choose the **benchmark workflows** that correspond to the cost and efficiency checks you want this run to perform.
+
+
+6. Click **Run** to execute the benchmark.
+7. When the run completes, open the benchmark report from the link in the wizard.
+
+
+## Benchmark report
+
+
+
+After a successful run, the **benchmark report** is built from benchmark opportunities and cost data from your chosen cloud provider. You will see:
+
+* **Summary metrics**: For example estimated monthly savings from open opportunities, total opportunity count, a **unified cost efficiency** metric (savings versus monthly cost context), and **monthly amortized cost over time**.
+* **Top opportunities to address**: A ranked view you can use to focus on the largest items first.
+* **Breakdown of savings**: Charts such as savings **by service**, **by region**, and **by account** so you can see where optimization potential clusters.
+
+Charts are **cross-linked**: Choose a service, region, or account in one chart to filter the rest of the dashboard. A short note on the dashboard reminds you that you can filter using those dimensions.
+
+
+
diff --git a/images/benchmark-report.png b/images/benchmark-report.png
new file mode 100644
index 00000000..325b9eb7
Binary files /dev/null and b/images/benchmark-report.png differ
diff --git a/images/benchmark-wizard-connection.png b/images/benchmark-wizard-connection.png
new file mode 100644
index 00000000..abefdd69
Binary files /dev/null and b/images/benchmark-wizard-connection.png differ
diff --git a/images/benchmark-wizard-provider.png b/images/benchmark-wizard-provider.png
new file mode 100644
index 00000000..01643e1d
Binary files /dev/null and b/images/benchmark-wizard-provider.png differ
diff --git a/images/benchmark-wizard-regions.png b/images/benchmark-wizard-regions.png
new file mode 100644
index 00000000..5b041aa6
Binary files /dev/null and b/images/benchmark-wizard-regions.png differ
diff --git a/images/benchmark-wizard-workflows.png b/images/benchmark-wizard-workflows.png
new file mode 100644
index 00000000..23c41fb2
Binary files /dev/null and b/images/benchmark-wizard-workflows.png differ
diff --git a/introduction/features-and-benefits.mdx b/introduction/features-and-benefits.mdx
index be740569..e70218e3 100644
--- a/introduction/features-and-benefits.mdx
+++ b/introduction/features-and-benefits.mdx
@@ -25,4 +25,5 @@ Here's a rundown of the major features and benefits that OpenOps provides:
* [Human-in-the-Loop](/workflow-management/human-in-the-loop) mechanisms to enforce control over critical optimizations. Before running deletions or scale-downs, you can make sure to get oversight and approval from stakeholders using notifications with quick action buttons.
* [Tables](/reporting-analytics) to log opportunities and anomalies in a central location, with options to approve, dismiss, mark as false positive, or snooze. You can also use tables to process billing data, map resources to owners, or generate spend reports.
* [Analytics](/reporting-analytics/data-visualization) to build charts and dashboards based on data in OpenOps tables or your existing data sources, such as CSV files, Google Sheets, Postgres databases, and more.
+* [FinOps Benchmark](/finops-benchmark/overview) to run automated cloud assessment that computes a cost efficiency score and a breakdown of savings opportunities.