<br />

This page describes how to enable VPC Service Controls on a Cloud SQL
project. Before you begin, review [Overview of VPC Service Controls](https://docs.cloud.google.com/vpc-service-controls/docs/overview.md.txt).
Also review the [Cloud SQL limitations when using VPC Service Controls](https://docs.cloud.google.com/vpc-service-controls/docs/supported-products.md.txt#cloud_sql_admin_api).

## Before you begin

1.


   Enable the Compute Engine API, if it is not already enabled.


   **Roles required to enable APIs**


   To enable APIs, you need the `serviceusage.services.enable` permission. If you
   created the project, then you likely already have this permission through the
   Owner role (`roles/owner`). Otherwise, you can get this permission through the
   Service Usage Admin role (`roles/serviceusage.serviceUsageAdmin`).
   [Learn how to grant roles](https://docs.cloud.google.com/iam/docs/granting-changing-revoking-access.md.txt).

   [Enable the API](https://console.cloud.google.com/apis/enableflow?apiid=compute)
2.


   Enable the Service Networking API, if it is not already enabled.


   **Roles required to enable APIs**


   To enable APIs, you need the `serviceusage.services.enable` permission. If you
   created the project, then you likely already have this permission through the
   Owner role (`roles/owner`). Otherwise, you can get this permission through the
   Service Usage Admin role (`roles/serviceusage.serviceUsageAdmin`).
   [Learn how to grant roles](https://docs.cloud.google.com/iam/docs/granting-changing-revoking-access.md.txt).

   [Enable the API](https://console.cloud.google.com/apis/enableflow?apiid=servicenetworking)
3. Add the [Identity and Access Management (IAM) roles](https://docs.cloud.google.com/vpc-service-controls/docs/access-control.md.txt#required_roles) to the user or service account you are using to set up and administer VPC Service Controls. For more information about the roles required to administer VPC Service Controls, see [Access control with IAM](https://docs.cloud.google.com/vpc-service-controls/docs/access-control.md.txt).
4. Review [limitations](https://docs.cloud.google.com/vpc-service-controls/docs/supported-products.md.txt#cloud_sql_admin_api) when using VPC Service Controls with Cloud SQL.
5. Optionally, add an organization policy that restricts public IP on instances in projects that use that policy. See [Connection organization policies](https://docs.cloud.google.com/sql/docs/sqlserver/connection-org-policy) and [Configuring the organization policy](https://docs.cloud.google.com/sql/docs/sqlserver/configure-org-policy#configuring_the_organization_policy).

### Configure the Virtual Private Cloud (VPC) network

Perform the steps in [Setting up private connectivity to Google APIs and services](https://docs.cloud.google.com/vpc-service-controls/docs/set-up-private-connectivity.md.txt).
**Note:** If you're using [Shared VPC](https://docs.cloud.google.com/vpc/docs/shared-vpc.md.txt), then you must include the [host project](https://docs.cloud.google.com/vpc-service-controls/docs/troubleshooting.md.txt#shared_vpc) in a service perimeter along with any projects that belong to the Shared VPC.

### Configure DNS for Artifact Registry

Cloud SQL instances require access to Artifact Registry (`pkg.dev`
and `*.pkg.dev`) to download essential service agent container
images during instance creation and maintenance. When using
VPC Service Controls, you must route requests for Artifact Registry
domains to the restricted virtual IP (VIP) range
(`199.36.153.4/30`).

To route Artifact Registry traffic to the restricted VIP, configure
Cloud DNS private DNS zones:

1. Create a dedicated private managed DNS zone for the
   `pkg.dev.` domain:

   ```bash
   gcloud dns managed-zones create ZONE_NAME \
       --project=PROJECT_ID \
       --description="DESCRIPTION" \
       --dns-name=pkg.dev. \
       --networks=NETWORK_NAME \
       --visibility=private
       
   ```

   Replace the following:
   - `ZONE_NAME`: a name for the DNS zone (for example, `pkg-dev-private`).
   - `PROJECT_ID`: the ID of the Google Cloud project that hosts your VPC network.
   - `DESCRIPTION`: a description of the zone (for example, `Private DNS zone for Artifact Registry`).
   - `NETWORK_NAME`: the name of your VPC network.

   > [!CAUTION]
   > **Caution:** You must create a dedicated private DNS zone for the
   > `pkg.dev.` domain. In Cloud DNS, all resource record sets in
   > a managed zone must be subdomains of the zone's domain suffix. Attempts
   > to add `pkg.dev` records into an existing private zone with a
   > different suffix (such as `example.internal.`) fail with
   > validation errors.

2. Start a DNS transaction:

   ```bash
   gcloud dns record-sets transaction start \
       --project=PROJECT_ID \
       --zone=ZONE_NAME
       
   ```
3. Add an `A` record for `pkg.dev.` pointing to
   the restricted VIP range (`199.36.153.4/30`):

   ```bash
   gcloud dns record-sets transaction add \
       199.36.153.4 199.36.153.5 199.36.153.6 199.36.153.7 \
       --name=pkg.dev. \
       --type=A \
       --ttl=300 \
       --zone=ZONE_NAME \
       --project=PROJECT_ID
       
   ```
4. Add a `CNAME` record mapping wildcard subdomains
   (`*.pkg.dev.`) to `pkg.dev.`:

   ```bash
   gcloud dns record-sets transaction add "pkg.dev." \
       --name="*.pkg.dev." \
       --type=CNAME \
       --ttl=300 \
       --zone=ZONE_NAME \
       --project=PROJECT_ID
       
   ```
5. Run the transaction:

   ```bash
   gcloud dns record-sets transaction execute \
       --zone=ZONE_NAME \
       --project=PROJECT_ID
       
   ```

> [!NOTE]
> **Note:** If your VPC network has firewall rules denying
> outbound traffic, then make sure that you have an egress firewall rule
> allowing TCP traffic on port 443 to `199.36.153.4/30`. For more
> information about securing Artifact Registry in a service perimeter, see
> [Secure repositories in
> a service perimeter](https://docs.cloud.google.com/artifact-registry/docs/securing-with-vpc-sc).

### Enable VPC Service Controls for private services access

When a Cloud SQL instance uses private IP (private services access), its
underlying resources run in a peered service producer VPC
network (`servicenetworking`). If your VPC network
exports custom broad routes (such as `0.0.0.0/0`,
`0.0.0.0/1`, or `128.0.0.0/2`) over the private services
access peering connection, those routes can override Google API routes in the
producer network and block Artifact Registry access.

To configure the service producer network with private DNS zones (including
`pkg.dev`) and a route to the restricted VIP
(`199.36.153.4/30`), enable VPC Service Controls on the peering
connection:

```bash
gcloud services vpc-peerings enable-vpc-service-controls \
    --network=NETWORK_NAME \
    --project=PROJECT_ID \
    --service=servicenetworking.googleapis.com
```

For more information, see
[gcloud services vpc-peerings enable-vpc-service-controls](https://docs.cloud.google.com/sdk/gcloud/reference/services/vpc-peerings/enable-vpc-service-controls)
and
[Configure hybrid
connectivity](https://docs.cloud.google.com/vpc/docs/configure-private-services-access#on-prem) in the VPC documentation.

## Disallow or disable public IP for Cloud SQL instances

To constrain data within the VPC for your Cloud SQL project,
don't allow connections to Cloud SQL instances from public IPs. IP-based
connections bypass VPC Service Controls. You must also disable public IP for new
and existing Cloud SQL instances within the VPC.

To either disallow or disable public IP on Cloud SQL instances:

- Organization administrators can apply organization policies that disallow creating new instances with public IP. See [Configure the organization policy](https://docs.cloud.google.com/sql/docs/sqlserver/configure-org-policy#configuring_the_organization_policy).
- Users who create Cloud SQL instances can configure the instances to use private IP instead of public IP. See [Disable public IP](https://docs.cloud.google.com/sql/docs/sqlserver/configure-ip.md.txt#disable-public).

## Create a service perimeter

During this procedure, you select the Cloud SQL projects that you want the
VPC service perimeter to protect.

> [!NOTE]
> **Note:** Sometimes, a Cloud SQL instance enabled with customer-managed encryption keys (CMEK) has the Cloud Key Management Service key hosted in a different project. For this scenario, when you enable VPC Service Controls, you must add the Cloud KMS key hosting project to the service perimeter.

To create a service perimeter, follow the instructions in
[Creating a service perimeter](https://docs.cloud.google.com/vpc-service-controls/docs/create-service-perimeters.md.txt).

### Add more instances to the service perimeter

To add existing Cloud SQL projects to the perimeter, follow the instructions
in [Updating a service perimeter](https://docs.cloud.google.com/vpc-service-controls/docs/manage-service-perimeters.md.txt#updating_a_service_perimeter).

### Add Cloud SQL and Cloud Storage APIs

To mitigate the risk of your data being exfiltrated from Cloud SQL, for
example, using Cloud SQL import or export APIs, you must restrict both the
**Google Cloud SQL Admin API** *and* the **Google Cloud Storage API**.

> [!NOTE]
> **Note:** You can only import or export data from a Cloud Storage bucket that is in a project that resides in the same service perimeter as Cloud SQL.

To add Cloud SQL and Cloud Storage APIs as restricted services:

### Console

1. In the Google Cloud console navigation menu, click **Security** , and then
   click **VPC Service Controls**.

   [Go to VPC Service Controls](https://console.cloud.google.com/security/service-perimeter)
2. On the **VPC Service Controls** page, in the table, click the name of
   the service perimeter that you want to modify.

3. Click **EDIT**.

4. On the **Edit VPC Service Perimeter** page, click **ADD SERVICES**.

5. Add **Cloud SQL Admin API** and **Cloud Storage API**.

6. Click **Save**.

### gcloud

```bash
gcloud access-context-manager perimeters update PERIMETER_ID \
--policy=POLICY_ID \
--add-restricted-services=sqladmin.googleapis.com,storage.googleapis.com
```

Where:

- <var translate="no">PERIMETER_ID</var> is the ID of the perimeter or the fully qualified identifier for the perimeter.
- <var translate="no">POLICY_ID</var> is the ID of the access policy.

For reference information, see [`access-context-manager perimeters update`](https://docs.cloud.google.com/sdk/gcloud/reference/alpha/access-context-manager/perimeters/update.md.txt).

## Create an access level

Optionally, to permit external access to protected resources inside a perimeter,
you can use *access levels*. Access levels apply only to requests for protected
resources coming from outside the service perimeter. You can't use access levels
to give protected resources or VMs permission to access data and services
outside the perimeter.

See [Allowing access to protected resources from outside a perimeter](https://docs.cloud.google.com/vpc-service-controls/docs/use-access-levels.md.txt).