Skip to content

Commit 8bde53d

Browse files
authored
Document Azure RBAC Custom Roles for OpenOps Benchmark (#341)
1 parent a14abe9 commit 8bde53d

File tree

4 files changed

+323
-1
lines changed

4 files changed

+323
-1
lines changed

cloud-access/azure-rbac.mdx

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
---
2+
title: 'Azure RBAC Custom Roles'
3+
description: 'How to set up Azure custom roles for OpenOps Benchmark using RBAC'
4+
icon: 'microsoft'
5+
---
6+
7+
import JoinCommunity from '/snippets/join-community.mdx'
8+
9+
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.
10+
11+
## Available Custom Roles
12+
13+
### OpenOps Azure Benchmark Reader
14+
15+
Creates the `OpenOps Azure Benchmark Reader` custom role with read-only permissions for running Azure cost optimization benchmarks. This role includes:
16+
17+
* **Compute resources**: Virtual machines, managed disks, snapshots, and images
18+
* **Networking**: Network interfaces and public IP addresses
19+
* **App Services**: Web apps, App Service Plans, and App Service Environments
20+
* **Databases**: Azure SQL servers, databases, and elastic pools
21+
* **Cost and billing**: Cost Management queries, consumption usage details, and billing properties
22+
* **Monitoring**: Azure Monitor metrics
23+
* **Optimization**: Azure Advisor recommendations and metadata
24+
25+
**[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)**
26+
27+
**Parameters:** AssignableScopes (required)
28+
29+
## Installation Steps
30+
31+
Before creating the custom role, you must configure the `AssignableScopes` parameter to specify where this role can be assigned.
32+
33+
### Configure AssignableScopes
34+
35+
Choose the appropriate scope for your deployment:
36+
37+
<AccordionGroup>
38+
<Accordion title="Single subscription">
39+
**JSON:**
40+
```json
41+
"AssignableScopes": [
42+
"/subscriptions/11111111-1111-1111-1111-111111111111"
43+
]
44+
```
45+
46+
**Bicep parameter:**
47+
```bash
48+
--parameters assignableScopes='["/subscriptions/11111111-1111-1111-1111-111111111111"]'
49+
```
50+
</Accordion>
51+
52+
<Accordion title="Multiple subscriptions">
53+
Use this when you want the role available in specific subscriptions but not across the entire management group.
54+
55+
**JSON:**
56+
```json
57+
"AssignableScopes": [
58+
"/subscriptions/11111111-1111-1111-1111-111111111111",
59+
"/subscriptions/22222222-2222-2222-2222-222222222222",
60+
"/subscriptions/33333333-3333-3333-3333-333333333333"
61+
]
62+
```
63+
64+
**Bicep parameter:**
65+
```bash
66+
--parameters assignableScopes='["/subscriptions/11111111-1111-1111-1111-111111111111","/subscriptions/22222222-2222-2222-2222-222222222222","/subscriptions/33333333-3333-3333-3333-333333333333"]'
67+
```
68+
</Accordion>
69+
70+
<Accordion title="Management group" id="management-group-scope">
71+
Use this only if you want the custom role available across the entire management group scope.
72+
73+
**JSON:**
74+
```json
75+
"AssignableScopes": [
76+
"/providers/Microsoft.Management/managementGroups/my-management-group"
77+
]
78+
```
79+
80+
**Bicep parameter:**
81+
```bash
82+
--parameters assignableScopes='["/providers/Microsoft.Management/managementGroups/my-management-group"]'
83+
```
84+
</Accordion>
85+
</AccordionGroup>
86+
87+
### Option 1: Deploy with Bicep (Recommended)
88+
89+
1. Update the `assignableScopes` parameter in the command below with your subscription ID(s):
90+
91+
```bash
92+
az deployment sub create \
93+
--name openops-azure-benchmark-reader-role \
94+
--location westus2 \
95+
--template-file "./OpenOps Azure Benchmark Reader.role-definition.bicep" \
96+
--parameters assignableScopes='["/subscriptions/<subscription-id>"]'
97+
```
98+
99+
2. For multiple subscriptions:
100+
101+
```bash
102+
az deployment sub create \
103+
--name openops-azure-benchmark-reader-role \
104+
--location westus2 \
105+
--template-file "./OpenOps Azure Benchmark Reader.role-definition.bicep" \
106+
--parameters assignableScopes='["/subscriptions/sub-1","/subscriptions/sub-2"]'
107+
```
108+
109+
**Notes:**
110+
* This is a subscription-scoped deployment. For management group scope, see the [management group configuration](#management-group-scope) above
111+
112+
### Option 2: Deploy with Azure CLI and JSON
113+
114+
1. Edit the `AssignableScopes` field in `OpenOps Azure Benchmark Reader.role-definition.json` with your subscription ID(s).
115+
116+
2. Create the role:
117+
118+
```bash
119+
az role definition create \
120+
--role-definition "./OpenOps Azure Benchmark Reader.role-definition.json"
121+
```
122+
123+
3. To update an existing role:
124+
125+
```bash
126+
az role definition update \
127+
--role-definition "./OpenOps Azure Benchmark Reader.role-definition.json"
128+
```
129+
130+
## Assign the Role to a Service Principal
131+
132+
After creating the custom role, assign it to the service principal that OpenOps uses to connect to Azure.
133+
134+
### Assign at subscription scope
135+
136+
```bash
137+
az role assignment create \
138+
--assignee-object-id "<service-principal-object-id>" \
139+
--assignee-principal-type ServicePrincipal \
140+
--role "OpenOps Azure Benchmark Reader" \
141+
--scope "/subscriptions/11111111-1111-1111-1111-111111111111"
142+
```
143+
144+
### Assign in multiple subscriptions
145+
146+
Run the assignment once per subscription:
147+
148+
```bash
149+
az role assignment create \
150+
--assignee-object-id "<service-principal-object-id>" \
151+
--assignee-principal-type ServicePrincipal \
152+
--role "OpenOps Azure Benchmark Reader" \
153+
--scope "/subscriptions/11111111-1111-1111-1111-111111111111"
154+
```
155+
156+
```bash
157+
az role assignment create \
158+
--assignee-object-id "<service-principal-object-id>" \
159+
--assignee-principal-type ServicePrincipal \
160+
--role "OpenOps Azure Benchmark Reader" \
161+
--scope "/subscriptions/22222222-2222-2222-2222-222222222222"
162+
```
163+
164+
### Assign at management group scope
165+
166+
```bash
167+
az role assignment create \
168+
--assignee-object-id "<service-principal-object-id>" \
169+
--assignee-principal-type ServicePrincipal \
170+
--role "OpenOps Azure Benchmark Reader" \
171+
--scope "/providers/Microsoft.Management/managementGroups/my-management-group"
172+
```
173+
174+
## Verification
175+
176+
Verify the role definition was created:
177+
178+
```bash
179+
az role definition list \
180+
--name "OpenOps Azure Benchmark Reader" \
181+
-o json
182+
```
183+
184+
Check role assignments for your service principal:
185+
186+
```bash
187+
az role assignment list \
188+
--assignee "<service-principal-object-id>" \
189+
--all \
190+
-o table
191+
```
192+
193+
## Cost Management Access
194+
195+
For subscription-scope cost queries, the role includes `Microsoft.CostManagement/query/action` for the POST query API.
196+
197+
Azure Cost Management access commonly requires related read permissions in billing and cost surfaces. This role includes:
198+
199+
* `Microsoft.CostManagement/query/action`
200+
* `Microsoft.CostManagement/*/read`
201+
* `Microsoft.Consumption/*/read`
202+
* `Microsoft.Billing/billingPeriods/read`
203+
* `Microsoft.Billing/billingProperty/read`
204+
* `Microsoft.Resources/subscriptions/read`
205+
* `Microsoft.Resources/subscriptions/resourceGroups/read`
206+
207+
<Note>
208+
If you update the role and still get `RBACAccessDenied`, wait a few minutes and retry. Azure RBAC propagation is not always immediate.
209+
210+
For subscriptions under EA or certain billing setups, cost visibility may also depend on billing-side settings such as view charges access.
211+
</Note>
212+
213+
## Important Notes
214+
215+
* `AssignableScopes` is required for all Azure custom roles
216+
* A management group is above subscriptions in the Azure hierarchy
217+
* If you use multiple subscriptions in `AssignableScopes`, the role is limited to those subscriptions only
218+
* Role creation requires permission to manage custom roles for every scope listed in `AssignableScopes`
219+
220+
## Modification
221+
222+
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.
223+
224+
<JoinCommunity />
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
targetScope = 'subscription'
2+
3+
@description('Scopes where this custom role can be assigned. Defaults to the current subscription.')
4+
param assignableScopes array = [
5+
subscription().id
6+
]
7+
8+
var roleDefinitionGuid = '97fd4ee5-cfe4-4d11-a798-2d9d8a4f153f'
9+
var roleName = 'OpenOps Azure Benchmark Reader'
10+
var roleDescription = 'Read-only benchmark, cost, and Azure Advisor recommendation role for OpenOps Azure Benchmark.'
11+
var actions = [
12+
'Microsoft.Advisor/metadata/read'
13+
'Microsoft.Advisor/recommendations/read'
14+
'Microsoft.Billing/billingPeriods/read'
15+
'Microsoft.Billing/billingProperty/read'
16+
'Microsoft.Compute/disks/read'
17+
'Microsoft.Compute/images/read'
18+
'Microsoft.Compute/snapshots/read'
19+
'Microsoft.Compute/virtualMachines/read'
20+
'Microsoft.Consumption/*/read'
21+
'Microsoft.CostManagement/*/read'
22+
'Microsoft.CostManagement/query/action'
23+
'Microsoft.Insights/metrics/read'
24+
'Microsoft.Network/networkInterfaces/read'
25+
'Microsoft.Network/publicIPAddresses/read'
26+
'Microsoft.Resources/subscriptions/read'
27+
'Microsoft.Resources/subscriptions/resourceGroups/read'
28+
'Microsoft.Sql/servers/databases/read'
29+
'Microsoft.Sql/servers/elasticPools/read'
30+
'Microsoft.Sql/servers/read'
31+
'Microsoft.Web/hostingEnvironments/read'
32+
'Microsoft.Web/serverfarms/read'
33+
'Microsoft.Web/sites/read'
34+
]
35+
36+
resource customRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' = {
37+
name: roleDefinitionGuid
38+
properties: {
39+
roleName: roleName
40+
description: roleDescription
41+
type: 'CustomRole'
42+
permissions: [
43+
{
44+
actions: actions
45+
notActions: []
46+
dataActions: []
47+
notDataActions: []
48+
}
49+
]
50+
assignableScopes: assignableScopes
51+
}
52+
}
53+
54+
output roleDefinitionId string = roleDefinitionGuid
55+
output roleDefinitionResourceId string = customRole.id
56+
output roleDefinitionName string = customRole.properties.roleName
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"Name": "OpenOps Azure Benchmark Reader",
3+
"IsCustom": true,
4+
"Description": "Read-only benchmark, cost, and Azure Advisor recommendation role for OpenOps Azure Benchmark.",
5+
"Actions": [
6+
"Microsoft.Advisor/metadata/read",
7+
"Microsoft.Advisor/recommendations/read",
8+
"Microsoft.Billing/billingPeriods/read",
9+
"Microsoft.Billing/billingProperty/read",
10+
"Microsoft.Compute/disks/read",
11+
"Microsoft.Compute/images/read",
12+
"Microsoft.Compute/snapshots/read",
13+
"Microsoft.Compute/virtualMachines/read",
14+
"Microsoft.Consumption/*/read",
15+
"Microsoft.CostManagement/*/read",
16+
"Microsoft.CostManagement/query/action",
17+
"Microsoft.Insights/metrics/read",
18+
"Microsoft.Network/networkInterfaces/read",
19+
"Microsoft.Network/publicIPAddresses/read",
20+
"Microsoft.Resources/subscriptions/read",
21+
"Microsoft.Resources/subscriptions/resourceGroups/read",
22+
"Microsoft.Sql/servers/databases/read",
23+
"Microsoft.Sql/servers/elasticPools/read",
24+
"Microsoft.Sql/servers/read",
25+
"Microsoft.Web/hostingEnvironments/read",
26+
"Microsoft.Web/serverfarms/read",
27+
"Microsoft.Web/sites/read"
28+
],
29+
"NotActions": [],
30+
"DataActions": [],
31+
"NotDataActions": [],
32+
"AssignableScopes": [
33+
"/subscriptions/<subscription-id>"
34+
]
35+
}

docs.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@
4040
"getting-started/user-management"
4141
]
4242
},
43+
{
44+
"group": "FinOps Benchmark",
45+
"pages": [
46+
"finops-benchmark/overview"
47+
]
48+
},
4349
{
4450
"group": "Workflow Management",
4551
"pages": [
@@ -61,7 +67,8 @@
6167
"pages": [
6268
"cloud-access/supported-cloud-providers",
6369
"cloud-access/access-levels-permissions",
64-
"cloud-access/aws-cf-role-stack"
70+
"cloud-access/aws-cf-role-stack",
71+
"cloud-access/azure-rbac"
6572
]
6673
},
6774
{

0 commit comments

Comments
 (0)