Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(terraform): add CKV_AWS_375, CKV_AWS_376, CKV_AWS_377 to add three new SageMaker checks #6732

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from checkov.common.models.consts import ANY_VALUE
from checkov.terraform.checks.resource.base_resource_value_check import BaseResourceValueCheck
from checkov.common.models.enums import CheckCategories

class SagemakerEndpointConfigurationEndpointNameSpecified(BaseResourceValueCheck):
def __init__(self):
name = "Ensure Amazon SageMaker endpoint has a name specified"
id = "CKV_AWS_375"
supported_resources = ['aws_sagemaker_endpoint_configuration']
categories = [CheckCategories.AI_AND_ML]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def get_inspected_key(self):
return "name"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requiring name isn't really a security check. You can also use name_prefix which would be valid but flagged by this check.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment below. 😄


def get_expected_value(self):
return ANY_VALUE

check = SagemakerEndpointConfigurationEndpointNameSpecified()
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck

class SagemakerEndpointConfigurationProductionVariantsSpecified(BaseResourceCheck):
def __init__(self):
name = "Ensure Amazon SageMaker endpoint configuration has at least one production variant specified"
id = "CKV_AWS_376"
supported_resources = ['aws_sagemaker_endpoint_configuration']
categories = [CheckCategories.AI_AND_ML]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def scan_resource_conf(self, conf):
production_variants = conf.get("production_variants")
if production_variants:
if isinstance(production_variants, list):
return CheckResult.PASSED if production_variants else CheckResult.FAILED
elif isinstance(production_variants, dict):
return CheckResult.PASSED if 'variant_name' in production_variants and production_variants['variant_name'] else CheckResult.FAILED
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the security concern of Terraform assigning a random name?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a GRC (specifically governance) concern. For example, my org requires specified SageMaker names and tags in spreadsheets, project management boards, planning docs, etc. A random, unspecific name could confuse users and result in downstream problems. So we prohibit random names in SageMaker endpoints for better governance.

return CheckResult.FAILED

check = SagemakerEndpointConfigurationProductionVariantsSpecified()
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from checkov.common.models.consts import ANY_VALUE
from checkov.terraform.checks.resource.base_resource_value_check import BaseResourceValueCheck
from checkov.common.models.enums import CheckCategories

class SagemakerNotebookLifecycleConfigSpecified(BaseResourceValueCheck):
def __init__(self):
name = "Ensure Amazon SageMaker notebook instances use lifecycle configurations"
id = "CKV_AWS_377"
supported_resources = ['aws_sagemaker_notebook_instance']
categories = [CheckCategories.GENERAL_SECURITY]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def get_inspected_key(self):
return "lifecycle_config_name"

def get_expected_value(self):
return ANY_VALUE

check = SagemakerNotebookLifecycleConfigSpecified()
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
resource "aws_sagemaker_endpoint_configuration" "name_fail" {
kms_key_arn = aws_kms_key.test.arn
production_variants {
variant_name = "variant-1"
model_name = aws_sagemaker_model.m.name
initial_instance_count = 1
instance_type = "ml.t2.medium"
}
tags = {
Name = "foo"
}
}

resource "aws_sagemaker_endpoint_configuration" "name_pass" {
name = "my-endpoint-config"
kms_key_arn = aws_kms_key.test.arn
production_variants {
variant_name = "variant-1"
model_name = aws_sagemaker_model.m.name
initial_instance_count = 1
instance_type = "ml.t2.medium"
}
tags = {
Name = "foo"
}
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
resource "aws_sagemaker_endpoint_configuration" "production_variants_pass_1" {
name = "my-endpoint-config"
production_variants {
variant_name = "variant-1"
model_name = aws_sagemaker_model.model.name
initial_instance_count = 1
instance_type = "ml.t2.medium"
}
}

resource "aws_sagemaker_endpoint_configuration" "production_variants_pass_2" {
name = "my-endpoint-config"
production_variants {
variant_name = "variant-1"
model_name = aws_sagemaker_model.model1.name
initial_instance_count = 1
instance_type = "ml.t2.medium"
}
production_variants {
variant_name = "variant-2"
model_name = aws_sagemaker_model.model2.name
initial_instance_count = 2
instance_type = "ml.m5.large"
}
}

resource "aws_sagemaker_endpoint_configuration" "production_variants_fail" {
name = "my-endpoint-config"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
resource "aws_sagemaker_notebook_instance" "lifecycle_config_fail" {
name = "my-notebook-instance"
role_arn = aws_iam_role.role.arn
instance_type = "ml.t2.medium"

tags = {
Name = "foo"
}
}

resource "aws_sagemaker_notebook_instance" "lifecycle_config_pass" {
name = "my-notebook-instance"
role_arn = aws_iam_role.role.arn
instance_type = "ml.t2.medium"
lifecycle_config_name = "test_lifecycle"

tags = {
Name = "foo"
}
}
Loading