Designing a defense-in-depth network security model between Google Kubernetes Engine and Cloud SQL
Tags: googlecloud, kubernetes, terraform
Published: 2021-06-15 14:57:28

It is very easy today to establish a connection between a container in Kubernetes and a relational database server, just create a SQL user and open a TCP connection. In cloud computing, in the case of Google Cloud Platform, the equivalent is connecting a container in a Google Kubernetes Engineer cluster to a Cloud SQL instance.

Important points should be taken into account in setting up this connectivity.

Which network topology to choose? How to authenticate and authorize the connection to the Cloud SQL instance? Can I publicly expose a private Cloud SQL instance?

Which architecture could be the most efficient, maintainable and scalable?

# Scenarios

Cloud SQL supports the following scenarios for accessing a DB instance in a VPC:

* A Compute Engine instance in the same VPC
* A Compute Engine in a different VPC
* A client application through the internet
* A private network

The scenarios that concern us are the first two:

* GKE and Cloud SQL in the same VPC.
* GKE and Cloud SQL in different VPCs.

In the first one, there is a direct communication between Kubernetes workloads and Cloud SQL instances.

In the second scenario, if private communication is required, a VPN connection between the two VPCs must be established.

Let's discover the possible architectures that could be used to implement each scenario.

## Direct communication with public IP and authorized networks

![GKE and Cloud SQL Direction communication with public IP and authorized networks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fyvq4o5j1wywm4nlc162.png)

In this architecture [2], our Cloud SQL instance is isolated on its own subnet and accessible through public IP address to only GKE Autopilot that requires access to it. Pods have access to Cloud SQL using Cloud SQL Proxy.

## Direct communication with private IP

![GKE and Cloud SQL Direction communication with private IP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t0m48ps5dkky49g4rmrj.png)

In this architecture [3], our Cloud SQL instance is isolated on its own subnet and accessible with a private IP to only GKE Autopilot that requires access to it. Pods have access to Cloud SQL using Cloud SQL Proxy.

## Communication using VPN

![GKE and Cloud SQL Communication using VPN](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/naa9h524xhhdryj2monk.png)

In this architecture, our Cloud SQL instance is isolated on its own VPC. The two VPCs communicate using Cloud VPN. Pods have access to Cloud SQL using Cloud SQL Proxy.

Each architecture has its own advantages and disadvantages but all apply network isolation best practices for securing sensitive data in Cloud SQL.

Let's explore scenario 2.

# Scenario 2 in detail

In the scenario 2 architecture, the network isolation is achieved using [Private services access][gcp-0]. We can go more deeply using [GKE Workload Identity][gcp-9] add-on to provide a pod level defense in depth security strategy at both the networking and authentication layers.

* We associate a Google Service Account with a Kubernetes service account. This service account can then provide IAM permissions to the containers in any pod that uses that service account. 
* Network policies to define rules that allow inbound and outbound network traffic to and from pods.

We could implement the same security pattern with the scenario of Cloud VPN.

Now that we have a clear idea of the concepts, let's implement this architecture.

# Prerequisites

* Download, install, and configure the [Google Cloud SDK][sdk].
* [Terraform][install-2]
* [Kubectl][install-3]

# Architecture

The overall architecture that we will implement during this series of articles is as follows:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bzoq93d85vdlxc7jb578.png)

# Objectives

During this section of the workshop:

With Terraform

* We will create a VPC with 2 subnets
  * web subnet for GKE Autopilot.
  * data subnet for the Cloud SQL instance.
* NAT gateway attached to web subnet, but not on data subnet as Cloud SQL doesn't need to access the public internet.
* GKE Autopilot.
* A highly available Cloud SQL MySQL Instance.

With Kubectl

* We will create an annotated Kubernetes service account with Google Service Account that has the necessary permission to connect to the Cloud SQL instance.
* [Cloud SQL proxy][gcp-1].
* A Web application. A Kubernetes deployment to connect with our MySQL database with:
 * A [GKE ingress][gcp-2], to create an external HTTPS Load balancer
 * A [managed SSL certificate][gcp-3].
 * A backend config with [IAP][gcp-4] and Cloud Armor [security policy][gcp-5] enabled.
 * A [frontend config][gcp-6] to redirect http requests to https.

The series is divided into five parts:

* Configuring an isolated network in Google Cloud
* Creating a GKE Autopilot cluster using Terraform
* Securing sensitive data in Cloud SQL
* Securing the connectivity between a GKE application and a Cloud SQL database

# Conclusion

In this first part, we discussed possible scenarios for securing communication between GKE workloads and Cloud SQL databases. In the [next section][part-2], we'll implement our network stack using Terraform.

# Documentation

[1] https://medium.com/google-cloud/cloud-sql-with-private-ip-only-the-good-the-bad-and-the-ugly-de4ac23ce98a
[2] https://cloud.google.com/sql/docs/mysql/configure-ip
[3] https://cloud.google.com/sql/docs/mysql/private-ip

[part-2]: https://dev.to/stack-labs/configuring-an-isolated-network-in-google-cloud-5cib
[sdk]: https://cloud.google.com/sdk
[install-2]: https://www.terraform.io/downloads.html
[install-3]: https://kubernetes.io/docs/tasks/tools/
[gcp-0]: https://cloud.google.com/vpc/docs/private-services-access
[gcp-1]: https://cloud.google.com/sql/docs/mysql/sql-proxy
[gcp-2]: https://cloud.google.com/kubernetes-engine/docs/concepts/ingress
[gcp-3]: https://cloud.google.com/kubernetes-engine/docs/how-to/managed-certs
[gcp-4]: https://cloud.google.com/iap/docs/enabling-kubernetes-howto
[gcp-5]: https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#cloud_armor
[gcp-6]: https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#https_redirect
[gcp-8]: https://cloud.google.com/kubernetes-engine/docs/concepts/horizontalpodautoscaler
[gcp-9]: https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity