Skip to content

Commit 16d428d

Browse files
yagreutsimar7
andauthored
feat: add prevent-custom-role-creation check (#471)
* add prevent-custom-role-creation check * turn actions into a set * implemented feedback * fix lint * Empty commit * Update checks/cloud/azure/authorization/prevent_custom_role_creation.rego Co-authored-by: simar7 <[email protected]> --------- Co-authored-by: simar7 <[email protected]>
1 parent cc46175 commit 16d428d

File tree

5 files changed

+234
-0
lines changed

5 files changed

+234
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
Avoid granting 'Microsoft.Authorization/roleDefinitions/write' permission in custom roles. Restrict role creation capability to core admins only.
3+
4+
```hcl
5+
data "azurerm_subscription" "primary" {
6+
}
7+
8+
resource "azurerm_role_definition" "example" {
9+
name = "my-custom-role"
10+
scope = data.azurerm_subscription.primary.id
11+
description = "This is a custom role created via Terraform"
12+
13+
permissions {
14+
actions = [
15+
"Microsoft.Authorization/roleDefinitions/read",
16+
"Microsoft.Resources/subscriptions/resourceGroups/read",
17+
"Microsoft.Storage/storageAccounts/read"
18+
]
19+
not_actions = []
20+
}
21+
22+
assignable_scopes = [
23+
data.azurerm_subscription.primary.id,
24+
]
25+
}
26+
```
27+
28+
#### Remediation Links
29+
- https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_definition#actions
30+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
Allowing custom roles to include 'roleDefinitions/write' enables privilege escalation. A user could define or alter roles to gain excessive permissions.
3+
4+
5+
### Impact
6+
<!-- Add Impact here -->
7+
8+
<!-- DO NOT CHANGE -->
9+
{{ remediationActions }}
10+
11+
### Links
12+
- https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_definition#actions
13+
14+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# METADATA
2+
# title: Role Definition Allows Custom Role Creation
3+
# description: |
4+
# Allowing custom roles to include 'roleDefinitions/write' enables privilege escalation. A user could define or alter roles to gain excessive permissions.
5+
# scope: package
6+
# schemas:
7+
# - input: schema["cloud"]
8+
# related_resources:
9+
# - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_definition#actions
10+
# custom:
11+
# id: AZU-0052
12+
# aliases:
13+
# - AVD-AZU-0052
14+
# - azure-role-definition-allows-custom-role-creation
15+
# long_id: azure-authorization-prevent-custom-role-creation
16+
# provider: azure
17+
# service: authorization
18+
# severity: MEDIUM
19+
# recommended_action: Avoid granting 'Microsoft.Authorization/roleDefinitions/write' permission in custom roles. Restrict role creation capability to core admins only.
20+
# input:
21+
# selector:
22+
# - type: cloud
23+
# subtypes:
24+
# - service: authorization
25+
# provider: azure
26+
# examples: checks/cloud/azure/authorization/prevent_custom_role_creation.yaml
27+
package builtin.azure.authorization.azure0052
28+
29+
import rego.v1
30+
31+
deny contains res if {
32+
some roledef in input.azure.authorization.roledefinitions
33+
isManaged(roledef)
34+
some action in roledef.permissions[_].actions
35+
allows_custom_role_creation(action.value)
36+
res := result.new(
37+
"Role definition allows custom role creation via 'Microsoft.Authorization/roleDefinitions/write' permission.",
38+
action,
39+
)
40+
}
41+
42+
dangerous_actions := {"Microsoft.Authorization/roleDefinitions/write", "Microsoft.Authorization/*/Write", "Microsoft.Authorization/*", "*"}
43+
44+
allows_custom_role_creation(action_value) if {
45+
action_value in dangerous_actions
46+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
terraform:
2+
links:
3+
- https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/role_definition#actions
4+
good:
5+
- |-
6+
data "azurerm_subscription" "primary" {
7+
}
8+
9+
resource "azurerm_role_definition" "example" {
10+
name = "my-custom-role"
11+
scope = data.azurerm_subscription.primary.id
12+
description = "This is a custom role created via Terraform"
13+
14+
permissions {
15+
actions = [
16+
"Microsoft.Authorization/roleDefinitions/read",
17+
"Microsoft.Resources/subscriptions/resourceGroups/read",
18+
"Microsoft.Storage/storageAccounts/read"
19+
]
20+
not_actions = []
21+
}
22+
23+
assignable_scopes = [
24+
data.azurerm_subscription.primary.id,
25+
]
26+
}
27+
bad:
28+
- |-
29+
data "azurerm_subscription" "primary" {
30+
}
31+
32+
resource "azurerm_role_definition" "example" {
33+
name = "my-custom-role"
34+
scope = data.azurerm_subscription.primary.id
35+
description = "This is a custom role created via Terraform"
36+
37+
permissions {
38+
actions = [
39+
"Microsoft.Authorization/roleDefinitions/write"
40+
]
41+
not_actions = []
42+
}
43+
44+
assignable_scopes = [
45+
data.azurerm_subscription.primary.id,
46+
]
47+
}
48+
- |-
49+
data "azurerm_subscription" "primary" {
50+
}
51+
52+
resource "azurerm_role_definition" "example" {
53+
name = "my-custom-role"
54+
scope = data.azurerm_subscription.primary.id
55+
description = "This is a custom role created via Terraform"
56+
57+
permissions {
58+
actions = [
59+
"Microsoft.Authorization/*"
60+
]
61+
not_actions = []
62+
}
63+
64+
assignable_scopes = [
65+
data.azurerm_subscription.primary.id,
66+
]
67+
}
68+
- |-
69+
data "azurerm_subscription" "primary" {
70+
}
71+
72+
resource "azurerm_role_definition" "example" {
73+
name = "my-custom-role"
74+
scope = data.azurerm_subscription.primary.id
75+
description = "This is a custom role created via Terraform"
76+
77+
permissions {
78+
actions = [
79+
"*"
80+
]
81+
not_actions = []
82+
}
83+
84+
assignable_scopes = [
85+
data.azurerm_subscription.primary.id,
86+
]
87+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package builtin.azure.authorization.azure0052_test
2+
3+
import rego.v1
4+
5+
import data.builtin.azure.authorization.azure0052 as check
6+
7+
test_deny_role_with_explicit_roleDefinitions_write if {
8+
inp := build_input({"permissions": [{"actions": [{"value": "Microsoft.Authorization/roleDefinitions/write"}]}]})
9+
res := check.deny with input as inp
10+
count(res) == 1
11+
}
12+
13+
test_deny_role_with_authorization_wildcard if {
14+
inp := build_input({"permissions": [{"actions": [{"value": "Microsoft.Authorization/*"}]}]})
15+
res := check.deny with input as inp
16+
count(res) == 1
17+
}
18+
19+
test_deny_role_with_full_wildcard if {
20+
inp := build_input({"permissions": [{"actions": [{"value": "*"}]}]})
21+
res := check.deny with input as inp
22+
count(res) == 1
23+
}
24+
25+
test_allow_role_with_specific_read_permission if {
26+
inp := build_input({"permissions": [{"actions": [{"value": "Microsoft.Authorization/roleDefinitions/read"}]}]})
27+
res := check.deny with input as inp
28+
res == set()
29+
}
30+
31+
test_allow_role_with_other_permissions if {
32+
inp := build_input({"permissions": [{"actions": [{"value": "Microsoft.Resources/subscriptions/resourceGroups/read"}]}]})
33+
res := check.deny with input as inp
34+
res == set()
35+
}
36+
37+
test_allow_role_with_multiple_safe_permissions if {
38+
inp := build_input({"permissions": [{"actions": [
39+
{"value": "Microsoft.Authorization/roleDefinitions/read"},
40+
{"value": "Microsoft.Resources/subscriptions/resourceGroups/read"},
41+
{"value": "Microsoft.Storage/storageAccounts/read"},
42+
]}]})
43+
res := check.deny with input as inp
44+
res == set()
45+
}
46+
47+
test_deny_role_with_mixed_permissions_including_dangerous if {
48+
inp := build_input({"permissions": [{"actions": [
49+
{"value": "Microsoft.Authorization/roleDefinitions/read"},
50+
{"value": "Microsoft.Authorization/roleDefinitions/write"},
51+
{"value": "Microsoft.Resources/subscriptions/resourceGroups/read"},
52+
]}]})
53+
res := check.deny with input as inp
54+
count(res) == 1
55+
}
56+
57+
build_input(roledef) := {"azure": {"authorization": {"roledefinitions": [roledef]}}}

0 commit comments

Comments
 (0)