diff --git a/cloud-access/azure-rbac.mdx b/cloud-access/azure-rbac.mdx new file mode 100644 index 0000000..301293c --- /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 0000000..07f1db5 --- /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 0000000..fc71af5 --- /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 c89f86b..6ebfc57 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" ] }, {