> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Sagemaker Models Should Have Network Isolation Enabled

### More Info:

Sagemaker Models should have network isolation enabled

### Risk Level

Medium

### Address

Monitoring, Security

### Compliance Standards

* APRA CPS 234 (Australia)
* BSI C5 (Germany)
* Brazil LGPD
* CCPA / CPRA (California)
* CIS Critical Security Controls v8
* CMMC 2.0
* CSA Cloud Controls Matrix v4
* DPDPA
* Digital Operational Resilience Act (EU)
* ISO 27001
* ISO/IEC 27018
* ISO/IEC 27701
* MAS Technology Risk Management (Singapore)
* MITRE ATT\&CK (Cloud)
* NIST SP 800-171
* NYDFS 23 NYCRR 500
* SOC2
* SWIFT Customer Security Controls Framework
* Sarbanes-Oxley IT General Controls
* UK NCSC Cyber Assessment Framework

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        To enable network isolation for SageMaker models using the AWS Management Console, you must create (or recreate) the model with network isolation turned on. It cannot be enabled on an existing model in-place.

        Below are step-by-step instructions.

        ***

        ## 1. Check the existing model (optional)

        1. Sign in to the **AWS Management Console**.
        2. Go to **Amazon SageMaker**.
        3. In the left navigation pane, choose **Inference** → **Models**.
        4. Click on the model name you want to remediate.
        5. On the **Model summary** page, check the configuration:
           * If the model was created without network isolation, you will need to create a new model with the same settings and network isolation enabled.

        ***

        ## 2. Create a new model with Network Isolation enabled

        1. In the SageMaker console, navigate to **Inference** → **Models**.

        2. Click **Create model**.

        3. **Model details**:
           * Enter a **Model name** (e.g., `my-model-ni-enabled`).
           * Optionally add a **Description** and **Tags**.

        4. **Container**:
           * Under **Container definition**, choose:
             * Either **Use an existing container image** (for custom images) or
             * **Use a SageMaker built-in algorithm** (if applicable).
           * Specify:
             * **Container image** URI.
             * **Model artifacts** S3 path (e.g., `s3://bucket/path/to/model.tar.gz`).
           * If using environment variables or container arguments, re-enter them as used in your previous model.

        5. **Network Isolation**:
           * Find the option that says **Network isolation** or **Enable network isolation**.
           * Check or toggle **Enable network isolation**.
             * This ensures the model container cannot make outbound network calls (only allowed to access its storage volume and input/output for the inference service).

        6. **IAM role**:
           * Under **Permissions**, choose an existing SageMaker **execution role** with access to your model artifacts in S3 (or create a new one).
           * Ensure the role has `s3:GetObject` for the model artifact location and any other needed permissions.

        7. Review the configuration.

        8. Click **Create model**.

        ***

        ## 3. Update endpoints or endpoint configurations to use the new model

        If the model is deployed behind an endpoint, you must update the endpoint configuration to point to the new, network-isolated model.

        ### 3.1 Create a new endpoint configuration

        1. In the SageMaker console, go to **Inference** → **Endpoint configurations**.
        2. Click **Create endpoint configuration**.
        3. Enter a **Name** (e.g., `my-endpoint-config-ni-enabled`).
        4. Under **Production variants**:
           * Click **Add model**.
           * Select the **new model** you just created (with network isolation).
           * Set:
             * **Variant name**
             * **Instance type**
             * **Initial instance count**
             * **Initial variant weight** as required.
        5. Adjust any other settings (e.g., data capture, async inference) as needed.
        6. Click **Create endpoint configuration**.

        ### 3.2 Update or create the endpoint

        * If you already have an endpoint:
          1. Go to **Inference** → **Endpoints**.
          2. Click on your existing endpoint.
          3. Choose **Update** (or **Update endpoint**).
          4. Select the **new endpoint configuration** created above.
          5. Click **Update endpoint** and wait for the status to become **InService**.

        * If you don’t have an endpoint yet:
          1. Go to **Inference** → **Endpoints**.
          2. Click **Create endpoint**.
          3. Specify an **Endpoint name**.
          4. Select the **endpoint configuration** you just created.
          5. Click **Create endpoint** and wait until it becomes **InService**.

        ***

        ## 4. Decommission old models/configurations (optional but recommended)

        1. Once traffic is confirmed to work through the new endpoint:
           * Delete the old **endpoint configuration** (if unused).
           * Delete the old **model** (without network isolation), if no longer needed.

        This ensures all active SageMaker models in use have network isolation enabled.
      </Accordion>

      <Accordion title="Using CLI">
        Below are concise, step‑by‑step steps to remediate this using only AWS CLI.

        ***

        ### 1. Identify SageMaker models without network isolation

        ```bash theme={null}
        aws sagemaker list-models --region <REGION> \
          --query 'Models[].ModelName' --output text
        ```

        Check each model:

        ```bash theme={null}
        MODEL_NAME=<MODEL_NAME>
        aws sagemaker describe-model \
          --model-name "$MODEL_NAME" \
          --region <REGION> \
          --query 'EnableNetworkIsolation'
        ```

        If this returns `false` or `null`, it needs remediation.

        ***

        ### 2. Get full configuration of the existing model

        You must recreate the model; you cannot “update” network isolation in place.

        ```bash theme={null}
        MODEL_NAME=<OLD_MODEL_NAME>
        aws sagemaker describe-model \
          --model-name "$MODEL_NAME" \
          --region <REGION> > model-desc.json
        ```

        `model-desc.json` will look roughly like:

        ```json theme={null}
        {
          "ModelName": "my-model",
          "PrimaryContainer": { ... },
          "Containers": [ ... ],
          "ExecutionRoleArn": "arn:aws:iam::123456789012:role/...",
          "VpcConfig": { ... },
          "EnableNetworkIsolation": false
        }
        ```

        ***

        ### 3. Prepare payload for new model with network isolation

        Create a new JSON file, e.g. `create-model-with-iso.json`, keeping everything the same **except**:

        * Use a new `ModelName`
        * Add `"EnableNetworkIsolation": true`

        Example:

        ```json theme={null}
        {
          "ModelName": "my-model-ni",              // new name
          "ExecutionRoleArn": "arn:aws:iam::123456789012:role/...",
          "PrimaryContainer": { ... },             // copy from describe-model
          "VpcConfig": { ... },                    // copy if present
          "EnableNetworkIsolation": true
        }
        ```

        If your original model used `Containers` instead of `PrimaryContainer`, copy that instead.

        ***

        ### 4. Create the new model with network isolation

        ```bash theme={null}
        aws sagemaker create-model \
          --cli-input-json file://create-model-with-iso.json \
          --region <REGION>
        ```

        Verify:

        ```bash theme={null}
        aws sagemaker describe-model \
          --model-name "my-model-ni" \
          --region <REGION} \
          --query 'EnableNetworkIsolation'
        # should return: true
        ```

        ***

        ### 5. Point existing endpoints / endpoint configs to the new model

        #### 5.1 Find endpoint configs that reference the old model

        ```bash theme={null}
        aws sagemaker list-endpoint-configs --region <REGION> \
          --query 'EndpointConfigs[].EndpointConfigName' --output text
        ```

        For each:

        ```bash theme={null}
        EC_NAME=<ENDPOINT_CONFIG_NAME>
        aws sagemaker describe-endpoint-config \
          --endpoint-config-name "$EC_NAME" \
          --region <REGION} \
          --query 'ProductionVariants[].ModelName'
        ```

        If the output includes `<OLD_MODEL_NAME>`, you need a new endpoint config.

        #### 5.2 Create a new endpoint config using the new model

        Export existing config:

        ```bash theme={null}
        EC_NAME=<OLD_ENDPOINT_CONFIG_NAME>
        aws sagemaker describe-endpoint-config \
          --endpoint-config-name "$EC_NAME" \
          --region <REGION> > ec-desc.json
        ```

        Edit to create `create-ec-with-iso.json`:

        * Change `EndpointConfigName`
        * In `ProductionVariants`, replace `ModelName` with the new model name.

        Example:

        ```json theme={null}
        {
          "EndpointConfigName": "my-endpoint-config-ni",
          "ProductionVariants": [
            {
              "VariantName": "AllTraffic",
              "ModelName": "my-model-ni",
              "InitialInstanceCount": 1,
              "InstanceType": "ml.m5.large",
              "InitialVariantWeight": 1.0
            }
          ],
          "KmsKeyId": "..."
        }
        ```

        Create it:

        ```bash theme={null}
        aws sagemaker create-endpoint-config \
          --cli-input-json file://create-ec-with-iso.json \
          --region <REGION>
        ```

        #### 5.3 Update the endpoint to use the new endpoint config

        ```bash theme={null}
        ENDPOINT_NAME=<ENDPOINT_NAME>

        aws sagemaker update-endpoint \
          --endpoint-name "$ENDPOINT_NAME" \
          --endpoint-config-name "my-endpoint-config-ni" \
          --region <REGION>
        ```

        Wait until the status is `InService`:

        ```bash theme={null}
        aws sagemaker describe-endpoint \
          --endpoint-name "$ENDPOINT_NAME" \
          --region <REGION} \
          --query 'EndpointStatus'
        ```

        ***

        ### 6. Clean up old resources (optional but recommended)

        After confirming traffic works as expected:

        * Delete old endpoint configs that are no longer used:

          ```bash theme={null}
          aws sagemaker delete-endpoint-config \
            --endpoint-config-name "<OLD_ENDPOINT_CONFIG_NAME>" \
            --region <REGION>
          ```

        * Delete old models:

          ```bash theme={null}
          aws sagemaker delete-model \
            --model-name "<OLD_MODEL_NAME>" \
            --region <REGION>
          ```

        ***

        ### 7. Automate for all non‑isolated models (outline)

        Script pattern (bash):

        ```bash theme={null}
        for MODEL in $(aws sagemaker list-models --region <REGION> --query 'Models[].ModelName' --output text); do
          ISO=$(aws sagemaker describe-model --model-name "$MODEL" --region <REGION> --query 'EnableNetworkIsolation' --output text)
          if [ "$ISO" != "True" ]; then
            echo "Model $MODEL missing network isolation – migrate manually or via script."
            # Insert the create-model + update-endpoint logic here
          fi
        done
        ```

        This is the required AWS CLI–based remediation: recreate each SageMaker model with `EnableNetworkIsolation=true` and repoint any endpoint configs/endpoints to the new model.
      </Accordion>

      <Accordion title="Using Python">
        To enable network isolation on SageMaker models, you must (re)create the model with `EnableNetworkIsolation=True`. This setting is immutable—you cannot “turn it on” for an existing model in-place. So remediation is:

        1. Identify models without network isolation
        2. Recreate those models with `EnableNetworkIsolation=True`
        3. (If used in endpoints) create new endpoint configs pointing to the new models and update endpoints

        Below is a concise Python/boto3 walkthrough.

        ***

        ### 1. List models and find ones without network isolation

        ```python theme={null}
        import boto3

        sm = boto3.client("sagemaker")

        def list_models():
            models = []
            next_token = None
            while True:
                kwargs = {}
                if next_token:
                    kwargs["NextToken"] = next_token
                resp = sm.list_models(**kwargs)
                models.extend(resp["Models"])
                next_token = resp.get("NextToken")
                if not next_token:
                    break
            return [m["ModelName"] for m in models]

        def models_without_network_isolation():
            bad = []
            for name in list_models():
                desc = sm.describe_model(ModelName=name)
                # If key missing, treat as False
                if not desc.get("EnableNetworkIsolation", False):
                    bad.append(desc)
            return bad

        bad_models = models_without_network_isolation()
        print("Models without network isolation:", [m["ModelName"] for m in bad_models])
        ```

        ***

        ### 2. Recreate each model with `EnableNetworkIsolation=True`

        You can clone the existing model definition, add `EnableNetworkIsolation=True`, and create a new model (recommended: use a new name to avoid endpoint disruption).

        ```python theme={null}
        def clone_model_with_network_isolation(model_desc, new_model_name=None):
            if not new_model_name:
                new_model_name = model_desc["ModelName"] + "-ni"

            # Build args for create_model from describe_model output
            create_args = {
                "ModelName": new_model_name,
                "ExecutionRoleArn": model_desc["ExecutionRoleArn"],
            }

            # Optional blocks – only include if present
            for key in [
                "PrimaryContainer",
                "Containers",
                "VpcConfig",
                "InferenceExecutionConfig",
                "Tags",
                "EnableNetworkIsolation",   # we’ll override below
                "ModelKmsKeyId",
                "Domain",
                "DriftCheckBaselines"
            ]:
                if key in model_desc:
                    create_args[key] = model_desc[key]

            # Force network isolation
            create_args["EnableNetworkIsolation"] = True

            # Keys that are *only* returned by describe_model and not accepted by create_model
            for bad_key in [
                "ModelArn", "CreationTime", "LastModifiedTime",
                "ResponseMetadata"
            ]:
                create_args.pop(bad_key, None)

            resp = sm.create_model(**create_args)
            return resp["ModelArn"], new_model_name

        for m in bad_models:
            arn, new_name = clone_model_with_network_isolation(m)
            print(f"Created model {new_name} with network isolation: {arn}")
        ```

        ***

        ### 3. (If the model is used in endpoints) update endpoint configs

        If existing endpoints use the old model, you must:

        1. Create a new endpoint config referencing the new model
        2. Update the endpoint to use the new config

        Example:

        ```python theme={null}
        def list_endpoint_configs_using_model(model_name):
            configs = []
            next_token = None
            while True:
                kwargs = {}
                if next_token:
                    kwargs["NextToken"] = next_token
                resp = sm.list_endpoint_configs(**kwargs)
                for c in resp["EndpointConfigs"]:
                    cfg = sm.describe_endpoint_config(
                        EndpointConfigName=c["EndpointConfigName"]
                    )
                    for prod in cfg["ProductionVariants"]:
                        if prod["ModelName"] == model_name:
                            configs.append(cfg)
                            break
                next_token = resp.get("NextToken")
                if not next_token:
                    break
            return configs

        def create_new_endpoint_config_with_model(old_cfg, old_model, new_model):
            new_cfg_name = old_cfg["EndpointConfigName"] + "-ni"
            new_variants = []
            for v in old_cfg["ProductionVariants"]:
                v = v.copy()
                if v["ModelName"] == old_model:
                    v["ModelName"] = new_model
                new_variants.append(v)

            args = {
                "EndpointConfigName": new_cfg_name,
                "ProductionVariants": new_variants,
            }
            if "DataCaptureConfig" in old_cfg:
                args["DataCaptureConfig"] = old_cfg["DataCaptureConfig"]
            if "KmsKeyId" in old_cfg:
                args["KmsKeyId"] = old_cfg["KmsKeyId"]

            resp = sm.create_endpoint_config(**args)
            return new_cfg_name, resp["EndpointConfigArn"]

        def update_endpoints_to_new_config(old_cfg_name, new_cfg_name):
            # Find endpoints that use old endpoint config
            next_token = None
            while True:
                kwargs = {}
                if next_token:
                    kwargs["NextToken"] = next_token
                resp = sm.list_endpoints(**kwargs)
                for e in resp["Endpoints"]:
                    ep = sm.describe_endpoint(EndpointName=e["EndpointName"])
                    if ep["EndpointConfigName"] == old_cfg_name:
                        print(f"Updating endpoint {ep['EndpointName']}...")
                        sm.update_endpoint(
                            EndpointName=ep["EndpointName"],
                            EndpointConfigName=new_cfg_name,
                        )
                next_token = resp.get("NextToken")
                if not next_token:
                    break
        ```

        Tie it together (for one model example):

        ```python theme={null}
        old_model_name = "my-model"
        old_desc = sm.describe_model(ModelName=old_model_name)
        _, new_model_name = clone_model_with_network_isolation(old_desc)

        cfgs = list_endpoint_configs_using_model(old_model_name)
        for cfg in cfgs:
            new_cfg_name, _ = create_new_endpoint_config_with_model(
                cfg, old_model_name, new_model_name
            )
            update_endpoints_to_new_config(cfg["EndpointConfigName"], new_cfg_name)
        ```

        ***

        ### 4. Going forward

        When creating any new model, always set:

        ```python theme={null}
        sm.create_model(
            ModelName="my-secure-model",
            ExecutionRoleArn="arn:aws:iam::123456789012:role/sagemaker-role",
            PrimaryContainer={...},
            EnableNetworkIsolation=True,
            # other params...
        )
        ```

        This ensures the control is satisfied for all future models.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
