diff --git a/assets/queries/terraform/aws/iam_role_without_permission_boundary/metadata.json b/assets/queries/terraform/aws/iam_role_without_permission_boundary/metadata.json new file mode 100644 index 00000000000..551f4fef0f2 --- /dev/null +++ b/assets/queries/terraform/aws/iam_role_without_permission_boundary/metadata.json @@ -0,0 +1,14 @@ +{ + "id": "a4d32b6e-9c7f-4b2a-8e5d-1f3c9a0e7b42", + "queryName": "BETA - IAM Role Without Permission Boundary", + "severity": "MEDIUM", + "category": "Access Control", + "descriptionText": "IAM roles should have a permissions boundary defined to limit the maximum permissions that can be granted. Without a permission boundary, IAM roles can potentially be exploited to escalate privileges beyond intended scope.", + "descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role#permissions_boundary", + "platform": "Terraform", + "descriptionID": "a4d32b6e", + "cloudProvider": "aws", + "cwe": "269", + "riskScore": 3.0, + "experimental": "true" +} diff --git a/assets/queries/terraform/aws/iam_role_without_permission_boundary/query.rego b/assets/queries/terraform/aws/iam_role_without_permission_boundary/query.rego new file mode 100644 index 00000000000..1a8ae168b33 --- /dev/null +++ b/assets/queries/terraform/aws/iam_role_without_permission_boundary/query.rego @@ -0,0 +1,20 @@ +package Cx + +import data.generic.common as common_lib +import data.generic.terraform as tf_lib + +CxPolicy[result] { + resource := input.document[i].resource.aws_iam_role[name] + not common_lib.valid_key(resource, "permissions_boundary") + + result := { + "documentId": input.document[i].id, + "resourceType": "aws_iam_role", + "resourceName": tf_lib.get_resource_name(resource, name), + "searchKey": sprintf("resource.aws_iam_role[%s]", [name]), + "issueType": "MissingAttribute", + "keyExpectedValue": sprintf("aws_iam_role[%s].permissions_boundary is defined", [name]), + "keyActualValue": sprintf("aws_iam_role[%s].permissions_boundary is undefined", [name]), + "searchLine": common_lib.build_search_line(["resource", "aws_iam_role", name], []), + } +} diff --git a/assets/queries/terraform/aws/iam_role_without_permission_boundary/test/negative1.tf b/assets/queries/terraform/aws/iam_role_without_permission_boundary/test/negative1.tf new file mode 100644 index 00000000000..1dac3f0b739 --- /dev/null +++ b/assets/queries/terraform/aws/iam_role_without_permission_boundary/test/negative1.tf @@ -0,0 +1,19 @@ +# This should NOT trigger the query - permissions_boundary is defined +resource "aws_iam_role" "negative1" { + name = "negative_role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "ec2.amazonaws.com" + } + } + ] + }) + + permissions_boundary = "arn:aws:iam::123456789012:policy/BoundaryPolicy" +} diff --git a/assets/queries/terraform/aws/iam_role_without_permission_boundary/test/positive1.tf b/assets/queries/terraform/aws/iam_role_without_permission_boundary/test/positive1.tf new file mode 100644 index 00000000000..b1f2fa4e131 --- /dev/null +++ b/assets/queries/terraform/aws/iam_role_without_permission_boundary/test/positive1.tf @@ -0,0 +1,17 @@ +# This should trigger the query - no permissions_boundary defined +resource "aws_iam_role" "positive1" { + name = "positive_role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "ec2.amazonaws.com" + } + } + ] + }) +} diff --git a/assets/queries/terraform/aws/iam_role_without_permission_boundary/test/positive_expected_result.json b/assets/queries/terraform/aws/iam_role_without_permission_boundary/test/positive_expected_result.json new file mode 100644 index 00000000000..4d7097fcbc9 --- /dev/null +++ b/assets/queries/terraform/aws/iam_role_without_permission_boundary/test/positive_expected_result.json @@ -0,0 +1,8 @@ +[ + { + "queryName": "IAM Role Without Permission Boundary", + "severity": "MEDIUM", + "line": 2, + "fileName": "positive1.tf" + } +]