feat(): Sagemaker service and checks (#1490)

Co-authored-by: sergargar <sergio@verica.io>
This commit is contained in:
Nacho Rivera
2022-11-17 12:56:36 +01:00
committed by GitHub
parent 67b5de205b
commit daa299c7a6
54 changed files with 1805 additions and 470 deletions

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7103="7.103"
CHECK_TITLE_extra7103="[extra7103] Check if Amazon SageMaker Notebook instances have root access disabled"
CHECK_SCORED_extra7103="NOT_SCORED"
CHECK_CIS_LEVEL_extra7103="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7103="AwsSageMakerNotebookInstance"
CHECK_ALTERNATE_check7103="extra7103"
CHECK_SEVERITY_extra7103="Medium"
CHECK_SERVICENAME_extra7103="sagemaker"
CHECK_RISK_extra7103='Users with root access have administrator privileges; users can access and edit all files on a notebook instance with root access enabled.'
CHECK_REMEDIATION_extra7103='set the RootAccess field to Disabled. You can also disable root access for users when you create or update a notebook instance in the Amazon SageMaker console.'
CHECK_DOC_extra7103='https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-root-access.html'
CHECK_CAF_EPIC_extra7103='IAM'
extra7103(){
for regx in ${REGIONS}; do
LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list notebook instances" "$regx"
continue
fi
if [[ $LIST_SM_NB_INSTANCES ]];then
for nb_instance in $LIST_SM_NB_INSTANCES; do
SM_NB_ROOTACCESS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-notebook-instance --notebook-instance-name $nb_instance --query 'RootAccess' --output text)
if [[ "${SM_NB_ROOTACCESS}" == "Enabled" ]]; then
textFail "${regx}: Sagemaker Notebook instance $nb_instance has root access enabled" "${regx}" "$nb_instance"
else
textPass "${regx}: Sagemaker Notebook instance $nb_instance has root access disabled" "${regx}" "$nb_instance"
fi
done
else
textInfo "${regx}: No Sagemaker Notebook instances found" "${regx}"
fi
done
}

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7104="7.104"
CHECK_TITLE_extra7104="[extra7104] Check if Amazon SageMaker Notebook instances have VPC settings configured"
CHECK_SCORED_extra7104="NOT_SCORED"
CHECK_CIS_LEVEL_extra7104="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7104="AwsSageMakerNotebookInstance"
CHECK_ALTERNATE_check7104="extra7104"
CHECK_SEVERITY_extra7104="Medium"
CHECK_SERVICENAME_extra7104="sagemaker"
CHECK_RISK_extra7104='This could provide an avenue for unauthorized access to your data.'
CHECK_REMEDIATION_extra7104='Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.'
CHECK_DOC_extra7104='https://docs.aws.amazon.com/sagemaker/latest/dg/studio-notebooks-and-internet-access.html'
CHECK_CAF_EPIC_extra7104='Infrastructure Security'
extra7104(){
for regx in ${REGIONS}; do
LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list notebook instances" "$regx"
continue
fi
if [[ $LIST_SM_NB_INSTANCES ]];then
for nb_instance in $LIST_SM_NB_INSTANCES; do
SM_NB_SUBNETID=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-notebook-instance --notebook-instance-name $nb_instance --query 'SubnetId' --output text)
if [[ "${SM_NB_SUBNETID}" == "None" ]]; then
textFail "${regx}: Sagemaker Notebook instance $nb_instance has VPC settings disabled" "${regx}" "$nb_instance"
else
textPass "${regx}: Sagemaker Notebook instance $nb_instance is in a VPC" "${regx}" "$nb_instance"
fi
done
else
textInfo "${regx}: No Sagemaker Notebook instances found" "${regx}"
fi
done
}

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7105="7.105"
CHECK_TITLE_extra7105="[extra7105] Check if Amazon SageMaker Models have network isolation enabled"
CHECK_SCORED_extra7105="NOT_SCORED"
CHECK_CIS_LEVEL_extra7105="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7105="AwsSageMakerModel"
CHECK_ALTERNATE_check7105="extra7105"
CHECK_SEVERITY_extra7105="Medium"
CHECK_SERVICENAME_extra7105="sagemaker"
CHECK_RISK_extra7105='This could provide an avenue for unauthorized access to your data.'
CHECK_REMEDIATION_extra7105='Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.'
CHECK_DOC_extra7105='https://docs.aws.amazon.com/sagemaker/latest/dg/studio-notebooks-and-internet-access.html'
CHECK_CAF_EPIC_extra7105='Infrastructure Security'
extra7105(){
for regx in ${REGIONS}; do
LIST_SM_NB_MODELS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-models --query 'Models[*].ModelName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_MODELS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list models" "$regx"
continue
fi
if [[ $LIST_SM_NB_MODELS ]];then
for nb_model_name in $LIST_SM_NB_MODELS; do
SM_NB_NETWORKISOLATION=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-model --model-name $nb_model_name --query 'EnableNetworkIsolation' --output text)
if [[ $SM_NB_NETWORKISOLATION == False ]]; then
textFail "${regx}: SageMaker Model $nb_model_name has network isolation disabled" "${regx}" "$nb_model_name"
else
textPass "${regx}: SageMaker Model $nb_model_name has network isolation enabled" "${regx}" "$nb_model_name"
fi
done
else
textInfo "${regx}: No Sagemaker Models found" "${regx}"
fi
done
}

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7106="7.106"
CHECK_TITLE_extra7106="[extra7106] Check if Amazon SageMaker Models have VPC settings configured"
CHECK_SCORED_extra7106="NOT_SCORED"
CHECK_CIS_LEVEL_extra7106="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7106="AwsSageMakerModel"
CHECK_ALTERNATE_check7106="extra7106"
CHECK_SEVERITY_extra7106="Medium"
CHECK_SERVICENAME_extra7106="sagemaker"
CHECK_RISK_extra7106='This could provide an avenue for unauthorized access to your data.'
CHECK_REMEDIATION_extra7106='Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.'
CHECK_DOC_extra7106='https://docs.aws.amazon.com/sagemaker/latest/dg/studio-notebooks-and-internet-access.html'
CHECK_CAF_EPIC_extra7106='Infrastructure Security'
extra7106(){
for regx in ${REGIONS}; do
LIST_SM_NB_MODELS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-models --query 'Models[*].ModelName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_MODELS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list models" "$regx"
continue
fi
if [[ $LIST_SM_NB_MODELS ]];then
for nb_model_name in $LIST_SM_NB_MODELS; do
SM_NB_VPCCONFIG=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-model --model-name $nb_model_name --query 'VpcConfig.Subnets' --output text)
if [[ $SM_NB_VPCCONFIG == "None" ]]; then
textFail "${regx}: Amazon SageMaker Model $nb_model_name has VPC settings disabled" "${regx}" "$nb_model_name"
else
textPass "${regx}: Amazon SageMaker Model $nb_model_name has VPC settings enabled" "${regx}" "$nb_model_name"
fi
done
else
textInfo "${regx}: No Sagemaker Models found" "${regx}"
fi
done
}

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7107="7.107"
CHECK_TITLE_extra7107="[extra7107] Check if Amazon SageMaker Training jobs have intercontainer encryption enabled"
CHECK_SCORED_extra7107="NOT_SCORED"
CHECK_CIS_LEVEL_extra7107="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7107="AwsSageMakerNotebookInstance"
CHECK_ALTERNATE_check7107="extra7107"
CHECK_SEVERITY_extra7107="Medium"
CHECK_SERVICENAME_extra7107="sagemaker"
CHECK_RISK_extra7107='If not restricted unintended access could happen.'
CHECK_REMEDIATION_extra7107='Internetwork communications support TLS 1.2 encryption between all components and clients.'
CHECK_DOC_extra7107='https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html'
CHECK_CAF_EPIC_extra7107='Data Protection'
extra7107(){
for regx in ${REGIONS}; do
LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_JOBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list training jobs" "$regx"
continue
fi
if [[ $LIST_SM_NB_JOBS ]];then
for nb_job_name in $LIST_SM_NB_JOBS; do
SM_NB_INTERCONTAINERENCRYPTION=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-training-job --training-job-name $nb_job_name --query 'EnableInterContainerTrafficEncryption' --output text)
if [[ $SM_NB_INTERCONTAINERENCRYPTION == "False" ]]; then
textFail "${regx}: SageMaker Training job $nb_job_name has intercontainer encryption disabled" "${regx}" "$nb_job_name"
else
textPass "${regx}: SageMaker Training jobs $nb_job_name has intercontainer encryption enabled" "${regx}" "$nb_job_name"
fi
done
else
textInfo "${regx}: No Sagemaker Training found" "${regx}"
fi
done
}

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7108="7.108"
CHECK_TITLE_extra7108="[extra7108] Check if Amazon SageMaker Training jobs have volume and output with KMS encryption enabled"
CHECK_SCORED_extra7108="NOT_SCORED"
CHECK_CIS_LEVEL_extra7108="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7108="AwsSageMakerNotebookInstance"
CHECK_ALTERNATE_check7108="extra7108"
CHECK_SEVERITY_extra7108="Medium"
CHECK_SERVICENAME_extra7108="sagemaker"
CHECK_RISK_extra7108='Data exfiltration could happen if information is not protected. KMS keys provide additional security level to IAM policies.'
CHECK_REMEDIATION_extra7108='Specify AWS KMS keys to use for input and output from S3 and EBS.'
CHECK_DOC_extra7108='https://docs.aws.amazon.com/sagemaker/latest/dg/key-management.html'
CHECK_CAF_EPIC_extra7108='Data Protection'
extra7108(){
for regx in ${REGIONS}; do
LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_JOBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list training jobs" "$regx"
continue
fi
if [[ $LIST_SM_NB_JOBS ]];then
for nb_job_name in $LIST_SM_NB_JOBS; do
SM_JOB_KMSENCRYPTION=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-training-job --training-job-name $nb_job_name --query 'ResourceConfig.VolumeKmsKeyId' --output text)
if [[ "${SM_JOB_KMSENCRYPTION}" == "None" ]];then
textFail "${regx}: Sagemaker Trainings job $nb_job_name has KMS encryption disabled" "${regx}" "$nb_job_name"
else
textPass "${regx}: Sagemaker Trainings job $nb_job_name has KSM encryption enabled" "${regx}" "$nb_job_name"
fi
done
else
textInfo "${regx}: No Sagemaker Trainings jobs found" "${regx}"
fi
done
}

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7109="7.109"
CHECK_TITLE_extra7109="[extra7109] Check if Amazon SageMaker Training jobs have network isolation enabled"
CHECK_SCORED_extra7109="NOT_SCORED"
CHECK_CIS_LEVEL_extra7109="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7109="AwsSageMakerNotebookInstance"
CHECK_ALTERNATE_check7109="extra7109"
CHECK_SEVERITY_extra7109="Medium"
CHECK_SERVICENAME_extra7109="sagemaker"
CHECK_RISK_extra7109='This could provide an avenue for unauthorized access to your data.'
CHECK_REMEDIATION_extra7109='Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.'
CHECK_DOC_extra7109='https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html'
CHECK_CAF_EPIC_extra7109='Infrastructure Security'
extra7109(){
for regx in ${REGIONS}; do
LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_JOBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list training jobs" "$regx"
continue
fi
if [[ $LIST_SM_NB_JOBS ]];then
for nb_job_name in $LIST_SM_NB_JOBS; do
SM_NB_NETWORKISOLATION=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-training-job --training-job-name $nb_job_name --query 'EnableNetworkIsolation' --output text)
if [[ $SM_NB_NETWORKISOLATION == False ]]; then
textFail "${regx}: Sagemaker Training job $nb_job_name has network isolation disabled" "${regx}" "$nb_job_name"
else
textPass "${regx}: Sagemaker Training job $nb_job_name has network isolation enabled" "${regx}" "$nb_job_name"
fi
done
else
textInfo "${regx}: No Sagemaker Trainings jobs found" "${regx}"
fi
done
}

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7110="7.110"
CHECK_TITLE_extra7110="[extra7110] Check if Amazon SageMaker Training job have VPC settings configured."
CHECK_SCORED_extra7110="NOT_SCORED"
CHECK_CIS_LEVEL_extra7110="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7110="AwsSageMakerNotebookInstance"
CHECK_ALTERNATE_check7110="extra7110"
CHECK_SEVERITY_extra7110="Medium"
CHECK_SERVICENAME_extra7110="sagemaker"
CHECK_RISK_extra7110='This could provide an avenue for unauthorized access to your data.'
CHECK_REMEDIATION_extra7110='Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.'
CHECK_DOC_extra7110='https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html'
CHECK_CAF_EPIC_extra7110='Infrastructure Security'
extra7110(){
for regx in ${REGIONS}; do
LIST_SM_NB_JOBS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-training-jobs --query 'TrainingJobSummaries[*].TrainingJobName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_JOBS" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list training jobs" "$regx"
continue
fi
if [[ $LIST_SM_NB_JOBS ]];then
for nb_job_name in $LIST_SM_NB_JOBS; do
SM_NB_SUBNETS=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-training-job --training-job-name $nb_job_name --query 'VpcConfig.Subnets' --output text)
if [[ $SM_NB_SUBNETS == "None" ]]; then
textFail "${regx}: Sagemaker Training job $nb_job_name has VPC settings for the training job volume and output disabled" "${regx}" "$nb_job_name"
else
textPass "${regx}: Sagemaker Training job $nb_job_name has VPC settings for the training job volume and output enabled" "${regx}" "$nb_job_name"
fi
done
else
textInfo "${regx}: No Sagemaker Trainings jobs found" "${regx}"
fi
done
}

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7111="7.111"
CHECK_TITLE_extra7111="[extra7111] Check if Amazon SageMaker Notebook instances have direct internet access"
CHECK_SCORED_extra7111="NOT_SCORED"
CHECK_CIS_LEVEL_extra7111="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7111="AwsSageMakerNotebookInstance"
CHECK_ALTERNATE_check7111="extra7111"
CHECK_SEVERITY_extra7111="Medium"
CHECK_SERVICENAME_extra7111="sagemaker"
CHECK_RISK_extra7111='This could provide an avenue for unauthorized access to your data.'
CHECK_REMEDIATION_extra7111='Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.'
CHECK_DOC_extra7111='https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html'
CHECK_CAF_EPIC_extra7111='Infrastructure Security'
extra7111(){
for regx in ${REGIONS}; do
LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list notebook instances" "$regx"
continue
fi
if [[ $LIST_SM_NB_INSTANCES ]];then
for nb_instance in $LIST_SM_NB_INSTANCES; do
SM_NB_DIRECTINET=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-notebook-instance --notebook-instance-name $nb_instance --query 'DirectInternetAccess' --output text)
if [[ "${SM_NB_DIRECTINET}" == "Enabled" ]]; then
textFail "${regx}: Sagemaker Notebook instance $nb_instance has direct internet access enabled" "${regx}" "$nb_instance"
else
textPass "${regx}: Sagemaker Notebook instance $nb_instance has direct internet access disabled" "${regx}" "$nb_instance"
fi
done
else
textInfo "${regx}: No Sagemaker Notebook instances found" "${regx}"
fi
done
}

View File

@@ -1,47 +0,0 @@
#!/usr/bin/env bash
# Prowler - the handy cloud security tool (copyright 2020) by Toni de la Fuente
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
CHECK_ID_extra7112="7.112"
CHECK_TITLE_extra7112="[extra7112] Check if Amazon SageMaker Notebook instances have data encryption enabled"
CHECK_SCORED_extra7112="NOT_SCORED"
CHECK_CIS_LEVEL_extra7112="EXTRA"
CHECK_ASFF_RESOURCE_TYPE_extra7112="AwsSageMakerNotebookInstance"
CHECK_ALTERNATE_check7112="extra7112"
CHECK_SEVERITY_extra7112="Medium"
CHECK_SERVICENAME_extra7112="sagemaker"
CHECK_RISK_extra7112='Data exfiltration could happen if information is not protected. KMS keys provide additional security level to IAM policies.'
CHECK_REMEDIATION_extra7112='Specify AWS KMS keys to use for input and output from S3 and EBS.'
CHECK_DOC_extra7112='https://docs.aws.amazon.com/sagemaker/latest/dg/key-management.html'
CHECK_CAF_EPIC_extra7112='Data Protection'
extra7112(){
for regx in ${REGIONS}; do
LIST_SM_NB_INSTANCES=$($AWSCLI $PROFILE_OPT --region $regx sagemaker list-notebook-instances --query 'NotebookInstances[*].NotebookInstanceName' --output text 2>&1)
if [[ $(echo "$LIST_SM_NB_INSTANCES" | grep -E 'AccessDenied|UnauthorizedOperation|AuthorizationError') ]]; then
textInfo "$regx: Access Denied trying to list notebook instances" "$regx"
continue
fi
if [[ $LIST_SM_NB_INSTANCES ]];then
for nb_instance in $LIST_SM_NB_INSTANCES; do
SM_NB_KMSKEY=$($AWSCLI $PROFILE_OPT --region $regx sagemaker describe-notebook-instance --notebook-instance-name $nb_instance --query 'KmsKeyId' --output text)
if [[ "${SM_NB_KMSKEY}" == "None" ]]; then
textFail "${regx}: Sagemaker Notebook instance $nb_instance has data encryption disabled" "${regx}" "$nb_instance"
else
textPass "${regx}: Sagemaker Notebook instance $nb_instance has data encryption enabled" "${regx}" "$nb_instance"
fi
done
else
textInfo "${regx}: No Sagemaker Notebook instances found" "${regx}"
fi
done
}

View File

@@ -0,0 +1,4 @@
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.sagemaker.sagemaker_service import SageMaker
sagemaker_client = SageMaker(current_audit_info)

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_models_network_isolation_enabled",
"CheckTitle": "Check if Amazon SageMaker Models have network isolation enabled",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:model",
"Severity": "medium",
"ResourceType": "AwsSageMakerModel",
"Description": "Check if Amazon SageMaker Models have network isolation enabled",
"Risk": "This could provide an avenue for unauthorized access to your data.",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/studio-notebooks-and-internet-access.html",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/studio-notebooks-and-internet-access.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,21 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_models_network_isolation_enabled(Check):
def execute(self):
findings = []
for model in sagemaker_client.sagemaker_models:
report = Check_Report(self.metadata)
report.region = model.region
report.resource_id = model.name
report.resource_arn = model.arn
report.status = "PASS"
report.status_extended = f"Sagemaker notebook instance {model.name} has network isolation enabled"
if not model.network_isolation:
report.status = "FAIL"
report.status_extended = f"Sagemaker notebook instance {model.name} has network isolation disabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,83 @@
from re import search
from unittest import mock
from uuid import uuid4
from providers.aws.services.sagemaker.sagemaker_service import Model
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_notebook_instance = "test-notebook-instance"
notebook_instance_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:notebook-instance/{test_notebook_instance}"
subnet_id = "subnet-" + str(uuid4())
class Test_sagemaker_models_network_isolation_enabled:
def test_no_models(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_models = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_models_network_isolation_enabled.sagemaker_models_network_isolation_enabled import (
sagemaker_models_network_isolation_enabled,
)
check = sagemaker_models_network_isolation_enabled()
result = check.execute()
assert len(result) == 0
def test_instance_network_isolation_enabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_models = []
sagemaker_client.sagemaker_models.append(
Model(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
network_isolation=True,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_models_network_isolation_enabled.sagemaker_models_network_isolation_enabled import (
sagemaker_models_network_isolation_enabled,
)
check = sagemaker_models_network_isolation_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search("has network isolation enabled", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn
def test_instance_network_isolation_disabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_models = []
sagemaker_client.sagemaker_models.append(
Model(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
network_isolation=False,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_models_network_isolation_enabled.sagemaker_models_network_isolation_enabled import (
sagemaker_models_network_isolation_enabled,
)
check = sagemaker_models_network_isolation_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search("has network isolation disabled", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_models_vpc_settings_configured",
"CheckTitle": "Check if Amazon SageMaker Models have VPC settings configured",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:model",
"Severity": "medium",
"ResourceType": "AwsSageMakerModel",
"Description": "Check if Amazon SageMaker Models have VPC settings configured",
"Risk": "This could provide an avenue for unauthorized access to your data.",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/studio-notebooks-and-internet-access.html",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/studio-notebooks-and-internet-access.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,23 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_models_vpc_settings_configured(Check):
def execute(self):
findings = []
for model in sagemaker_client.sagemaker_models:
report = Check_Report(self.metadata)
report.region = model.region
report.resource_id = model.name
report.resource_arn = model.arn
report.status = "PASS"
report.status_extended = (
f"Sagemaker notebook instance {model.name} has VPC settings enabled"
)
if not model.vpc_config_subnets:
report.status = "FAIL"
report.status_extended = f"Sagemaker notebook instance {model.name} has VPC settings disabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,82 @@
from re import search
from unittest import mock
from uuid import uuid4
from providers.aws.services.sagemaker.sagemaker_service import Model
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_notebook_instance = "test-notebook-instance"
notebook_instance_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:notebook-instance/{test_notebook_instance}"
subnet_id = "subnet-" + str(uuid4())
class Test_sagemaker_models_vpc_settings_configured:
def test_no_models(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_models = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_models_vpc_settings_configured.sagemaker_models_vpc_settings_configured import (
sagemaker_models_vpc_settings_configured,
)
check = sagemaker_models_vpc_settings_configured()
result = check.execute()
assert len(result) == 0
def test_instance_vpc_settings_configured(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_models = []
sagemaker_client.sagemaker_models.append(
Model(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
vpc_config_subnets=[subnet_id],
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_models_vpc_settings_configured.sagemaker_models_vpc_settings_configured import (
sagemaker_models_vpc_settings_configured,
)
check = sagemaker_models_vpc_settings_configured()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search("has VPC settings enabled", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn
def test_instance_vpc_settings_not_configured(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_models = []
sagemaker_client.sagemaker_models.append(
Model(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_models_vpc_settings_configured.sagemaker_models_vpc_settings_configured import (
sagemaker_models_vpc_settings_configured,
)
check = sagemaker_models_vpc_settings_configured()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search("has VPC settings disabled", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_notebook_instance_encryption_enabled",
"CheckTitle": "Check if Amazon SageMaker Notebook instances have data encryption enabled",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:notebook-instance",
"Severity": "medium",
"ResourceType": "AwsSageMakerNotebookInstance",
"Description": "Check if Amazon SageMaker Notebook instances have data encryption enabled",
"Risk": "Data exfiltration could happen if information is not protected. KMS keys provide additional security level to IAM policies.",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/key-management.html",
"Remediation": {
"Code": {
"CLI": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/SageMaker/notebook-data-encrypted.html",
"NativeIaC": "",
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/SageMaker/notebook-data-encrypted.html",
"Terraform": "https://docs.bridgecrew.io/docs/bc_aws_general_40#fix---buildtime"
},
"Recommendation": {
"Text": "Specify AWS KMS keys to use for input and output from S3 and EBS.",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/key-management.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,21 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_notebook_instance_encryption_enabled(Check):
def execute(self):
findings = []
for notebook_instance in sagemaker_client.sagemaker_notebook_instances:
report = Check_Report(self.metadata)
report.region = notebook_instance.region
report.resource_id = notebook_instance.name
report.resource_arn = notebook_instance.arn
report.status = "PASS"
report.status_extended = f"Sagemaker notebook instance {notebook_instance.name} has data encryption enabled"
if not notebook_instance.kms_key_id:
report.status = "FAIL"
report.status_extended = f"Sagemaker notebook instance {notebook_instance.name} has data encryption disabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,82 @@
from re import search
from unittest import mock
from uuid import uuid4
from providers.aws.services.sagemaker.sagemaker_service import NotebookInstance
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_notebook_instance = "test-notebook-instance"
notebook_instance_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:notebook-instance/{test_notebook_instance}"
kms_key = str(uuid4())
class Test_sagemaker_notebook_instance_encryption_enabled:
def test_no_instances(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_encryption_enabled.sagemaker_notebook_instance_encryption_enabled import (
sagemaker_notebook_instance_encryption_enabled,
)
check = sagemaker_notebook_instance_encryption_enabled()
result = check.execute()
assert len(result) == 0
def test_instance_with_kms_key(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
sagemaker_client.sagemaker_notebook_instances.append(
NotebookInstance(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
kms_key_id=kms_key,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_encryption_enabled.sagemaker_notebook_instance_encryption_enabled import (
sagemaker_notebook_instance_encryption_enabled,
)
check = sagemaker_notebook_instance_encryption_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search("has data encryption enabled", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn
def test_instance_no_kms_key(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
sagemaker_client.sagemaker_notebook_instances.append(
NotebookInstance(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_encryption_enabled.sagemaker_notebook_instance_encryption_enabled import (
sagemaker_notebook_instance_encryption_enabled,
)
check = sagemaker_notebook_instance_encryption_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search("has data encryption disabled", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_notebook_instance_root_access_disabled",
"CheckTitle": "Check if Amazon SageMaker Notebook instances have root access disabled",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:notebook-instance",
"Severity": "medium",
"ResourceType": "AwsSageMakerNotebookInstance",
"Description": "Check if Amazon SageMaker Notebook instances have root access disabled",
"Risk": "Users with root access have administrator privileges; users can access and edit all files on a notebook instance with root access enabled",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-root-access.html",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Set the RootAccess field to Disabled. You can also disable root access for users when you create or update a notebook instance in the Amazon SageMaker console.",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-root-access.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,21 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_notebook_instance_root_access_disabled(Check):
def execute(self):
findings = []
for notebook_instance in sagemaker_client.sagemaker_notebook_instances:
report = Check_Report(self.metadata)
report.region = notebook_instance.region
report.resource_id = notebook_instance.name
report.resource_arn = notebook_instance.arn
report.status = "PASS"
report.status_extended = f"Sagemaker notebook instance {notebook_instance.name} has root access disabled"
if notebook_instance.root_access:
report.status = "FAIL"
report.status_extended = f"Sagemaker notebook instance {notebook_instance.name} has root access enabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,81 @@
from re import search
from unittest import mock
from providers.aws.services.sagemaker.sagemaker_service import NotebookInstance
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_notebook_instance = "test-notebook-instance"
notebook_instance_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:notebook-instance/{test_notebook_instance}"
class Test_sagemaker_notebook_instance_root_access_disabled:
def test_no_instances(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_root_access_disabled.sagemaker_notebook_instance_root_access_disabled import (
sagemaker_notebook_instance_root_access_disabled,
)
check = sagemaker_notebook_instance_root_access_disabled()
result = check.execute()
assert len(result) == 0
def test_instance_root_access_disabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
sagemaker_client.sagemaker_notebook_instances.append(
NotebookInstance(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
root_access=False,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_root_access_disabled.sagemaker_notebook_instance_root_access_disabled import (
sagemaker_notebook_instance_root_access_disabled,
)
check = sagemaker_notebook_instance_root_access_disabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search("has root access disabled", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn
def test_instance_root_access_enabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
sagemaker_client.sagemaker_notebook_instances.append(
NotebookInstance(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
root_access=True,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_root_access_disabled.sagemaker_notebook_instance_root_access_disabled import (
sagemaker_notebook_instance_root_access_disabled,
)
check = sagemaker_notebook_instance_root_access_disabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search("has root access enabled", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_notebook_instance_vpc_settings_configured",
"CheckTitle": "Check if Amazon SageMaker Notebook instances have VPC settings configured",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:notebook-instance",
"Severity": "medium",
"ResourceType": "AwsSageMakerNotebookInstance",
"Description": "Check if Amazon SageMaker Notebook instances have VPC settings configured",
"Risk": "This could provide an avenue for unauthorized access to your data.",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/studio-notebooks-and-internet-access.html",
"Remediation": {
"Code": {
"CLI": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/SageMaker/notebook-instance-in-vpc.html",
"NativeIaC": "",
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/SageMaker/notebook-instance-in-vpc.html",
"Terraform": ""
},
"Recommendation": {
"Text": "Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing..",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/studio-notebooks-and-internet-access.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,23 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_notebook_instance_vpc_settings_configured(Check):
def execute(self):
findings = []
for notebook_instance in sagemaker_client.sagemaker_notebook_instances:
report = Check_Report(self.metadata)
report.region = notebook_instance.region
report.resource_id = notebook_instance.name
report.resource_arn = notebook_instance.arn
report.status = "PASS"
report.status_extended = (
f"Sagemaker notebook instance {notebook_instance.name} is in a VPC"
)
if not notebook_instance.subnet_id:
report.status = "FAIL"
report.status_extended = f"Sagemaker notebook instance {notebook_instance.name} has VPC settings disabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,83 @@
from re import search
from unittest import mock
from uuid import uuid4
from providers.aws.services.sagemaker.sagemaker_service import NotebookInstance
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_notebook_instance = "test-notebook-instance"
notebook_instance_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:notebook-instance/{test_notebook_instance}"
subnet_id = "subnet-" + str(uuid4())
class Test_sagemaker_notebook_instance_vpc_settings_configured:
def test_no_instances(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_vpc_settings_configured.sagemaker_notebook_instance_vpc_settings_configured import (
sagemaker_notebook_instance_vpc_settings_configured,
)
check = sagemaker_notebook_instance_vpc_settings_configured()
result = check.execute()
assert len(result) == 0
def test_instance_vpc_settings_configured(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
sagemaker_client.sagemaker_notebook_instances.append(
NotebookInstance(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
subnet_id=subnet_id,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_vpc_settings_configured.sagemaker_notebook_instance_vpc_settings_configured import (
sagemaker_notebook_instance_vpc_settings_configured,
)
check = sagemaker_notebook_instance_vpc_settings_configured()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search("is in a VPC", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn
def test_instance_vpc_settings_not_configured(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
sagemaker_client.sagemaker_notebook_instances.append(
NotebookInstance(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
root_access=True,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_vpc_settings_configured.sagemaker_notebook_instance_vpc_settings_configured import (
sagemaker_notebook_instance_vpc_settings_configured,
)
check = sagemaker_notebook_instance_vpc_settings_configured()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search("has VPC settings disabled", result[0].status_extended)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_notebook_instance_without_direct_internet_access_configured",
"CheckTitle": "Check if Amazon SageMaker Notebook instances have direct internet access",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:notebook-instance",
"Severity": "medium",
"ResourceType": "AwsSageMakerNotebookInstance",
"Description": "Check if Amazon SageMaker Notebook instances have direct internet access",
"Risk": "This could provide an avenue for unauthorized access to your data.",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html",
"Remediation": {
"Code": {
"CLI": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/SageMaker/notebook-direct-internet-access.html",
"NativeIaC": "",
"Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/SageMaker/notebook-direct-internet-access.html",
"Terraform": "https://docs.bridgecrew.io/docs/ensure-that-direct-internet-access-is-disabled-for-an-amazon-sagemaker-notebook-instance#fix---buildtime"
},
"Recommendation": {
"Text": "Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,21 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_notebook_instance_without_direct_internet_access_configured(Check):
def execute(self):
findings = []
for notebook_instance in sagemaker_client.sagemaker_notebook_instances:
report = Check_Report(self.metadata)
report.region = notebook_instance.region
report.resource_id = notebook_instance.name
report.resource_arn = notebook_instance.arn
report.status = "PASS"
report.status_extended = f"Sagemaker notebook instance {notebook_instance.name} has direct internet access disabled"
if notebook_instance.direct_internet_access:
report.status = "FAIL"
report.status_extended = f"Sagemaker notebook instance {notebook_instance.name} has direct internet access enabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,91 @@
from re import search
from unittest import mock
from providers.aws.services.sagemaker.sagemaker_service import NotebookInstance
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_notebook_instance = "test-notebook-instance"
notebook_instance_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:notebook-instance/{test_notebook_instance}"
class Test_sagemaker_notebook_instance_without_direct_internet_access_configured:
def test_no_instances(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_without_direct_internet_access_configured.sagemaker_notebook_instance_without_direct_internet_access_configured import (
sagemaker_notebook_instance_without_direct_internet_access_configured,
)
check = (
sagemaker_notebook_instance_without_direct_internet_access_configured()
)
result = check.execute()
assert len(result) == 0
def test_instance_direct_internet_disabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
sagemaker_client.sagemaker_notebook_instances.append(
NotebookInstance(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
direct_internet_access=False,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_without_direct_internet_access_configured.sagemaker_notebook_instance_without_direct_internet_access_configured import (
sagemaker_notebook_instance_without_direct_internet_access_configured,
)
check = (
sagemaker_notebook_instance_without_direct_internet_access_configured()
)
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search(
"has direct internet access disabled", result[0].status_extended
)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn
def test_instance_direct_internet_enabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_notebook_instances = []
sagemaker_client.sagemaker_notebook_instances.append(
NotebookInstance(
name=test_notebook_instance,
arn=notebook_instance_arn,
region=AWS_REGION,
direct_internet_access=True,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_notebook_instance_without_direct_internet_access_configured.sagemaker_notebook_instance_without_direct_internet_access_configured import (
sagemaker_notebook_instance_without_direct_internet_access_configured,
)
check = (
sagemaker_notebook_instance_without_direct_internet_access_configured()
)
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search(
"has direct internet access enabled", result[0].status_extended
)
assert result[0].resource_id == test_notebook_instance
assert result[0].resource_arn == notebook_instance_arn

View File

@@ -0,0 +1,203 @@
import threading
from pydantic import BaseModel
from lib.logger import logger
from providers.aws.aws_provider import generate_regional_clients
################################ SageMaker
class SageMaker:
def __init__(self, audit_info):
self.service = "sagemaker"
self.session = audit_info.audit_session
self.regional_clients = generate_regional_clients(self.service, audit_info)
self.sagemaker_notebook_instances = []
self.sagemaker_models = []
self.sagemaker_training_jobs = []
self.__threading_call__(self.__list_notebook_instances__)
self.__threading_call__(self.__list_models__)
self.__threading_call__(self.__list_training_jobs__)
self.__describe_model__(self.regional_clients)
self.__describe_notebook_instance__(self.regional_clients)
self.__describe_training_job__(self.regional_clients)
def __get_session__(self):
return self.session
def __threading_call__(self, call):
threads = []
for regional_client in self.regional_clients.values():
threads.append(threading.Thread(target=call, args=(regional_client,)))
for t in threads:
t.start()
for t in threads:
t.join()
def __list_notebook_instances__(self, regional_client):
logger.info("SageMaker - listing notebook instances...")
try:
list_notebook_instances_paginator = regional_client.get_paginator(
"list_notebook_instances"
)
for page in list_notebook_instances_paginator.paginate():
for notebook_instance in page["NotebookInstances"]:
self.sagemaker_notebook_instances.append(
NotebookInstance(
name=notebook_instance["NotebookInstanceName"],
region=regional_client.region,
arn=notebook_instance["NotebookInstanceArn"],
)
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __list_models__(self, regional_client):
logger.info("SageMaker - listing models...")
try:
list_models_paginator = regional_client.get_paginator("list_models")
for page in list_models_paginator.paginate():
for model in page["Models"]:
self.sagemaker_models.append(
Model(
name=model["ModelName"],
region=regional_client.region,
arn=model["ModelArn"],
)
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __list_training_jobs__(self, regional_client):
logger.info("SageMaker - listing training jobs...")
try:
list_training_jobs_paginator = regional_client.get_paginator(
"list_training_jobs"
)
for page in list_training_jobs_paginator.paginate():
for training_job in page["TrainingJobSummaries"]:
self.sagemaker_training_jobs.append(
TrainingJob(
name=training_job["TrainingJobName"],
region=regional_client.region,
arn=training_job["TrainingJobArn"],
)
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __describe_notebook_instance__(self, regional_clients):
logger.info("SageMaker - describing notebook instances...")
try:
for notebook_instance in self.sagemaker_notebook_instances:
regional_client = regional_clients[notebook_instance.region]
describe_notebook_instance = regional_client.describe_notebook_instance(
NotebookInstanceName=notebook_instance.name
)
if (
"RootAccess" in describe_notebook_instance
and describe_notebook_instance["RootAccess"] == "Enabled"
):
notebook_instance.root_access = True
if "SubnetId" in describe_notebook_instance:
notebook_instance.subnet_id = describe_notebook_instance["SubnetId"]
if (
"DirectInternetAccess" in describe_notebook_instance
and describe_notebook_instance["RootAccess"] == "Enabled"
):
notebook_instance.direct_internet_access = True
if "KmsKeyId" in describe_notebook_instance:
notebook_instance.kms_key_id = describe_notebook_instance[
"KmsKeyId"
]
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __describe_model__(self, regional_clients):
logger.info("SageMaker - describing models...")
try:
for model in self.sagemaker_models:
regional_client = regional_clients[model.region]
describe_model = regional_client.describe_model(ModelName=model.name)
if "EnableNetworkIsolation" in describe_model:
model.network_isolation = describe_model["EnableNetworkIsolation"]
if (
"VpcConfig" in describe_model
and "Subnets" in describe_model["VpcConfig"]
):
model.vpc_config_subnets = describe_model["VpcConfig"]["Subnets"]
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __describe_training_job__(self, regional_clients):
logger.info("SageMaker - describing training jobs...")
try:
for training_job in self.sagemaker_training_jobs:
regional_client = regional_clients[training_job.region]
describe_training_job = regional_client.describe_training_job(
TrainingJobName=training_job.name
)
if "EnableInterContainerTrafficEncryption" in describe_training_job:
training_job.container_traffic_encryption = describe_training_job[
"EnableInterContainerTrafficEncryption"
]
if (
"ResourceConfig" in describe_training_job
and "VolumeKmsKeyId" in describe_training_job["ResourceConfig"]
):
training_job.volume_kms_key_id = describe_training_job[
"ResourceConfig"
]["VolumeKmsKeyId"]
if "EnableNetworkIsolation" in describe_training_job:
training_job.network_isolation = describe_training_job[
"EnableNetworkIsolation"
]
if (
"VpcConfig" in describe_training_job
and "Subnets" in describe_training_job["VpcConfig"]
):
training_job.vpc_config_subnets = describe_training_job[
"VpcConfig"
]["Subnets"]
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
class NotebookInstance(BaseModel):
name: str
region: str
arn: str
root_access: bool = None
subnet_id: str = None
direct_internet_access: bool = None
kms_key_id: str = None
class Model(BaseModel):
name: str
region: str
arn: str
network_isolation: bool = None
vpc_config_subnets: list[str] = []
class TrainingJob(BaseModel):
name: str
region: str
arn: str
container_traffic_encryption: bool = None
volume_kms_key_id: str = None
network_isolation: bool = None
vpc_config_subnets: list[str] = []

View File

@@ -0,0 +1,194 @@
from unittest.mock import patch
from uuid import uuid4
import botocore
from boto3 import session
from providers.aws.lib.audit_info.models import AWS_Audit_Info
from providers.aws.services.sagemaker.sagemaker_service import SageMaker
AWS_ACCOUNT_NUMBER = 123456789012
AWS_REGION = "eu-west-1"
test_notebook_instance = "test-notebook-instance"
notebook_instance_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:notebook-instance/{test_notebook_instance}"
test_model = "test-model"
test_arn_model = (
f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:model/{test_model}"
)
test_training_job = "test-training-job"
test_arn_training_job = (
f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:training-job/{test_model}"
)
subnet_id = "subnet-" + str(uuid4())
kms_key_id = str(uuid4())
make_api_call = botocore.client.BaseClient._make_api_call
def mock_make_api_call(self, operation_name, kwarg):
if operation_name == "ListNotebookInstances":
return {
"NotebookInstances": [
{
"NotebookInstanceName": test_notebook_instance,
"NotebookInstanceArn": notebook_instance_arn,
},
]
}
if operation_name == "ListModels":
return {
"Models": [
{
"ModelName": test_model,
"ModelArn": test_arn_model,
},
]
}
if operation_name == "ListTrainingJobs":
return {
"TrainingJobSummaries": [
{
"TrainingJobName": test_training_job,
"TrainingJobArn": test_arn_training_job,
},
]
}
if operation_name == "DescribeNotebookInstance":
return {
"SubnetId": subnet_id,
"KmsKeyId": kms_key_id,
"DirectInternetAccess": "Enabled",
"RootAccess": "Enabled",
}
if operation_name == "DescribeModel":
return {
"VpcConfig": {
"Subnets": [
subnet_id,
]
},
"EnableNetworkIsolation": True,
}
if operation_name == "DescribeTrainingJob":
return {
"ResourceConfig": {
"VolumeKmsKeyId": kms_key_id,
},
"VpcConfig": {
"Subnets": [
subnet_id,
]
},
"EnableNetworkIsolation": True,
"EnableInterContainerTrafficEncryption": True,
}
return make_api_call(self, operation_name, kwarg)
def mock_generate_regional_clients(service, audit_info):
regional_client = audit_info.audit_session.client(service, region_name=AWS_REGION)
regional_client.region = AWS_REGION
return {AWS_REGION: regional_client}
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
@patch(
"providers.aws.services.sagemaker.sagemaker_service.generate_regional_clients",
new=mock_generate_regional_clients,
)
class Test_SageMaker_Service:
# Mocked Audit Info
def set_mocked_audit_info(self):
audit_info = AWS_Audit_Info(
original_session=None,
audit_session=session.Session(
profile_name=None,
botocore_session=None,
),
audited_account=AWS_ACCOUNT_NUMBER,
audited_user_id=None,
audited_partition="aws",
audited_identity_arn=None,
profile=None,
profile_region=None,
credentials=None,
assumed_role_info=None,
audited_regions=None,
organizations_metadata=None,
)
return audit_info
# Test SageMaker Service
def test_service(self):
audit_info = self.set_mocked_audit_info()
sagemaker = SageMaker(audit_info)
assert sagemaker.service == "sagemaker"
# Test SageMaker client
def test_client(self):
audit_info = self.set_mocked_audit_info()
sagemaker = SageMaker(audit_info)
for reg_client in sagemaker.regional_clients.values():
assert reg_client.__class__.__name__ == "SageMaker"
# Test SageMaker session
def test__get_session__(self):
audit_info = self.set_mocked_audit_info()
sagemaker = SageMaker(audit_info)
assert sagemaker.session.__class__.__name__ == "Session"
# Test SageMaker list notebook instances
def test_list_notebook_instances(self):
audit_info = self.set_mocked_audit_info()
sagemaker = SageMaker(audit_info)
assert len(sagemaker.sagemaker_notebook_instances) == 1
assert sagemaker.sagemaker_notebook_instances[0].name == test_notebook_instance
assert sagemaker.sagemaker_notebook_instances[0].arn == notebook_instance_arn
assert sagemaker.sagemaker_notebook_instances[0].region == AWS_REGION
# Test SageMaker list models
def test_list_models(self):
audit_info = self.set_mocked_audit_info()
sagemaker = SageMaker(audit_info)
assert len(sagemaker.sagemaker_models) == 1
assert sagemaker.sagemaker_models[0].name == test_model
assert sagemaker.sagemaker_models[0].arn == test_arn_model
assert sagemaker.sagemaker_models[0].region == AWS_REGION
# Test SageMaker list training jobs
def test_list_training_jobs(self):
audit_info = self.set_mocked_audit_info()
sagemaker = SageMaker(audit_info)
assert len(sagemaker.sagemaker_training_jobs) == 1
assert sagemaker.sagemaker_training_jobs[0].name == test_training_job
assert sagemaker.sagemaker_training_jobs[0].arn == test_arn_training_job
assert sagemaker.sagemaker_training_jobs[0].region == AWS_REGION
# Test SageMaker describe notebook instance
def test_describe_notebook_instance(self):
audit_info = self.set_mocked_audit_info()
sagemaker = SageMaker(audit_info)
assert len(sagemaker.sagemaker_notebook_instances) == 1
assert sagemaker.sagemaker_notebook_instances[0].root_access
assert sagemaker.sagemaker_notebook_instances[0].subnet_id == subnet_id
assert sagemaker.sagemaker_notebook_instances[0].direct_internet_access
assert sagemaker.sagemaker_notebook_instances[0].kms_key_id == kms_key_id
# Test SageMaker describe model
def test_describe_model(self):
audit_info = self.set_mocked_audit_info()
sagemaker = SageMaker(audit_info)
assert len(sagemaker.sagemaker_models) == 1
assert sagemaker.sagemaker_models[0].network_isolation
assert sagemaker.sagemaker_models[0].vpc_config_subnets == [subnet_id]
# Test SageMaker describe training jobs
def test_describe_training_jobs(self):
audit_info = self.set_mocked_audit_info()
sagemaker = SageMaker(audit_info)
assert len(sagemaker.sagemaker_training_jobs) == 1
assert sagemaker.sagemaker_training_jobs[0].container_traffic_encryption
assert sagemaker.sagemaker_training_jobs[0].network_isolation
assert sagemaker.sagemaker_training_jobs[0].volume_kms_key_id == kms_key_id
assert sagemaker.sagemaker_training_jobs[0].vpc_config_subnets == [subnet_id]

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_training_jobs_intercontainer_encryption_enabled",
"CheckTitle": "Check if Amazon SageMaker Training jobs have intercontainer encryption enabled",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:training-job",
"Severity": "medium",
"ResourceType": "AwsSageMakerTrainingJob",
"Description": "Check if Amazon SageMaker Training jobs have intercontainer encryption enabled",
"Risk": "If not restricted unintended access could happen.",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Internetwork communications support TLS 1.2 encryption between all components and clients.",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,21 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_training_jobs_intercontainer_encryption_enabled(Check):
def execute(self):
findings = []
for training_job in sagemaker_client.sagemaker_training_jobs:
report = Check_Report(self.metadata)
report.region = training_job.region
report.resource_id = training_job.name
report.resource_arn = training_job.arn
report.status = "PASS"
report.status_extended = f"Sagemaker training job {training_job.name} has intercontainer encryption enabled"
if not training_job.container_traffic_encryption:
report.status = "FAIL"
report.status_extended = f"Sagemaker training job {training_job.name} has intercontainer encryption disabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,84 @@
from re import search
from unittest import mock
from providers.aws.services.sagemaker.sagemaker_service import TrainingJob
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_training_job = "test-training-job"
training_job_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:training-job/{test_training_job}"
class Test_sagemaker_training_jobs_intercontainer_encryption_enabled:
def test_no_training_jobs(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_intercontainer_encryption_enabled.sagemaker_training_jobs_intercontainer_encryption_enabled import (
sagemaker_training_jobs_intercontainer_encryption_enabled,
)
check = sagemaker_training_jobs_intercontainer_encryption_enabled()
result = check.execute()
assert len(result) == 0
def test_instance_traffic_encryption_enabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
sagemaker_client.sagemaker_training_jobs.append(
TrainingJob(
name=test_training_job,
arn=training_job_arn,
region=AWS_REGION,
container_traffic_encryption=True,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_intercontainer_encryption_enabled.sagemaker_training_jobs_intercontainer_encryption_enabled import (
sagemaker_training_jobs_intercontainer_encryption_enabled,
)
check = sagemaker_training_jobs_intercontainer_encryption_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search(
"has intercontainer encryption enabled", result[0].status_extended
)
assert result[0].resource_id == test_training_job
assert result[0].resource_arn == training_job_arn
def test_instance_traffic_encryption_disabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
sagemaker_client.sagemaker_training_jobs.append(
TrainingJob(
name=test_training_job,
arn=training_job_arn,
region=AWS_REGION,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_intercontainer_encryption_enabled.sagemaker_training_jobs_intercontainer_encryption_enabled import (
sagemaker_training_jobs_intercontainer_encryption_enabled,
)
check = sagemaker_training_jobs_intercontainer_encryption_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search(
"has intercontainer encryption disabled", result[0].status_extended
)
assert result[0].resource_id == test_training_job
assert result[0].resource_arn == training_job_arn

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_training_jobs_network_isolation_enabled",
"CheckTitle": "Check if Amazon SageMaker Training jobs have network isolation enabled",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:training-job",
"Severity": "medium",
"ResourceType": "AwsSageMakerTrainingJob",
"Description": "Check if Amazon SageMaker Training jobs have network isolation enabled",
"Risk": "This could provide an avenue for unauthorized access to your data.",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,21 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_training_jobs_network_isolation_enabled(Check):
def execute(self):
findings = []
for training_job in sagemaker_client.sagemaker_training_jobs:
report = Check_Report(self.metadata)
report.region = training_job.region
report.resource_id = training_job.name
report.resource_arn = training_job.arn
report.status = "PASS"
report.status_extended = f"Sagemaker training job {training_job.name} has network isolation enabled"
if not training_job.network_isolation:
report.status = "FAIL"
report.status_extended = f"Sagemaker training job {training_job.name} has network isolation disabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,82 @@
from re import search
from unittest import mock
from uuid import uuid4
from providers.aws.services.sagemaker.sagemaker_service import TrainingJob
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_training_job = "test-training-job"
training_job_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:training-job/{test_training_job}"
kms_key_id = str(uuid4())
class Test_sagemaker_training_jobs_network_isolation_enabled:
def test_no_training_jobs(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_network_isolation_enabled.sagemaker_training_jobs_network_isolation_enabled import (
sagemaker_training_jobs_network_isolation_enabled,
)
check = sagemaker_training_jobs_network_isolation_enabled()
result = check.execute()
assert len(result) == 0
def test_instance_traffic_encryption_enabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
sagemaker_client.sagemaker_training_jobs.append(
TrainingJob(
name=test_training_job,
arn=training_job_arn,
region=AWS_REGION,
network_isolation=True,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_network_isolation_enabled.sagemaker_training_jobs_network_isolation_enabled import (
sagemaker_training_jobs_network_isolation_enabled,
)
check = sagemaker_training_jobs_network_isolation_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search("has network isolation enabled", result[0].status_extended)
assert result[0].resource_id == test_training_job
assert result[0].resource_arn == training_job_arn
def test_instance_traffic_encryption_disabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
sagemaker_client.sagemaker_training_jobs.append(
TrainingJob(
name=test_training_job,
arn=training_job_arn,
region=AWS_REGION,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_network_isolation_enabled.sagemaker_training_jobs_network_isolation_enabled import (
sagemaker_training_jobs_network_isolation_enabled,
)
check = sagemaker_training_jobs_network_isolation_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search("has network isolation disabled", result[0].status_extended)
assert result[0].resource_id == test_training_job
assert result[0].resource_arn == training_job_arn

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_training_jobs_volume_and_output_encryption_enabled",
"CheckTitle": "Check if Amazon SageMaker Training jobs have volume and output with KMS encryption enabled",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:training-job",
"Severity": "medium",
"ResourceType": "AwsSageMakerTrainingJob",
"Description": "Check if Amazon SageMaker Training jobs have volume and output with KMS encryption enabled",
"Risk": "Data exfiltration could happen if information is not protected. KMS keys provide additional security level to IAM policies.",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/key-management.html",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Specify AWS KMS keys to use for input and output from S3 and EBS.",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/key-management.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,23 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_training_jobs_volume_and_output_encryption_enabled(Check):
def execute(self):
findings = []
for training_job in sagemaker_client.sagemaker_training_jobs:
report = Check_Report(self.metadata)
report.region = training_job.region
report.resource_id = training_job.name
report.resource_arn = training_job.arn
report.status = "PASS"
report.status_extended = (
f"Sagemaker training job {training_job.name} has KMS encryption enabled"
)
if not training_job.volume_kms_key_id:
report.status = "FAIL"
report.status_extended = f"Sagemaker training job {training_job.name} has KMS encryption disabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,82 @@
from re import search
from unittest import mock
from uuid import uuid4
from providers.aws.services.sagemaker.sagemaker_service import TrainingJob
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_training_job = "test-training-job"
training_job_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:training-job/{test_training_job}"
kms_key_id = str(uuid4())
class Test_sagemaker_training_jobs_volume_and_output_encryption_enabled:
def test_no_training_jobs(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_volume_and_output_encryption_enabled.sagemaker_training_jobs_volume_and_output_encryption_enabled import (
sagemaker_training_jobs_volume_and_output_encryption_enabled,
)
check = sagemaker_training_jobs_volume_and_output_encryption_enabled()
result = check.execute()
assert len(result) == 0
def test_instance_traffic_encryption_enabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
sagemaker_client.sagemaker_training_jobs.append(
TrainingJob(
name=test_training_job,
arn=training_job_arn,
region=AWS_REGION,
volume_kms_key_id=kms_key_id,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_volume_and_output_encryption_enabled.sagemaker_training_jobs_volume_and_output_encryption_enabled import (
sagemaker_training_jobs_volume_and_output_encryption_enabled,
)
check = sagemaker_training_jobs_volume_and_output_encryption_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search("has KMS encryption enabled", result[0].status_extended)
assert result[0].resource_id == test_training_job
assert result[0].resource_arn == training_job_arn
def test_instance_traffic_encryption_disabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
sagemaker_client.sagemaker_training_jobs.append(
TrainingJob(
name=test_training_job,
arn=training_job_arn,
region=AWS_REGION,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_volume_and_output_encryption_enabled.sagemaker_training_jobs_volume_and_output_encryption_enabled import (
sagemaker_training_jobs_volume_and_output_encryption_enabled,
)
check = sagemaker_training_jobs_volume_and_output_encryption_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search("has KMS encryption disabled", result[0].status_extended)
assert result[0].resource_id == test_training_job
assert result[0].resource_arn == training_job_arn

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "sagemaker_training_jobs_vpc_settings_configured",
"CheckTitle": "Check if Amazon SageMaker Training job have VPC settings configured.",
"CheckType": [],
"ServiceName": "sagemaker",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:sagemaker:region:account-id:training-job",
"Severity": "medium",
"ResourceType": "AwsSageMakerTrainingJob",
"Description": "Check if Amazon SageMaker Training job have VPC settings configured.",
"Risk": "This could provide an avenue for unauthorized access to your data.",
"RelatedUrl": "https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Restrict which traffic can access by launching Studio in a Virtual Private Cloud (VPC) of your choosing.",
"Url": "https://docs.aws.amazon.com/sagemaker/latest/dg/interface-vpc-endpoint.html"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,21 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.sagemaker.sagemaker_client import sagemaker_client
class sagemaker_training_jobs_vpc_settings_configured(Check):
def execute(self):
findings = []
for training_job in sagemaker_client.sagemaker_training_jobs:
report = Check_Report(self.metadata)
report.region = training_job.region
report.resource_id = training_job.name
report.resource_arn = training_job.arn
report.status = "PASS"
report.status_extended = f"Sagemaker training job {training_job.name} has VPC settings for the training job volume and output enabled"
if not training_job.vpc_config_subnets:
report.status = "FAIL"
report.status_extended = f"Sagemaker training job {training_job.name} has VPC settings for the training job volume and output disabled"
findings.append(report)
return findings

View File

@@ -0,0 +1,88 @@
from re import search
from unittest import mock
from uuid import uuid4
from providers.aws.services.sagemaker.sagemaker_service import TrainingJob
AWS_REGION = "eu-west-1"
AWS_ACCOUNT_NUMBER = "123456789012"
test_training_job = "test-training-job"
training_job_arn = f"arn:aws:sagemaker:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:training-job/{test_training_job}"
subnet_id = "subnet-" + str(uuid4())
class Test_sagemaker_training_jobs_vpc_settings_configured:
def test_no_training_jobs(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_vpc_settings_configured.sagemaker_training_jobs_vpc_settings_configured import (
sagemaker_training_jobs_vpc_settings_configured,
)
check = sagemaker_training_jobs_vpc_settings_configured()
result = check.execute()
assert len(result) == 0
def test_instance_traffic_encryption_enabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
sagemaker_client.sagemaker_training_jobs.append(
TrainingJob(
name=test_training_job,
arn=training_job_arn,
region=AWS_REGION,
vpc_config_subnets=[subnet_id],
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_vpc_settings_configured.sagemaker_training_jobs_vpc_settings_configured import (
sagemaker_training_jobs_vpc_settings_configured,
)
check = sagemaker_training_jobs_vpc_settings_configured()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert search(
"has VPC settings for the training job volume and output enabled",
result[0].status_extended,
)
assert result[0].resource_id == test_training_job
assert result[0].resource_arn == training_job_arn
def test_instance_traffic_encryption_disabled(self):
sagemaker_client = mock.MagicMock
sagemaker_client.sagemaker_training_jobs = []
sagemaker_client.sagemaker_training_jobs.append(
TrainingJob(
name=test_training_job,
arn=training_job_arn,
region=AWS_REGION,
)
)
with mock.patch(
"providers.aws.services.sagemaker.sagemaker_service.SageMaker",
sagemaker_client,
):
from providers.aws.services.sagemaker.sagemaker_training_jobs_vpc_settings_configured.sagemaker_training_jobs_vpc_settings_configured import (
sagemaker_training_jobs_vpc_settings_configured,
)
check = sagemaker_training_jobs_vpc_settings_configured()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert search(
"has VPC settings for the training job volume and output disabled",
result[0].status_extended,
)
assert result[0].resource_id == test_training_job
assert result[0].resource_arn == training_job_arn