-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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" | ||
|
||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain the security concern of Terraform assigning a random name? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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" | ||
} | ||
} |
There was a problem hiding this comment.
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 usename_prefix
which would be valid but flagged by this check.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment below. 😄