Stay organized with collections Save and categorize content based on your preferences.
This page explains how you can secure a Gateway using various security features:
SSL Policies to ensure the Gateway is using the required secure protocols and algorithms
Certificates to secure Client-to-Gateway and Gateway-to-Backends traffic with TLS
Google Cloud Armor security policy to protect Services from DDoS attacks
Identity-Aware Proxy (IAP) to provide a layer of authentication and authorization before allowing access to a Service
To learn more about Gateway security, see Gateway security.
Before you beginBefore you start, make sure that you have performed the following tasks:
gcloud components update
. Note: For existing gcloud CLI installations, make sure to set the compute/region
property. If you use primarily zonal clusters, set the compute/zone
instead. By setting a default location, you can avoid errors in the gcloud CLI like the following: One of [--zone, --region] must be supplied: Please specify location
. You might need to specify the location in certain commands if the location of your cluster differs from the default that you set.HttpLoadBalancing
add-on enabled.Compute Network User
role to the GKE Service account for the service project.In addition to the GKE Gateway controller restrictions and limitations, the following limitations apply specifically to Gateway security:
TLS configurations using either an SSL Certificate or Certificate Manager on Gateways are not supported with GKE version 1.28.4-gke.1083000. Use a Kubernetes secret as a workaround for this GKE version.
You cannot use the networking.gke.io/certmap
annotation with a tls.certificateRefs
on the same Gateway resource. If you reference a CertificateMap
in a Gateway, GKE will treat this as an error.
Certificate Manager supports both self-managed and Google-managed certificates. Google-managed certificates are compatible with regional Gateways and global Gateways.
When using Google-managed SSL certificates, you must create the SSL certificates outside of GKE before you attach them to your Gateway.
You cannot use the same service as a backend to a regional and a global Gateway if you are referencing a Google Cloud Armor backend security policy in your GCPBackendPolicy
. You must create two separate services and policies for this use case.
The Gateway controller does not support the ManagedCertificate
resource.
The Gateway controller does not support the networking.gke.io/managed-certificates
annotation.
For a list of supported Gateway API fields and capabilities of the GatewayClass resources available on GKE, see GatewayClass capabilities.
Secure a Gateway using a Kubernetes SecretIn this example, you configure a Gateway using a Kubernetes Secret.
Store a certificate in a Kubernetes SecretYou can use a certificate issued and validated by your certificate authority (CA) or create a self-signed certificate. The following steps use a self-signed certificate.
Create a private key:
openssl genrsa -out PRIVATE_KEY_FILE 2048
Replace PRIVATE_KEY_FILE
with the name of your private key file, such as private-key.pem
. For more information, see Select or create a private key.
Create an Open SSL configuration file:
cat <<EOF >CONFIG_FILE
[req]
default_bits = 2048
req_extensions = extension_requirements
distinguished_name = dn_requirements
prompt = no
[extension_requirements]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @sans_list
[dn_requirements]
0.organizationName = example
commonName = store.example.com
[sans_list]
DNS.1 = store.example.com
EOF
Replace CONFIG_FILE
with the name for the new config file, such as config-file.cnf
.
Create a certificate signing request (CSR) file:
openssl req -new -key PRIVATE_KEY_FILE \
-out CSR_FILE \
-config CONFIG_FILE
Replace CSR_FILE
with the name of the new CSR file, such as cert.pem
. For more information, see Create a CSR.
Sign the CSR:
openssl x509 -req \
-signkey PRIVATE_KEY_FILE \
-in CSR_FILE \
-out CERTIFICATE_FILE \
-extfile CONFIG_FILE \
-extensions extension_requirements \
-days 30
Replace CERTIFICATE_FILE
with the path and name of the file that the command generates, such as cert-file.pem
. For more information, see Sign the CSR.
Create a Kubernetes TLS Secret using the key and the certificate file that you created:
kubectl create secret tls store-example-com \
--cert=CERTIFICATE_FILE \
--key=PRIVATE_KEY_FILE
GKE saves the certificate and key as a Kubernetes resource that you can attach to your Gateway.
Save the following manifest as external-gateway.yaml
:
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: external-http
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: store-example-com
This manifest describes a Gateway with the following properties:
gatewayClassName: gke-l7-global-external-managed
: deploys a global external Application Load Balancer.protocol: HTTPS
and port: 443
: required for enabling TLS.tls
: references the Kubernetes Secret created in the previous step.Apply the manifest to the cluster:
kubectl apply -f external-gateway.yaml
Save the following manifest as store-external-route.yaml
:
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: store-external
labels:
gateway: external-http
spec:
parentRefs:
- name: external-http
hostnames:
- "store.example.com"
rules:
- backendRefs:
- name: store-v1
port: 8080
This manifest describes an HTTPRoute that matches traffic to store.example.com
and sends it to the store-v1
Service.
Apply the manifest to the cluster:
kubectl apply -f store-external-route.yaml
Verify that the Gateway works by sending a request over the internet.
Get the IP address of the Gateway:
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"
The output is similar to the following:
203.0.113.12
This output is a public IP address, which means any client with internet access can connect to it.
Access the domain of the Gateway using curl
:
curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert CERTIFICATE_FILE -v
Replace the following:
GATEWAY_IP_ADDRESS
: the IP address of the Gateway load balancer.CERTIFICATE_FILE
: the certificate file that you generated. You must save this file on the machine that you are using to connect to the Gateway. The certificate is required to authenticate the Gateway because the Gateway uses a self-signed certificate.The --resolve
option resolves the domain name to the IP address of the Gateway, which is required because DNS is not configured for this domain.
The output is similar to the following:
...
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
* subject: O=example; CN=store.example.com
* start date: Apr 19 15:54:50 2021 GMT
* expire date: Apr 19 15:54:50 2022 GMT
* common name: store.example.com (matched)
* issuer: O=example; CN=store.example.com
* SSL certificate verify ok.
...
{
"cluster_name": "gw",
"host_header": "store.example.com",
"metadata": "store-v1",
"node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal",
"pod_name": "store-v1-84b47c7f58-tj5mn",
"pod_name_emoji": "😍",
"project_id": "agmsb-k8s",
"timestamp": "2021-04-19T16:30:08"
# Several lines of output omitted here.
}
This output includes a successful TLS handshake followed by a response from the application. The TLS connection is terminated at the Gateway and the application responds to the client securely.
In this example, you configure a Gateway with a Google-managed SSL certificate.
Note: Configuring an SSL Certificate and thenetworking.gke.io/certmap
annotation on the same Gateway is not a valid configuration and the controller will treat this as an error. Create an SSL certificate
Create a Google-managed global SslCertificate
resource:
gcloud compute ssl-certificates create store-example-com \
--domains=store.example.com \
--global
Save the following manifest as external-gateway.yaml
:
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: external-http
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
options:
networking.gke.io/pre-shared-certs: store-example-com
This manifest describes a Gateway with the following properties:
gatewayClassName: gke-l7-global-external-managed
: deploys a global external Application Load Balancer.protocol:HTTPS
and port:443
: required for enabling TLS.tls.mode:Terminate
: terminates TLS using your SSL certificate.Apply the manifest to your cluster:
kubectl apply -f external-gateway.yaml
Save the following HTTPRoute manifest as store-external-route.yaml
:
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: store-external
labels:
gateway: external-http
spec:
parentRefs:
- name: external-http
hostnames:
- "store.example.com"
rules:
- backendRefs:
- name: store-v1
port: 8080
Deploy the HTTPRoute in your cluster:
kubectl apply -f store-external-route.yaml
It might take several minutes for GKE to deploy the Gateway.
Get the IP address of the Gateway:
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"
The output is similar to the following:
203.0.113.12
This output is a public IP address, which means any client with internet access can connect to it.
Update an A or AAAA record to direct your domain to the IP address of the Gateway.
This step is only necessary if you are configuring a Google-managed SSL certificate. If you are configuring a self-managed certificate, you can skip this step.
After the DNS records are updated, it can take up to 10 minutes for your load balancer to begin using the Google-managed certificate.
Verify that the Gateway is working by sending a request over the internet using curl
:
curl https://store.example.com -v
The output is similar to the following:
...
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
* subject: O=example; CN=store.example.com
* start date: Apr 19 15:54:50 2021 GMT
* expire date: Apr 19 15:54:50 2022 GMT
* common name: store.example.com (matched)
* issuer: O=example; CN=store.example.com
* SSL certificate verify ok.
...
{
"cluster_name": "gw",
"host_header": "store.example.com",
"metadata": "store-v1",
"node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal",
"pod_name": "store-v1-84b47c7f58-tj5mn",
"pod_name_emoji": "😍",
"project_id": "agmsb-k8s",
"timestamp": "2021-04-19T16:30:08",
"zone": "us-west1-a"
}
This output includes a successful TLS handshake and a response from the application. TLS is terminated at the Gateway correctly and the application responds to the client securely.
In this example, you configure a Gateway using Certificate Manager.
Note: Configuring an SSL Certificate and thenetworking.gke.io/certmap
annotation on the same Gateway is not a valid configuration and the controller will treat this as an error. Create a Certificate
Global Gateway
To create a global Gateway, you reference a certificate map resource that contains one or more certificates. You must create at least one certificate and add it as an entry to your certificate map.
To create a certificate, first create a private key and certificate file.
Create a Certificate
resource by loading your self-managed certificate and key:
gcloud certificate-manager certificates create store-example-com-cert \
--certificate-file="cert.pem" \
--private-key-file="PRIVATE_KEY_FILE"
Create a CertificateMap
:
gcloud certificate-manager maps create store-example-com-map
Create a CertificateMapEntry
which assigns the certificate to the CertificateMap
:
gcloud certificate-manager maps entries create store-example-com-map-entry \
--map=store-example-com-map \
--hostname=store.example.com \
--certificates=store-example-com-cert
For a regional Gateway, you create a Certificate
which will be specified directly when creating the Gateway. Unlike a global Gateway, you don't need to create a CertificateMap
to which certificates are assigned.
Create a private key and certificate file.
Create a Certificate
resource by uploading your certificate file and key:
gcloud certificate-manager certificates create "CERTIFICATE_NAME" \
--certificate-file="CERTIFICATE_FILE" \
--private-key-file="PRIVATE_KEY_FILE" \
--location="REGION"
Replace the following:
CERTIFICATE_NAME
: the name of your certificate, for example store-example-com-cert
.CERTIFICATE_FILE
: the name of the certificate file, for example, cert.pem
.PRIVATE_KEY_FILE
: the name of your private key file, such as private-key.pem
. For more information, see Select or create a private key.REGION
: the name of the region in which you are configuring the Gateway, for example us-central1
.--location
flag with a --scope=all-regions
flag. Failing to use --scope=all-regions
will result in the certificate not being found when creating the gateway. For example 'Certificate' was not found
. Create a Gateway and HTTPRoute Global Gateway
To create a global Gateway, complete the following steps:
Save the following manifest as cert-map-gateway.yaml
:
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: external-http
annotations:
networking.gke.io/certmap: store-example-com-map
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: https
protocol: HTTPS
port: 443
This manifest describes a Gateway with the following properties:
gatewayClassName: gke-l7-global-external-managed
: deploys a global external Application Load Balancer.protocol: HTTPS
and port: 443
: required for enabling TLS.There is no TLS section because TLS is configured with Certificate Manager using the annotation networking.gke.io/certmap
.
Apply the manifest to the cluster:
kubectl apply -f cert-map-gateway.yaml
It might take several minutes for GKE to deploy the Gateway.
To create an HTTPRoute, save the following manifest as cert-map-http-route.yaml
:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: foo
namespace: default
spec:
parentRefs:
- name: external-http
hostnames:
- foo.example.com
rules:
- matches:
- path:
value: /
backendRefs:
- name: foo-v1
port: 8080
Apply the manifest to the cluster:
kubectl apply -f cert-map-http-route.yaml
When creating a regional Gateway, you can specify certificates managed by Certificate Manager and certificates managed by Compute Engine.
To create a regional external Gateway, save the following manifest as external-gateway.yaml
:
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: gateway
namespace: corp
spec:
gatewayClassName: gke-l7-regional-external-managed
listeners:
- name: gateway-pre-shared-certmap
protocol: HTTPS
port: 443
tls:
mode: Terminate
options:
networking.gke.io/cert-manager-certs: store-example-com-cert1, store-example-com-cert2
allowedRoutes:
kinds:
- kind: HTTPRoute
namespaces:
from: All
This manifest describes a Gateway with the following properties:
gatewayClassName
: gke-l7-regional-external-managed
: deploys a regional external Application Load Balancer.protocol: HTTPS
and port: 443
: required for enabling TLS.options
:
networking.gke.io/cert-manager-certs
: certificates managed by Certificate Manager.To create a regional internal Gateway, in the preceding example, change the value of gatewayClassName
to gke-l7-rilb
. This deploys an internal Application Load Balancer.
Apply the manifest to the cluster:
kubectl apply -f external-gateway.yaml
To create an HTTPRoute, save the following manifest as store-external-route.yaml
:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: store-external
labels:
gateway: external-http
spec:
parentRefs:
- name: external-http
hostnames:
- "store.example.com"
rules:
backendRefs:
- name: store-v1
port: 8080
This manifest describes an HTTPRoute that matches traffic for store.example.com
and forwards the traffic to the store-v1
Service.
Apply the manifest to the cluster:
kubectl apply -f store-external-route.yaml
Get the IP address of the Gateway:
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"
The output is similar to the following:
203.0.113.12
This output is a public IP address, which means any client with internet access can connect to it.
Update an A or AAAA record to direct your domain to the IP address of the Gateway.
This step is only necessary if you are configuring a Google-managed SSL Certificate. If you are configuring a self-managed certificate, you can skip this step.
After the DNS records are updated, it can take up to 10 minutes for your load balancer to begin using the Google-managed certificate.
Access the domain of the Gateway using curl
:
curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert CERTIFICATE_FILE -v
Replace the following:
GATEWAY_IP_ADDRESS
: the IP address of the Gateway load balancer.CERTIFICATE_FILE
: the certificate file that you generated. You must save this file on the machine that you are using to connect to the Gateway. The certificate is required to authenticate the Gateway because the Gateway uses a self-signed certificate.The output is similar to the following:
...
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
* subject: O=example; CN=store.example.com
* start date: Apr 19 15:54:50 2021 GMT
* expire date: Apr 19 15:54:50 2022 GMT
* common name: store.example.com (matched)
* issuer: O=example; CN=store.example.com
* SSL certificate verify ok.
...
{
"cluster_name": "gw",
"host_header": "store.example.com",
"metadata": "store-v1",
"node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal",
"pod_name": "store-v1-84b47c7f58-tj5mn",
"pod_name_emoji": "😍",
"project_id": "agmsb-k8s",
"timestamp": "2021-04-19T16:30:08",
"zone": "us-west1-a"
}
This output includes a successful TLS handshake and a response from the application. TLS is terminated at the Gateway correctly and the application responds to the client securely.
You can encrypt traffic from the load balancer to backend Pods using the ports[].appProtocol
field. The supported fields for appProtocol
are: HTTP
, HTTPS
, HTTP2
, and kubernetes.io/h2c
.
The following manifest describes a Service that specifies the load balancer must use HTTPS traffic to communication with the backend Pods:
apiVersion: v1
kind: Service
metadata:
name: store-v2
spec:
selector:
app: store
version: v2
ports:
- port: 8080
targetPort: 8080
appProtocol: HTTPS
The load balancer does not verify the certificate used by backend Pods. It is your responsibility to ensure the certificate used on the backend Pods is valid.
Note: The previously supportednetworking.gke.io/app-protocol
is deprecated. This annotation is not supported by the GKE Gateway controller. Secure client to load balancer traffic using SSL policies
When your applications are exposed through an external gateway that uses HTTPS, it is important to use the latest protocols or specify the minimum SSL or TLS version. You can secure the client to load balancer traffic by using SSL policies.
To know more about SSL policies that can be attached to your Gateway and how to create them, see Configure SSL Policies to secure client to load balancer traffic.
Protect your backends using Google Cloud ArmorGoogle Cloud Armor security policies help you protect your load-balanced applications from web-based attacks. Once you have configured a Google Cloud Armor security policy, you can reference it in a GCPBackendPolicy
applied to your Kubernetes Services.
To configure Google Cloud Armor policies with Gateway, see Configure Google Cloud Armor security policy to secure your backend Services.
Authenticate requests to your backends using Identity-Aware ProxyIdentity-Aware Proxy helps you protect your backends from unwanted traffic by authenticating clients sending requests to your applications and enforcing role-based traffic authorization. After you enable Identity-Aware Proxy for GKE, you can reference your OAuth credentials in a GCPBackendPolicy
applied to your Kubernetes Services.
To configure Identity-Aware Proxy with Gateway, see Configure Identity-Aware Proxy.
What's nextExcept as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-08-07 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-07 UTC."],[],[]]
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4