Skip to content

Commit

Permalink
Setup mTLS and TLS with GCP Application Load Balancer (EXTERNAL_MANAG…
Browse files Browse the repository at this point in the history
…ED) (#1444)

* Setup mTLS and TLS with GCP application load balancer

* Update README.md

---------

Co-authored-by: Andrew Gold <41129777+agold-rh@users.noreply.github.com>
  • Loading branch information
pawanphalak and agold-rh authored Feb 7, 2025
1 parent c8635a5 commit 659e7fc
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 0 deletions.
87 changes: 87 additions & 0 deletions examples/gclb-mtls-tls/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
## Setup mTLS and TLS with GCP Application Load Balancer (EXTERNAL_MANAGED)

### OVERVIEW:

mTLS with GCP Application Load Balancer enhances security by requiring clients to authenticate themselves with certificates, in addition to the server authenticating itself to the client. This provides mutual authentication, ensuring that both parties are who they claim to be.

To implement mTLS with GCP Application Load Balancer, you need to create a trust config resource that contains the root and intermediate certificates used to validate client certificates. You then create a client authentication resource that specifies the client validation mode and associates it with the trust config. Finally, you attach the client authentication resource to your load balancer's HTTPS frontend.

mTLS with GCP Application Load Balancer supports various features, including custom mTLS headers that can be used to pass information about the mTLS connection to backend services. It also supports different client validation modes, allowing you to choose how to handle invalid or missing client certificates.

### [Create a VPC native cluster:](https://cloud.google.com/kubernetes-engine/docs/how-to/standalone-neg#create-cluster)

```bash
gcloud container clusters create neg-demo-cluster \
--create-subnetwork="" \
--network=default \
--zone=us-central1-a
```
### Connect to GKE cluster:
```bash
gcloud container clusters get-credentials neg-demo-cluster --zone us-central1-a --project <GCP_PROJECT_ID>
```
### Deploy the Sample application deployment and service(along with [NEG](https://cloud.google.com/load-balancing/docs/negs/zonal-neg-concepts)):
```bash
kubectl apply -f manifests/deploy.yaml
```

### Generate the self signed certificates

A detailed steps to generate the self signed certificates are documented in the [Medium Article.](https://medium.com/google-cloud/tls-and-mtls-connection-with-gcp-application-load-balancer-6e2cd5189707)

After executing the steps from the above article, you should have a root, 2 intermediate, server and client certificates generated. Copy all the generated certificates along with the following unencrypted server keys in the `terraform/certs` directory.

Decrypt the server key file using the passphrase used in previous steps:
```bash
openssl rsa -in server.key -out un-server.key
```

### Deploy the GCP Global application load balancer with both tls and mTLS configuration

#### Update the following terraform local variables in `terraform/main.tf`:
* project_id: GCP Project ID where the GCP load balancer will be deployed.
* vpc_networks: List of VPC network where the load balancer backend exists. The additional firewall rules required by load balancer are added using this input variable.
* vpc_projects: The GCP project ID where the VPC network exists.

#### Initialize the terraform directory

```bash
terraform init
```

#### Generate the terraform plan
```bash
terraform plan
```

#### Apply the terraform plan to provision all GCP resources.

```bash
terraform apply
```

After executing the terraform script, we should have the GCP application load balancer provisioned with 2 forwarding rules:
* One forwarding rule is used to send the tls connection.
![tls](https://github.com/user-attachments/assets/6d52967b-c275-497d-9c35-fd09254e183d)


* Another forwarding rule is used to send the mtls connection to load balancer.
![mtls](https://github.com/user-attachments/assets/0f8852f5-0ee7-47b1-a27f-faa7d3337153)


#### Test the tls connection to the GCP Load balancer by sending the following curl request

```bash
curl -v --cacert int2.cert --connect-to test-domain.com:443:34.149.90.136:443 https://test-domain.com
```
<img width="1098" alt="Screenshot 2025-02-06 at 10 46 25 PM" src="https://github.com/user-attachments/assets/d392214c-da93-4198-be47-eb2e0ac3315f" />
The GCP application load balancer is also configured to send the custom headers of the mtls request back to the backend service which are seen in the curl request output of the mTLS connection, since the above request was tls connection, the custom headers are empty in the above tls connection response.


#### Test the mTLS connection to the GCP application load balancer by sending the following request

```bash
curl -v --cacert int2.cert --key client.key --cert client.cert --connect-to test-domain.com:443:34.8.115.55:443 https://test-domain.com
```
<img width="1204" alt="Screenshot 2025-02-06 at 10 49 07 PM" src="https://github.com/user-attachments/assets/24f69993-46a9-4329-bb8f-6609c7d2680f" />
We see the mTLS custom headers in above mtls connection response are populated automatically by load balancer frontend and sent back to the backend server after a successful mTLS connection is established.
61 changes: 61 additions & 0 deletions examples/gclb-mtls-tls/manifests/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copyright 2025 Google Inc. All Rights Reserved.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and

apiVersion: v1
kind: Namespace
metadata:
name: mtls-demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: echo
namespace: mtls-demo
spec:
selector:
matchLabels:
app: echo
template:
metadata:
labels:
app: echo
spec:
containers:
- name: echo
image: gcr.io/istio-testing/app:latest
args:
- --tcp=7070
- --tcp=7071
- --port=8080
- --grpc=9090
- --server-first=7071
---
apiVersion: v1
kind: Service
metadata:
name: echo
namespace: mtls-demo
annotations:
cloud.google.com/neg: '{"exposed_ports": {"8080":{"name": "mtls-demo-neg"}}}'
spec:
selector:
app: echo
ports:
- name: http
port: 8080
- name: tcp
port: 7070
- name: tcp-sf
port: 7071
- name: grpc
port: 9090
19 changes: 19 additions & 0 deletions examples/gclb-mtls-tls/terraform/certs/client.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[req]
default_bits = 2048
req_extensions = extension_requirements
distinguished_name = dn_requirements
prompt = no

[extension_requirements]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth,clientAuth
subjectAltName = DNS:test-client.com,DNS:www.test-client.com

[dn_requirements]
countryName = IN
stateOrProvinceName = Telangana
localityName = Hyderabad
0.organizationName = Google
organizationalUnitName = QA
commonName = test-client
17 changes: 17 additions & 0 deletions examples/gclb-mtls-tls/terraform/certs/int.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[req]
default_bits = 2048
req_extensions = extension_requirements
distinguished_name = dn_requirements
prompt = no

[extension_requirements]
basicConstraints = critical,CA:TRUE
keyUsage = keyCertSign

[dn_requirements]
countryName = IN
stateOrProvinceName = Telangana
localityName = Hyderabad
0.organizationName = Google
organizationalUnitName = IT
commonName = int
17 changes: 17 additions & 0 deletions examples/gclb-mtls-tls/terraform/certs/int2.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[req]
default_bits = 2048
req_extensions = extension_requirements
distinguished_name = dn_requirements
prompt = no

[extension_requirements]
basicConstraints = critical,CA:TRUE
keyUsage = keyCertSign

[dn_requirements]
countryName = IN
stateOrProvinceName = Telangana
localityName = Hyderabad
0.organizationName = Google
organizationalUnitName = IT
commonName = int2
17 changes: 17 additions & 0 deletions examples/gclb-mtls-tls/terraform/certs/root.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[req]
default_bits = 2048
req_extensions = extension_requirements
distinguished_name = dn_requirements
prompt = no

[extension_requirements]
basicConstraints = critical,CA:TRUE
keyUsage = keyCertSign

[dn_requirements]
countryName = IN
stateOrProvinceName = Telangana
localityName = Hyderabad
0.organizationName = Google
organizationalUnitName = IT
commonName = root
19 changes: 19 additions & 0 deletions examples/gclb-mtls-tls/terraform/certs/server.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[req]
default_bits = 2048
req_extensions = extension_requirements
distinguished_name = dn_requirements
prompt = no

[extension_requirements]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth,clientAuth
subjectAltName = DNS:test-domain.com,DNS:www.test-domain.com

[dn_requirements]
countryName = IN
stateOrProvinceName = Telangana
localityName = Hyderabad
0.organizationName = Google
organizationalUnitName = DEV
commonName = test-domain.com
Loading

0 comments on commit 659e7fc

Please sign in to comment.