feat(misconf): Add RoleAssignments attribute (#9396)

This commit is contained in:
yagreut
2025-10-31 11:37:16 +02:00
committed by GitHub
parent d020f2690e
commit 3fb8703f8c
6 changed files with 184 additions and 0 deletions

View File

@@ -3,11 +3,13 @@ package authorization
import (
"github.com/aquasecurity/trivy/pkg/iac/providers/azure/authorization"
"github.com/aquasecurity/trivy/pkg/iac/scanners/azure"
iacTypes "github.com/aquasecurity/trivy/pkg/iac/types"
)
func Adapt(deployment azure.Deployment) authorization.Authorization {
return authorization.Authorization{
RoleDefinitions: adaptRoleDefinitions(deployment),
RoleAssignments: adaptRoleAssignments(deployment),
}
}
@@ -27,6 +29,23 @@ func adaptRoleDefinition(resource azure.Resource) authorization.RoleDefinition {
}
}
func adaptRoleAssignments(deployment azure.Deployment) (roleAssignments []authorization.RoleAssignment) {
for _, resource := range deployment.GetResourcesByType("Microsoft.Authorization/roleAssignments") {
roleAssignments = append(roleAssignments, adaptRoleAssignment(resource))
}
return roleAssignments
}
func adaptRoleAssignment(resource azure.Resource) authorization.RoleAssignment {
return authorization.RoleAssignment{
Metadata: resource.Metadata,
RoleDefinitionId: resource.Properties.GetMapValue("roleDefinitionId").AsStringValue("", resource.Metadata),
RoleDefinitionName: iacTypes.String("", iacTypes.NewUnmanagedMetadata()),
PrincipalId: resource.Properties.GetMapValue("principalId").AsStringValue("", resource.Metadata),
PrincipalType: resource.Properties.GetMapValue("principalType").AsStringValue("", resource.Metadata),
}
}
func adaptPermissions(resource azure.Resource) (permissions []authorization.Permission) {
for _, permission := range resource.Properties.GetMapValue("permissions").AsList() {
permissions = append(permissions, authorization.Permission{

View File

@@ -62,6 +62,51 @@ func TestAdapt(t *testing.T) {
}},
},
},
{
name: "role assignment with complete properties",
source: `{
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"properties": {
"scope": "/subscriptions/12345678-1234-1234-1234-123456789012",
"roleDefinitionId": "/subscriptions/12345678-1234-1234-1234-123456789012/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635",
"principalId": "11111111-1111-1111-1111-111111111111",
"principalType": "User"
}
}
]
}`,
expected: authorization.Authorization{
RoleAssignments: []authorization.RoleAssignment{{
RoleDefinitionId: types.StringTest("/subscriptions/12345678-1234-1234-1234-123456789012/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635"),
RoleDefinitionName: types.String("", types.NewUnmanagedMetadata()),
PrincipalId: types.StringTest("11111111-1111-1111-1111-111111111111"),
PrincipalType: types.StringTest("User"),
}},
},
},
{
name: "role assignment with missing properties",
source: `{
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"properties": {
"scope": "/subscriptions/12345678-1234-1234-1234-123456789012"
}
}
]
}`,
expected: authorization.Authorization{
RoleAssignments: []authorization.RoleAssignment{{
RoleDefinitionId: types.StringTest(""),
RoleDefinitionName: types.String("", types.NewUnmanagedMetadata()),
PrincipalId: types.StringTest(""),
PrincipalType: types.StringTest(""),
}},
},
},
}
for _, tt := range tests {

View File

@@ -8,6 +8,7 @@ import (
func Adapt(modules terraform.Modules) authorization.Authorization {
return authorization.Authorization{
RoleDefinitions: adaptRoleDefinitions(modules),
RoleAssignments: adaptRoleAssignments(modules),
}
}
@@ -40,3 +41,28 @@ func adaptRoleDefinition(resource *terraform.Block) authorization.RoleDefinition
AssignableScopes: assignableScopesAttr.AsStringValues(),
}
}
func adaptRoleAssignments(modules terraform.Modules) []authorization.RoleAssignment {
var roleAssignments []authorization.RoleAssignment
for _, module := range modules {
for _, resource := range module.GetResourcesByType("azurerm_role_assignment") {
roleAssignments = append(roleAssignments, adaptRoleAssignment(resource))
}
}
return roleAssignments
}
func adaptRoleAssignment(resource *terraform.Block) authorization.RoleAssignment {
roleDefIdAttr := resource.GetAttribute("role_definition_id")
roleDefNameAttr := resource.GetAttribute("role_definition_name")
principalIdAttr := resource.GetAttribute("principal_id")
principalTypeAttr := resource.GetAttribute("principal_type")
return authorization.RoleAssignment{
Metadata: resource.GetMetadata(),
RoleDefinitionId: roleDefIdAttr.AsStringValueOrDefault("", resource),
RoleDefinitionName: roleDefNameAttr.AsStringValueOrDefault("", resource),
PrincipalId: principalIdAttr.AsStringValueOrDefault("", resource),
PrincipalType: principalTypeAttr.AsStringValueOrDefault("", resource),
}
}

View File

@@ -115,3 +115,56 @@ func TestLines(t *testing.T) {
assert.Equal(t, 10, adapted.RoleDefinitions[0].AssignableScopes[0].GetMetadata().Range().GetEndLine())
}
func Test_adaptRoleAssignment(t *testing.T) {
tests := []struct {
name string
terraform string
expected authorization.RoleAssignment
}{
{
name: "complete role assignment",
terraform: `
resource "azurerm_role_assignment" "example" {
scope = "/subscriptions/12345678-1234-1234-1234-123456789012"
role_definition_id = "/subscriptions/12345678-1234-1234-1234-123456789012/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635"
role_definition_name = "Owner"
principal_id = "11111111-1111-1111-1111-111111111111"
principal_type = "User"
}
`,
expected: authorization.RoleAssignment{
Metadata: iacTypes.NewTestMetadata(),
RoleDefinitionId: iacTypes.String("/subscriptions/12345678-1234-1234-1234-123456789012/providers/Microsoft.Authorization/roleDefinitions/8e3af657-a8ff-443c-a75c-2fe8c4bcb635", iacTypes.NewTestMetadata()),
RoleDefinitionName: iacTypes.String("Owner", iacTypes.NewTestMetadata()),
PrincipalId: iacTypes.String("11111111-1111-1111-1111-111111111111", iacTypes.NewTestMetadata()),
PrincipalType: iacTypes.String("User", iacTypes.NewTestMetadata()),
},
},
{
name: "data reference scope (unresolvable)",
terraform: `
resource "azurerm_role_assignment" "example" {
scope = data.azurerm_resource_group.example.id
role_definition_id = "/subscriptions/12345678-1234-1234-1234-123456789012/providers/Microsoft.Authorization/roleDefinitions/reader"
principal_id = "33333333-3333-3333-3333-333333333333"
}
`,
expected: authorization.RoleAssignment{
Metadata: iacTypes.NewTestMetadata(),
RoleDefinitionId: iacTypes.String("/subscriptions/12345678-1234-1234-1234-123456789012/providers/Microsoft.Authorization/roleDefinitions/reader", iacTypes.NewTestMetadata()),
RoleDefinitionName: iacTypes.String("", iacTypes.NewTestMetadata()),
PrincipalId: iacTypes.String("33333333-3333-3333-3333-333333333333", iacTypes.NewTestMetadata()),
PrincipalType: iacTypes.String("", iacTypes.NewTestMetadata()),
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
modules := tftestutil.CreateModulesFromSource(t, test.terraform, ".tf")
adapted := adaptRoleAssignment(modules.GetBlocks()[0])
testutil.AssertDefsecEqual(t, test.expected, adapted)
})
}
}

View File

@@ -6,6 +6,7 @@ import (
type Authorization struct {
RoleDefinitions []RoleDefinition
RoleAssignments []RoleAssignment
}
type RoleDefinition struct {
@@ -14,6 +15,14 @@ type RoleDefinition struct {
AssignableScopes []iacTypes.StringValue
}
type RoleAssignment struct {
Metadata iacTypes.Metadata
RoleDefinitionId iacTypes.StringValue
RoleDefinitionName iacTypes.StringValue
PrincipalId iacTypes.StringValue
PrincipalType iacTypes.StringValue
}
type Permission struct {
Metadata iacTypes.Metadata
Actions []iacTypes.StringValue

View File

@@ -4572,6 +4572,13 @@
"github.com.aquasecurity.trivy.pkg.iac.providers.azure.authorization.Authorization": {
"type": "object",
"properties": {
"roleassignments": {
"type": "array",
"items": {
"type": "object",
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.providers.azure.authorization.RoleAssignment"
}
},
"roledefinitions": {
"type": "array",
"items": {
@@ -4597,6 +4604,31 @@
}
}
},
"github.com.aquasecurity.trivy.pkg.iac.providers.azure.authorization.RoleAssignment": {
"type": "object",
"properties": {
"__defsec_metadata": {
"type": "object",
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.Metadata"
},
"principalid": {
"type": "object",
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.StringValue"
},
"principaltype": {
"type": "object",
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.StringValue"
},
"roledefinitionid": {
"type": "object",
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.StringValue"
},
"roledefinitionname": {
"type": "object",
"$ref": "#/definitions/github.com.aquasecurity.trivy.pkg.iac.types.StringValue"
}
}
},
"github.com.aquasecurity.trivy.pkg.iac.providers.azure.authorization.RoleDefinition": {
"type": "object",
"properties": {