SageMaker Notebook Instance Direct Internet Access Disabled
Overview
This check verifies that Amazon SageMaker notebook instances have direct internet access disabled. When disabled, notebooks can only communicate through your Virtual Private Cloud (VPC), giving you control over what network traffic enters and leaves the instance.
Risk
If direct internet access is enabled, your notebook instance can freely communicate with the internet. This creates several security risks:
- Data exfiltration: Sensitive data or model information could be sent to external servers
- Malware downloads: Malicious code could be downloaded and executed
- Supply chain attacks: Unverified packages could be installed from public repositories
- Command-and-control: A compromised notebook could receive instructions from attackers
Severity: High
Remediation Steps
Prerequisites
- AWS account access with permissions to modify SageMaker notebook instances
- A VPC with a private subnet configured
- A security group for the notebook instance
Important: The DirectInternetAccess setting cannot be changed on an existing notebook instance. You must create a new notebook instance with the correct settings and migrate your work.
Setting up VPC infrastructure (if needed)
If you do not already have a private subnet and security group, you will need to create them first:
- Create or identify a VPC with private subnets
- Create a security group that allows necessary outbound traffic
- Set up VPC endpoints for AWS services your notebook needs to access (S3, SageMaker API, CloudWatch Logs, etc.)
For notebooks to function without internet access, you typically need these VPC endpoints:
com.amazonaws.us-east-1.sagemaker.apicom.amazonaws.us-east-1.sagemaker.runtimecom.amazonaws.us-east-1.s3(Gateway endpoint)com.amazonaws.us-east-1.logs(for CloudWatch)
AWS Console Method
-
Open the SageMaker console at https://console.aws.amazon.com/sagemaker/
-
Navigate to Notebook instances in the left navigation panel
-
If you have an existing notebook to migrate:
- Select the notebook instance
- Click Stop and wait for the status to change to "Stopped"
- Note down the current configuration (instance type, volume size, IAM role, etc.)
- Download any notebooks or data you want to preserve
-
Create a new notebook instance:
- Click Create notebook instance
- Enter a Notebook instance name
- Select an Instance type (e.g., ml.t3.medium)
- Choose or create an IAM role with appropriate permissions
-
Configure network settings:
- Expand the Network section
- For VPC, select your VPC
- For Subnet, select a private subnet (one without a route to an internet gateway)
- For Security group(s), select an appropriate security group
- For Direct internet access, select Disable
-
Complete the creation:
- Configure any additional settings (volume size, lifecycle configuration, etc.)
- Click Create notebook instance
-
Upload your saved notebooks to the new instance once it is running
AWS CLI (optional)
List existing notebook instances and check their configuration:
# List all notebook instances
aws sagemaker list-notebook-instances \
--region us-east-1 \
--query 'NotebookInstances[*].[NotebookInstanceName,NotebookInstanceStatus,DirectInternetAccess]' \
--output table
# Get detailed information about a specific instance
aws sagemaker describe-notebook-instance \
--notebook-instance-name <your-notebook-name> \
--region us-east-1
Stop an existing notebook instance (if migrating):
aws sagemaker stop-notebook-instance \
--notebook-instance-name <your-notebook-name> \
--region us-east-1
Create a new notebook instance with direct internet access disabled:
aws sagemaker create-notebook-instance \
--notebook-instance-name my-secure-notebook \
--instance-type ml.t3.medium \
--role-arn arn:aws:iam::<account-id>:role/<sagemaker-execution-role> \
--subnet-id subnet-xxxxxxxxxxxxxxxxx \
--security-group-ids sg-xxxxxxxxxxxxxxxxx \
--direct-internet-access Disabled \
--volume-size-in-gb 20 \
--region us-east-1
Replace the following placeholders:
<account-id>: Your AWS account ID<sagemaker-execution-role>: IAM role name for SageMaker executionsubnet-xxxxxxxxxxxxxxxxx: Your private subnet IDsg-xxxxxxxxxxxxxxxxx: Your security group ID
CloudFormation (optional)
AWSTemplateFormatVersion: '2010-09-09'
Description: SageMaker Notebook Instance with Direct Internet Access Disabled
Parameters:
NotebookInstanceName:
Type: String
Description: Name for the SageMaker notebook instance
Default: my-secure-notebook
InstanceType:
Type: String
Description: ML compute instance type
Default: ml.t3.medium
AllowedValues:
- ml.t3.medium
- ml.t3.large
- ml.t3.xlarge
- ml.m5.xlarge
- ml.m5.2xlarge
SubnetId:
Type: AWS::EC2::Subnet::Id
Description: Subnet ID for the notebook instance (must be a private subnet)
SecurityGroupId:
Type: AWS::EC2::SecurityGroup::Id
Description: Security group ID for the notebook instance
Resources:
SageMakerExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub '${NotebookInstanceName}-execution-role'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: sagemaker.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSageMakerFullAccess
SageMakerNotebook:
Type: AWS::SageMaker::NotebookInstance
Properties:
NotebookInstanceName: !Ref NotebookInstanceName
InstanceType: !Ref InstanceType
RoleArn: !GetAtt SageMakerExecutionRole.Arn
DirectInternetAccess: Disabled
SubnetId: !Ref SubnetId
SecurityGroupIds:
- !Ref SecurityGroupId
VolumeSizeInGB: 20
Outputs:
NotebookInstanceArn:
Description: ARN of the SageMaker notebook instance
Value: !Ref SageMakerNotebook
NotebookInstanceName:
Description: Name of the SageMaker notebook instance
Value: !Ref NotebookInstanceName
Deploy the stack:
aws cloudformation create-stack \
--stack-name sagemaker-secure-notebook \
--template-body file://template.yaml \
--parameters \
ParameterKey=NotebookInstanceName,ParameterValue=my-secure-notebook \
ParameterKey=SubnetId,ParameterValue=subnet-xxxxxxxxxxxxxxxxx \
ParameterKey=SecurityGroupId,ParameterValue=sg-xxxxxxxxxxxxxxxxx \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1
Terraform (optional)
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
variable "notebook_instance_name" {
description = "Name for the SageMaker notebook instance"
type = string
default = "my-secure-notebook"
}
variable "instance_type" {
description = "ML compute instance type"
type = string
default = "ml.t3.medium"
}
variable "subnet_id" {
description = "Subnet ID for the notebook instance (must be a private subnet)"
type = string
}
variable "security_group_ids" {
description = "List of security group IDs for the notebook instance"
type = list(string)
}
resource "aws_iam_role" "sagemaker_execution_role" {
name = "${var.notebook_instance_name}-execution-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "sagemaker.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}
resource "aws_iam_role_policy_attachment" "sagemaker_full_access" {
role = aws_iam_role.sagemaker_execution_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonSageMakerFullAccess"
}
resource "aws_sagemaker_notebook_instance" "secure_notebook" {
name = var.notebook_instance_name
instance_type = var.instance_type
role_arn = aws_iam_role.sagemaker_execution_role.arn
direct_internet_access = "Disabled"
subnet_id = var.subnet_id
security_groups = var.security_group_ids
volume_size = 20
tags = {
Name = var.notebook_instance_name
Environment = "production"
}
}
output "notebook_instance_arn" {
description = "ARN of the SageMaker notebook instance"
value = aws_sagemaker_notebook_instance.secure_notebook.arn
}
output "notebook_instance_name" {
description = "Name of the SageMaker notebook instance"
value = aws_sagemaker_notebook_instance.secure_notebook.name
}
Deploy with Terraform:
terraform init
terraform plan -var="subnet_id=subnet-xxxxxxxxxxxxxxxxx" -var='security_group_ids=["sg-xxxxxxxxxxxxxxxxx"]'
terraform apply -var="subnet_id=subnet-xxxxxxxxxxxxxxxxx" -var='security_group_ids=["sg-xxxxxxxxxxxxxxxxx"]'
Verification
After creating the notebook instance:
-
In the AWS Console:
- Go to SageMaker > Notebook instances
- Click on your notebook instance name
- In the Network section, confirm Direct internet access shows Disabled
-
Test connectivity (optional):
- Open the notebook instance
- Try to access the internet (e.g.,
!curl https://example.com) - The request should fail or time out, confirming internet access is blocked
CLI verification
aws sagemaker describe-notebook-instance \
--notebook-instance-name my-secure-notebook \
--region us-east-1 \
--query 'DirectInternetAccess' \
--output text
The output should be Disabled.
Additional Resources
- AWS Documentation: SageMaker Notebook Instance Security
- AWS Documentation: Connect to SageMaker Through a VPC Interface Endpoint
- AWS Documentation: VPC Endpoints for Amazon S3
- AWS Well-Architected Framework: Security Pillar
Notes
-
Cannot modify existing instances: The
DirectInternetAccesssetting is immutable after creation. You must create a new notebook instance with the correct setting. -
VPC endpoints required: Without direct internet access, your notebook needs VPC endpoints to reach AWS services. At minimum, configure endpoints for S3 and the SageMaker API.
-
Package installation: With internet access disabled, you cannot install packages from PyPI or Conda directly. Consider:
- Using a NAT Gateway in your VPC (allows controlled outbound internet access)
- Setting up a private PyPI mirror
- Pre-installing packages in a custom lifecycle configuration
- Using AWS CodeArtifact for package management
-
Cost considerations: VPC endpoints have hourly charges and data processing fees. Factor this into your cost planning.
-
Security groups matter: Even with direct internet access disabled, ensure your security groups follow the principle of least privilege. Only allow necessary inbound and outbound traffic.