> ## 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.

# OCI Network Internet Gateways Should Not Be Exposed

### More Info:

Internet Gateways that are enabled and attached to a VCN provide direct internet connectivity. Unnecessary internet gateways expand the network attack surface.

### Risk Level

Medium

### Address

Compliance, 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)
* HIPAA
* ISO/IEC 27017
* ISO/IEC 27018
* ISO/IEC 27701
* KSA PDPL
* MAS Technology Risk Management (Singapore)
* MITRE ATT\&CK (Cloud)
* NIS2 Directive
* NIST
* NIST SP 800-171
* NYDFS 23 NYCRR 500
* Reserve Bank of India (RBI) Cyber Security Framework
* Reserve Bank of India (RBI) Master Direction – Information Technology Framework
* SOC2
* SWIFT Customer Security Controls Framework
* Sarbanes-Oxley IT General Controls
* Securities and Exchange Board of India (SEBI) - Cloud Security Adoption Framework
* UK NCSC Cyber Assessment Framework

### Triage and Remediation

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

    <AccordionGroup>
      <Accordion title="Using Console" defaultOpen="true">
        Below are step‑by‑step remediation options in the **OCI Console** for the issue\
        **“OCI Network Internet Gateways Should Not Be Exposed”** in the context of **OCI Networking / Monitoring** (e.g., flagged by Cloud Guard, Network Monitoring, or security posture tools).

        ***

        ## 1. Identify the Exposed Internet Gateway

        1. Sign in to the **OCI Console**.
        2. In the top-left, open the **Navigation menu** → **Networking** → **Virtual Cloud Networks**.
        3. Select the **compartment** where the issue was reported.
        4. Click the **VCN** in which the Internet Gateway (IGW) exists.
        5. In the left panel of the VCN details page, click **Internet Gateways**.
        6. Find the **Internet Gateway** flagged as exposed (or review each IGW):
           * Check **State** (should be “Available”).
           * Check if it is **attached to route tables** with 0.0.0.0/0 pointing to it.

        > If a security tool (Cloud Guard, etc.) gave you a specific IGW OCID or name, use that to find it.

        ***

        ## 2. If the Internet Gateway Is Not Needed → Disable or Delete It

        **A. Disable the Internet Gateway**

        1. From the VCN → **Internet Gateways** list, click the IGW name.
        2. Click **Edit**.
        3. Uncheck **Enable internet gateway**.
        4. Click **Save changes**.

        **B. Delete the Internet Gateway** (only if you are sure it’s not needed)

        1. Ensure no **route table** has this IGW as a target:
           * From VCN page, click **Route Tables**.
           * Open each Route Table and remove any rule with **Target Type = Internet Gateway** pointing to this IGW (see Section 3 below).
        2. Once no routes use it, go back to **Internet Gateways**.
        3. Click the **Actions (⋮)** menu next to the IGW → **Terminate** (or **Delete**).
        4. Confirm deletion.

        ***

        ## 3. If the Internet Gateway Must Exist → Remove or Restrict Public Routes

        The exposure usually comes from **default route 0.0.0.0/0 → Internet Gateway**.

        ### A. Remove the 0.0.0.0/0 Route to IGW (Preferred)

        1. From the VCN page, click **Route Tables**.
        2. For each Route Table associated with **public subnets**:
           * Click the route table name.
           * Click **Edit**.
           * For any route rule with:
             * **Destination CIDR Block = 0.0.0.0/0** and
             * **Target Type = Internet Gateway** (your IGW),
           * Click the trash icon to **remove** that rule.
           * Optionally, add a more restrictive rule (e.g., specific CIDRs if you must allow certain IP ranges).
           * Click **Save changes**.

        If the subnet no longer needs internet access at all, it’s now effectively private.

        ### B. Use NAT Gateway or Service Gateway Instead of IGW (For Private Egress)

        If workloads only need **outbound** access (no inbound from Internet):

        1. From **Navigation menu** → **Networking** → **Virtual Cloud Networks** → open your VCN.
        2. In left panel, click **NAT Gateways** → **Create NAT Gateway** (if not already present).
        3. Still in the VCN, go to **Route Tables**, edit the relevant route table:
           * Remove `0.0.0.0/0 → Internet Gateway`.
           * Add `0.0.0.0/0 → NAT Gateway`.
        4. Associate that route table with the subnets that should be private but require outbound Internet.

        For OCI services (Object Storage, etc.) without public Internet:

        1. In VCN, click **Service Gateways** → **Create Service Gateway**.
        2. Edit route tables:
           * Add route with **Destination Type = Service CIDR** (All OCI Services or specific service).
           * **Target Type = Service Gateway**.
        3. Remove any corresponding `0.0.0.0/0 → Internet Gateway` if not required.

        ***

        ## 4. Tighten Security for Subnets Using IGW (If You Must Keep Public Access)

        If you absolutely must keep an IGW and public subnet, limit exposure:

        ### A. Restrict Security Lists or Network Security Groups (NSGs)

        1. From **Networking** → **Virtual Cloud Networks** → open your VCN.
        2. For **Security Lists**:
           * Click **Security Lists**, open the list associated with the public subnet.
           * Edit **Ingress Rules**:
             * Remove or narrow any **0.0.0.0/0** rules, especially with wide ports (e.g., 0–65535).
             * Add only the minimal required IP ranges and ports (e.g., SSH from your office IP only).
           * Edit **Egress Rules** similarly, restricting if possible.
        3. For **NSGs** (recommended over security lists):
           * Click **Network Security Groups**.
           * Open the NSG associated with your instances.
           * Reduce rules from `0.0.0.0/0` to specific **source CIDRs** and **ports**.

        ***

        ## 5. Validate via Networking / Monitoring / Cloud Guard

        1. If using **Cloud Guard**:
           * Go to **Navigation menu** → **Identity & Security** → **Cloud Guard**.
           * Check **Detections**.
           * Confirm that the “Network Internet Gateways Should Not Be Exposed” problem is **Resolved** after your changes (may take a few minutes).
        2. If using **Network Monitoring / VCN Flow Logs**:
           * Verify that no unexpected inbound traffic from unknown internet IPs is reaching formerly exposed subnets.
        3. Optionally run an updated **Security Assessment / Vulnerability scan** to confirm no open/public endpoints remain unintentionally exposed.

        ***

        **Summary remediation pattern (OCI Console):**

        * If IGW unnecessary → **Disable or Delete it**.
        * If IGW required → **remove 0.0.0.0/0 routes** or move subnets to NAT/Service Gateway.
        * Where IGW and public subnets must exist → **strict Security Lists/NSGs** and **narrow routes**.
      </Accordion>

      <Accordion title="Using CLI">
        To “remediate” exposed Internet Gateways (IGs) in OCI via CLI, you typically:

        1. **Identify** all Internet Gateways and which are “exposed”
        2. **Stop exposure** by:
           * Disabling or deleting the IG, and/or
           * Removing 0.0.0.0/0 routes that point to the IG

        Below are step‑by‑step OCI CLI commands you can run.

        ***

        ## 0. Set up common variables

        ```bash theme={null}
        # Replace with your values
        COMPARTMENT_OCID="<your_compartment_ocid>"
        VCN_OCID="<your_vcn_ocid>"   # optional if you want to scope to a VCN
        ```

        ***

        ## 1. List Internet Gateways in a compartment

        ```bash theme={null}
        oci network internet-gateway list \
          --compartment-id "$COMPARTMENT_OCID" \
          --all
        ```

        Look for:

        * `"is-enabled": true`
        * Attached `"vcn-id": "..."`

        If you want to filter by VCN:

        ```bash theme={null}
        oci network internet-gateway list \
          --compartment-id "$COMPARTMENT_OCID" \
          --vcn-id "$VCN_OCID" \
          --all
        ```

        Note each **internet-gateway-id** that should not be exposed.

        ***

        ## 2. Find route tables that expose these IGs

        For each IG:

        ```bash theme={null}
        IG_OCID="<internet_gateway_ocid>"

        oci network route-table list \
          --compartment-id "$COMPARTMENT_OCID" \
          --all \
          --output json
        ```

        Inspect the JSON for any `route-rules` with:

        * `"destination": "0.0.0.0/0"`
        * `"network-entity-id": "<IG_OCID>"`

        To narrow with `jq`:

        ```bash theme={null}
        oci network route-table list \
          --compartment-id "$COMPARTMENT_OCID" \
          --all \
          --output json | \
        jq --arg IG "$IG_OCID" '
          .data[] |
          select(.["route-rules"][]? |
                 .["network-entity-id"] == $IG and .destination == "0.0.0.0/0") |
          { "routeTableId": .id, "displayName": .["display-name"], "routeRules": .["route-rules"] }
        '
        ```

        Any returned route tables are exposing the IG to the internet.

        ***

        ## 3. Remove 0.0.0.0/0 routes to the Internet Gateway

        For each exposed route table, fetch its full config:

        ```bash theme={null}
        RT_OCID="<route_table_ocid>"

        oci network route-table get \
          --rt-id "$RT_OCID" \
          --output json > rt.json
        ```

        Edit `rt.json` and **remove or change** any rule like:

        ```json theme={null}
        {
          "cidrBlock": "0.0.0.0/0",
          "networkEntityId": "<internet_gateway_ocid>"
        }
        ```

        or (for newer APIs):

        ```json theme={null}
        {
          "destination": "0.0.0.0/0",
          "destinationType": "CIDR_BLOCK",
          "networkEntityId": "<internet_gateway_ocid>"
        }
        ```

        Keep only the desired rules.

        Then update the route table:

        ```bash theme={null}
        # Prepare only the route-rules array from rt.json
        jq '.data."route-rules"' rt.json > route-rules.json

        oci network route-table update \
          --rt-id "$RT_OCID" \
          --route-rules file://route-rules.json \
          --force
        ```

        Repeat for all route tables exposing the IG.

        ***

        ## 4. Disable or delete unused Internet Gateways

        If the IG should **no longer be used at all**:

        ### Option A – Disable the Internet Gateway (safer)

        ```bash theme={null}
        IG_OCID="<internet_gateway_ocid>"

        oci network internet-gateway update \
          --ig-id "$IG_OCID" \
          --is-enabled false \
          --force
        ```

        This leaves the object but stops traffic.

        ### Option B – Delete the Internet Gateway

        Make sure no route table still references it.

        ```bash theme={null}
        oci network internet-gateway delete \
          --ig-id "$IG_OCID" \
          --force \
          --wait-for-state TERMINATED
        ```

        ***

        ## 5. (Optional) Verify that no IG is exposing 0.0.0.0/0

        Quick cross-check:

        ```bash theme={null}
        oci network route-table list \
          --compartment-id "$COMPARTMENT_OCID" \
          --all \
          --output json | \
        jq '
          .data[] |
          . as $rt |
          .["route-rules"][]? |
          select(.destination == "0.0.0.0/0" and .["network-entity-id"] | contains("internetGateway")) |
          {routeTableId: $rt.id, displayName: $rt["display-name"], rule: .}
        '
        ```

        If this returns nothing, there are no 0.0.0.0/0 routes via Internet Gateways in the compartment.

        ***

        If you share a sample Cloud Guard / Monitoring finding (OCID or JSON), I can translate it to exact CLI commands for that specific IG and route table.
      </Accordion>

      <Accordion title="Using Python">
        To “not expose” OCI Internet Gateways (IGWs), you generally need to:

        1. Detect IGWs in a tenancy/compartment.
        2. Find route tables that send `0.0.0.0/0` (and `::/0` for IPv6) to those IGWs.
        3. Either:
           * Remove or modify those route rules, or
           * Disable/delete the IGW if not needed.

        Below is a concise, step‑by‑step approach and a Python example using the OCI SDK.

        ***

        ## 1. Prerequisites

        * Install SDK:

        ```bash theme={null}
        pip install oci
        ```

        * Configure `~/.oci/config` with at least:
          * `tenancy`
          * `user`
          * `fingerprint`
          * `key_file`
          * `region`

        Example profile `[DEFAULT]` is assumed.

        ***

        ## 2. Decide What “Not Exposed” Means for Your Policy

        Pick your policy, for example:

        * **Strict**: No route rule anywhere with `0.0.0.0/0` or `::/0` using an Internet Gateway.
        * **Conditional**: Only allow from specific VCNs/compartments; everything else is remediated.

        In the example below, we:

        * Flag any route rule with:
          * `cidr_block == "0.0.0.0/0"` or `destination == "0.0.0.0/0"`
          * `destination_type == "CIDR_BLOCK"`
          * `network_entity_id` == an IGW OCID
        * And **delete those route rules**.

        You can adapt to instead:

        * Replace the IGW with a NAT Gateway, or
        * Narrow the CIDR to a specific external subnet, etc.

        ***

        ## 3. Python Script – Monitor and Remediate IGW Exposure

        ```python theme={null}
        import oci

        PROFILE = "DEFAULT"  # OCI config profile name
        COMPARTMENT_OCID = "<your_compartment_ocid>"  # or tenancy OCID for full scan
        DRY_RUN = True  # set to False to actually remediate

        def get_all_vcns(network_client, compartment_id):
            vcns = []
            list_vcns_resp = oci.pagination.list_call_get_all_results(
                network_client.list_vcns,
                compartment_id=compartment_id
            )
            vcns.extend(list_vcns_resp.data)
            return vcns

        def get_all_igws(network_client, compartment_id, vcn_ids=None):
            igws = []
            kwargs = {}
            if vcn_ids:
                # If you want to limit to selected VCNs
                for vcn_id in vcn_ids:
                    resp = oci.pagination.list_call_get_all_results(
                        network_client.list_internet_gateways,
                        compartment_id=compartment_id,
                        vcn_id=vcn_id
                    )
                    igws.extend(resp.data)
            else:
                resp = oci.pagination.list_call_get_all_results(
                    network_client.list_internet_gateways,
                    compartment_id=compartment_id
                )
                igws.extend(resp.data)
            return igws

        def get_all_route_tables(network_client, compartment_id, vcn_ids=None):
            rts = []
            if vcn_ids:
                for vcn_id in vcn_ids:
                    resp = oci.pagination.list_call_get_all_results(
                        network_client.list_route_tables,
                        compartment_id=compartment_id,
                        vcn_id=vcn_id
                    )
                    rts.extend(resp.data)
            else:
                resp = oci.pagination.list_call_get_all_results(
                    network_client.list_route_tables,
                    compartment_id=compartment_id
                )
                rts.extend(resp.data)
            return rts

        def is_default_anywhere_route(rule):
            # IPv4 & IPv6 default routes
            dest = getattr(rule, "destination", None) or getattr(rule, "cidr_block", None)
            return dest in ["0.0.0.0/0", "::/0"]

        def main():
            config = oci.config.from_file("~/.oci/config", PROFILE)

            network_client = oci.core.VirtualNetworkClient(config)

            # 1. Get all VCNs in compartment
            vcns = get_all_vcns(network_client, COMPARTMENT_OCID)
            vcn_ids = [vcn.id for vcn in vcns]

            # 2. Get all Internet Gateways
            igws = get_all_igws(network_client, COMPARTMENT_OCID, vcn_ids=vcn_ids)
            igw_ids = {igw.id for igw in igws}

            if not igw_ids:
                print("No Internet Gateways found; nothing to remediate.")
                return

            print(f"Found IGWs: {igw_ids}")

            # 3. Get all route tables in those VCNs
            route_tables = get_all_route_tables(network_client, COMPARTMENT_OCID, vcn_ids=vcn_ids)

            for rt in route_tables:
                # Identify rules to remove
                rules_to_keep = []
                rules_to_remove = []

                for rule in rt.route_rules:
                    # Check if rule points to an IGW and is 0.0.0.0/0 or ::/0
                    if (rule.network_entity_id in igw_ids) and is_default_anywhere_route(rule):
                        rules_to_remove.append(rule)
                    else:
                        rules_to_keep.append(rule)

                if not rules_to_remove:
                    continue

                print(f"\nRoute Table: {rt.display_name} ({rt.id})")
                for r in rules_to_remove:
                    dest = getattr(r, "destination", None) or getattr(r, "cidr_block", None)
                    print(f"  Will remove rule: {dest} -> {r.network_entity_id}")

                if DRY_RUN:
                    print("  DRY_RUN=True, not making changes.")
                    continue

                # 4. Update the route table (remove insecure rules)
                update_details = oci.core.models.UpdateRouteTableDetails(
                    route_rules=rules_to_keep
                )
                try:
                    resp = network_client.update_route_table(
                        rt.id,
                        update_route_table_details=update_details
                    )
                    print(f"  Updated route table {rt.id}, removed {len(rules_to_remove)} rules.")
                except Exception as e:
                    print(f"  ERROR updating route table {rt.id}: {e}")

            print("\nCompleted scan/remediation.")

        if __name__ == "__main__":
            main()
        ```

        ***

        ## 4. Using This for “Monitoring”

        To turn this into ongoing monitoring:

        1. Keep `DRY_RUN = True` and:
           * Run it periodically from:
             * OCI Functions (wrapped in a function)
             * OCI DevOps/Code pipelines or an external CI
             * A cron job on a bastion host
           * Send output to:
             * OCI Logging / Logging Analytics
             * Email / Slack via extra code.

        2. For auto-remediation:
           * Set `DRY_RUN = False` in a controlled environment.
           * Optionally restrict to specific compartments.

        ***

        ## 5. Optional: Hardening IGWs Further

        If you want stricter remediation, after cleaning routes you can:

        * Disable an IGW (`is_enabled=False` via `update_internet_gateway`).
        * Or delete unused IGWs (`delete_internet_gateway`) if no more routes reference them.

        If you specify your exact policy (e.g., “no IGW at all in compartment X”), I can adjust the code to enforce that explicitly.
      </Accordion>

      <Accordion title="Using Terraform">
        ```hcl theme={null}
        resource "oci_core_internet_gateway" "this" {
          # REQUIRED: replace with your compartment OCID
          compartment_id = "OCID_OF_COMPARTMENT"

          # REQUIRED: replace with your VCN OCID
          vcn_id = "OCID_OF_VCN"

          display_name = "NON_INTERNET_EXPOSED_IGW"

          # Remediation: disable the Internet Gateway so it no longer provides internet connectivity
          enabled = false

          # OPTIONAL: add tags as appropriate
          freeform_tags = {
            "Environment" = "ENVIRONMENT_NAME"
            "Owner"       = "TEAM_OR_OWNER"
          }
        }
        ```

        Disabling `enabled` is an in‑place update on `oci_core_internet_gateway` and does not force replacement of the gateway (no outage from the resource being recreated, but any existing routes to it will stop providing internet connectivity).

        To verify, `terraform plan` should show only an in-place update on `oci_core_internet_gateway.this` with `enabled` changing from `true` to `false` and no resources marked `-/+` (replace) or `-` (destroy) unless you intentionally removed other configuration.
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
