Skip to content

Commit

Permalink
CKV_AWS_79
Browse files Browse the repository at this point in the history
  • Loading branch information
bahar-shah committed Feb 20, 2025
1 parent b04094a commit a7604d4
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 0 deletions.
12 changes: 12 additions & 0 deletions assets/queries/terraform/aws/imdsv1_is_enabled/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"id": "f1g2h3i4-j5k6-7lmn-8opq-9012rstuvwxy",
"queryName": "IMDSv1 Enabled",
"severity": "HIGH",
"category": "General Security",
"descriptionText": "Ensures that AWS Instance Metadata Service Version 1 (IMDSv1) is disabled. IMDSv1 is vulnerable to SSRF attacks and should be replaced with IMDSv2 with session tokens required.",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#metadata-options",
"platform": "Terraform",
"descriptionID": "f1g2h3i4",
"cloudProvider": "aws",
"cwe": "284"
}
101 changes: 101 additions & 0 deletions assets/queries/terraform/aws/imdsv1_is_enabled/query.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package Cx

import data.generic.common as common_lib
import data.generic.terraform as tf_lib

# Enforce check on aws_instance, aws_launch_template, and aws_launch_configuration
IMDSv1_Disabled[resource_type] {
resource_type := "aws_instance"
}

IMDSv1_Disabled[resource_type] {
resource_type := "aws_launch_template"
}

IMDSv1_Disabled[resource_type] {
resource_type := "aws_launch_configuration"
}

# Case where metadata_options is an array
CxPolicy[result] {
resource_type := IMDSv1_Disabled[_]
resource := input.document[i].resource[resource_type][name]

common_lib.valid_key(resource, "metadata_options")
is_array(resource.metadata_options)

metadata_opt := resource.metadata_options[_]
common_lib.valid_key(metadata_opt, "http_tokens")

metadata_opt.http_tokens != "required"

result := {
"documentId": input.document[i].id,
"resourceType": resource_type,
"resourceName": tf_lib.get_specific_resource_name(resource, resource_type, name),
"searchKey": sprintf("%s[%s].metadata_options.http_tokens", [resource_type, name]),
"issueType": "IncorrectValue",
"keyExpectedValue": "metadata_options.http_tokens should be 'required'",
"keyActualValue": sprintf("metadata_options.http_tokens is '%s'", [metadata_opt.http_tokens]),
"searchLine": common_lib.build_search_line(["resource", resource_type, name, "metadata_options", "http_tokens"], []),
"remediation": json.marshal({
"before": "metadata_options { http_tokens = \"optional\" }",
"after": "metadata_options { http_tokens = \"required\" }"
}),
"remediationType": "replacement"
}
}

# Case where metadata_options is a single object
CxPolicy[result] {
resource_type := IMDSv1_Disabled[_]
resource := input.document[i].resource[resource_type][name]

common_lib.valid_key(resource, "metadata_options")
not is_array(resource.metadata_options)

metadata_opt := resource.metadata_options
common_lib.valid_key(metadata_opt, "http_tokens")

metadata_opt.http_tokens != "required"

result := {
"documentId": input.document[i].id,
"resourceType": resource_type,
"resourceName": tf_lib.get_specific_resource_name(resource, resource_type, name),
"searchKey": sprintf("%s[%s].metadata_options.http_tokens", [resource_type, name]),
"issueType": "IncorrectValue",
"keyExpectedValue": "metadata_options.http_tokens should be 'required'",
"keyActualValue": sprintf("metadata_options.http_tokens is '%s'", [metadata_opt.http_tokens]),
"searchLine": common_lib.build_search_line(["resource", resource_type, name, "metadata_options", "http_tokens"], []),
"remediation": json.marshal({
"before": "metadata_options { http_tokens = \"optional\" }",
"after": "metadata_options { http_tokens = \"required\" }"
}),
"remediationType": "replacement"
}
}

# Case where metadata_options is missing (defaults to IMDSv1)
CxPolicy[result] {
resource_type := IMDSv1_Disabled[_]
resource := input.document[i].resource[resource_type][name]

not common_lib.valid_key(resource, "metadata_options")

result := {
"documentId": input.document[i].id,
"resourceType": resource_type,
"resourceName": tf_lib.get_specific_resource_name(resource, resource_type, name),
"searchKey": sprintf("%s[%s].metadata_options", [resource_type, name]),
"issueType": "MissingValue",
"keyExpectedValue": "metadata_options must be defined with http_tokens set to 'required'",
"keyActualValue": "metadata_options is missing, defaulting to IMDSv1",
"searchLine": common_lib.build_search_line(["resource", resource_type, name, "metadata_options"], []),
"remediation": json.marshal({
"before": "metadata_options is missing",
"after": "metadata_options { http_tokens = \"required\" }"
}),
"remediationType": "addition"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource "aws_instance" "good_example" {
ami = "ami-123456"
instance_type = "t2.micro"

metadata_options {
http_tokens = "required" # ✅ Secure
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "aws_launch_template" "good_example" {
name_prefix = "example"
image_id = "ami-123456"
instance_type = "t2.micro"

metadata_options {
http_tokens = "required" # ✅ Secure
}
}
18 changes: 18 additions & 0 deletions assets/queries/terraform/aws/imdsv1_is_enabled/test/positive.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "aws_instance" "bad_example" {
ami = "ami-123456"
instance_type = "t2.micro"

metadata_options {
http_tokens = "optional" # ❌ Should be "required"
}
}

resource "aws_launch_template" "bad_example" {
name_prefix = "example"
image_id = "ami-123456"
instance_type = "t2.micro"

metadata_options {
http_tokens = "optional" # ❌ Should be "required"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"queryName": "IMDSv1 Enabled",
"severity": "HIGH",
"line": 6
},
{
"queryName": "IMDSv1 Enabled",
"severity": "HIGH",
"line": 16
}
]

0 comments on commit a7604d4

Please sign in to comment.