1+ /**
2+ * Authorization resource framework for Microsoft.Authorization resources in Bicep.
3+ *
4+ * Provides classes for working with Azure role assignments and other authorization resources.
5+ *
6+ * Classes:
7+ * - RoleAssignmentResource: Represents Microsoft.Authorization/roleAssignments resources.
8+ * - RoleAssignmentProperties: Properties object for role assignments.
9+ */
10+
11+ private import bicep
12+ private import codeql.bicep.frameworks.Microsoft.General
13+
14+ module Authorization {
15+ private import RoleAssignmentProperties
16+
17+ /**
18+ * Represents a Microsoft.Authorization/roleAssignments resource in a Bicep file.
19+ * See: https://learn.microsoft.com/en-us/azure/templates/microsoft.authorization/roleassignments
20+ */
21+ class RoleAssignmentResource extends AzureResource {
22+ /**
23+ * Constructs a RoleAssignmentResource for Microsoft.Authorization/roleAssignments resources.
24+ */
25+ RoleAssignmentResource ( ) {
26+ this .getResourceType ( ) .regexpMatch ( "^Microsoft.Authorization/roleAssignments@.*" )
27+ }
28+
29+ /**
30+ * Returns the properties object for the role assignment resource.
31+ */
32+ Properties getProperties ( ) { result = this .getProperty ( "properties" ) }
33+
34+ /**
35+ * Returns the scope property of the role assignment.
36+ * This can be a reference to a subscription, resource group, or specific resource.
37+ */
38+ Expr getScope ( ) { result = this .getProperty ( "scope" ) }
39+
40+ /**
41+ * Returns the name property of the role assignment (typically a GUID).
42+ */
43+ StringLiteral getName ( ) { result = this .getProperty ( "name" ) }
44+
45+ /**
46+ * Gets the role definition ID from the properties.
47+ * This identifies which Azure built-in or custom role is being assigned.
48+ * It may be a direct string literal or extracted from a function call.
49+ */
50+ string getRoleDefinitionId ( ) {
51+ result = this .getProperties ( ) .getRoleDefinitionId ( )
52+ }
53+
54+ /**
55+ * Gets the principal ID from the properties.
56+ * This identifies the user, group, or service principal receiving the role assignment.
57+ */
58+ string getPrincipalId ( ) { result = this .getProperties ( ) .getPrincipalId ( ) }
59+
60+ /**
61+ * Gets the principal type from the properties.
62+ * This indicates whether the principal is a User, Group, or ServicePrincipal.
63+ */
64+ string getPrincipalType ( ) { result = this .getProperties ( ) .getPrincipalType ( ) }
65+
66+ /**
67+ * Determines if this is a subscription-scoped role assignment.
68+ */
69+ predicate isSubscriptionScoped ( ) {
70+ exists ( CallExpression call |
71+ call = this .getScope ( ) and
72+ call .getName ( ) = "subscription"
73+ )
74+ }
75+
76+ /**
77+ * Determines if this is a resource group-scoped role assignment.
78+ */
79+ predicate isResourceGroupScoped ( ) {
80+ exists ( CallExpression call |
81+ call = this .getScope ( ) and
82+ call .getName ( ) = "resourceGroup"
83+ )
84+ }
85+
86+ /**
87+ * Determines if this role assignment has a broad scope (subscription or resource group).
88+ */
89+ predicate hasBroadScope ( ) {
90+ this .isSubscriptionScoped ( ) or this .isResourceGroupScoped ( )
91+ }
92+
93+ /**
94+ * Determines if this role assignment grants a powerful built-in role.
95+ * Checks for common powerful roles like Owner and Contributor.
96+ */
97+ predicate grantsPrivilegedRole ( ) {
98+ exists ( string roleId | roleId = this .getRoleDefinitionId ( ) |
99+ // Owner role
100+ roleId = "8e3af657-a8ff-443c-a75c-2fe8c4bcb635" or
101+ // Contributor role
102+ roleId = "b24988ac-6180-42a0-ab88-20f7382dd24c" or
103+ // User Access Administrator role
104+ roleId = "18d7d88d-d35e-4fb5-a5c3-7773c20a72d9"
105+ )
106+ }
107+
108+ /**
109+ * Determines if this role assignment is overly permissive.
110+ * This checks for privileged roles assigned at broad scopes.
111+ */
112+ predicate isOverlyPermissive ( ) {
113+ this .hasBroadScope ( ) and this .grantsPrivilegedRole ( )
114+ }
115+ }
116+
117+ /**
118+ * Module containing property classes for role assignment resources.
119+ */
120+ private module RoleAssignmentProperties {
121+ /**
122+ * Represents the properties object of a role assignment resource.
123+ */
124+ class Properties extends ResourceProperties {
125+ private RoleAssignmentResource parent ;
126+
127+ /**
128+ * Constructor for the Properties class.
129+ */
130+ Properties ( ) { this = parent .getProperty ( "properties" ) }
131+
132+ /**
133+ * Gets the role definition ID property.
134+ */
135+ Expr getRoleDefinitionIdProperty ( ) { result = this .getProperty ( "roleDefinitionId" ) }
136+
137+ /**
138+ * Returns the role definition ID as a string.
139+ * This handles both direct string literals and subscriptionResourceId function calls.
140+ */
141+ string getRoleDefinitionId ( ) {
142+ // Direct string literal
143+ result = this .getRoleDefinitionIdProperty ( ) .( StringLiteral ) .getValue ( )
144+ or
145+ // Extract from subscriptionResourceId function call
146+ exists ( CallExpression call |
147+ call = this .getRoleDefinitionIdProperty ( ) and
148+ call .getName ( ) = "subscriptionResourceId" and
149+ result = call .getArgument ( 1 ) .( StringLiteral ) .getValue ( )
150+ )
151+ }
152+
153+ /**
154+ * Determines if the role definition ID property exists.
155+ */
156+ predicate hasRoleDefinitionId ( ) { exists ( this .getRoleDefinitionIdProperty ( ) ) }
157+
158+ /**
159+ * Gets the principal ID property.
160+ */
161+ Expr getPrincipalIdProperty ( ) { result = this .getProperty ( "principalId" ) }
162+
163+ /**
164+ * Returns the principal ID as a string.
165+ */
166+ string getPrincipalId ( ) { result = this .getPrincipalIdProperty ( ) .( StringLiteral ) .getValue ( ) }
167+
168+ /**
169+ * Determines if the principal ID property exists.
170+ */
171+ predicate hasPrincipalId ( ) { exists ( this .getPrincipalIdProperty ( ) ) }
172+
173+ /**
174+ * Gets the principal type property.
175+ */
176+ Expr getPrincipalTypeProperty ( ) { result = this .getProperty ( "principalType" ) }
177+
178+ /**
179+ * Returns the principal type as a string.
180+ */
181+ string getPrincipalType ( ) { result = this .getPrincipalTypeProperty ( ) .( StringLiteral ) .getValue ( ) }
182+
183+ /**
184+ * Determines if the principal type property exists.
185+ */
186+ predicate hasPrincipalType ( ) { exists ( this .getPrincipalTypeProperty ( ) ) }
187+
188+ override string toString ( ) { result = "RoleAssignmentProperties" }
189+ }
190+ }
191+ }
0 commit comments