本頁面說明如何使用各種安全防護功能保護 Gateway:
安全資料傳輸層 (SSL) 政策,確保閘道使用必要的安全通訊協定和演算法
使用 TLS 保護用戶端到閘道,以及閘道到後端的流量
Google Cloud Armor 安全性政策,可保護服務免於遭受 DDoS 攻擊
Identity-Aware Proxy (IAP),可在允許存取服務前提供驗證和授權層級
如要進一步瞭解閘道安全性,請參閱「閘道安全性」。
事前準備
開始之前,請確認你已完成下列工作:
- 啟用 Google Kubernetes Engine API。 啟用 Google Kubernetes Engine API
- 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行
gcloud components update
,取得最新版本。
GKE Gateway 控制器需求
- 如果是標準叢集,則須使用 GKE 1.24 以上版本。
- 如果是 Autopilot,則須為 GKE 1.26 以上版本。
- Google Cloud CLI 407.0.0 以上版本。
- 閘道 API 僅支援虛擬私有雲原生叢集。
- 如果您使用內部 GatewayClass,則必須啟用僅限 Proxy 的子網路。
- 叢集必須啟用
HttpLoadBalancing
外掛程式。 - 如果您使用 Istio,請務必將 Istio 升級至下列其中一個版本:
- 1.15.2 以上版本
- 1.14.5 以上版本
- 1.13.9 以上版本。
- 如果您使用共用虛擬私有雲,則需要在主機專案中,將
Compute Network User
角色指派給服務專案的 GKE 服務帳戶。
規定與限制
除了 GKE Gateway 控制器的限制,Gateway 安全性還受到下列限制:
在閘道上使用 SSL 憑證或 Certificate Manager 的 TLS 設定,不支援 GKE 1.28.4-gke.1083000 版。針對這個 GKE 版本,請改用 Kubernetes 密鑰。
您無法在同一個 Gateway 資源上,將
networking.gke.io/certmap
註解與tls.certificateRefs
搭配使用。如果您在 Gateway 中參照CertificateMap
,GKE 會將此視為錯誤。憑證管理工具支援自行管理和 Google 代管的憑證。Google 代管憑證與區域閘道和全球閘道相容。
使用 Google 代管的 SSL 憑證時,您必須在 GKE 外部建立 SSL 憑證,才能將憑證附加至 Gateway。
如果您在
GCPBackendPolicy
中參照 Google Cloud Armor 後端安全政策,就無法將同一項服務做為區域和全域閘道的後端。您必須為這個用途建立兩項不同的服務和政策。Gateway 控制器不支援
ManagedCertificate
資源。Gateway 控制器不支援
networking.gke.io/managed-certificates
註解。
如需 GKE 支援的 Gateway API 欄位清單,以及 GatewayClass 資源的功能,請參閱 GatewayClass 功能。
使用 Kubernetes Secret 保護閘道
在本範例中,您將使用 Kubernetes Secret 設定 Gateway。
將憑證儲存在 Kubernetes Secret 中
您可以使用憑證授權單位 (CA) 核發及驗證的憑證,也可以建立自行簽署的憑證。下列步驟使用自簽憑證。
建立私密金鑰:
openssl genrsa -out PRIVATE_KEY_FILE 2048
將
PRIVATE_KEY_FILE
替換為私密金鑰檔案的名稱,例如private-key.pem
。詳情請參閱「選取或建立私密金鑰」。建立 Open SSL 設定檔:
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
將
CONFIG_FILE
替換為新設定檔的名稱,例如config-file.cnf
。建立憑證簽署要求 (CSR) 檔案:
openssl req -new -key PRIVATE_KEY_FILE \ -out CSR_FILE \ -config CONFIG_FILE
將
CSR_FILE
替換為新的 CSR 檔案名稱,例如cert.pem
。詳情請參閱建立 CSR。簽署 CSR:
openssl x509 -req \ -signkey PRIVATE_KEY_FILE \ -in CSR_FILE \ -out CERTIFICATE_FILE \ -extfile CONFIG_FILE \ -extensions extension_requirements \ -days 30
將
CERTIFICATE_FILE
替換為指令產生的檔案路徑和名稱,例如cert-file.pem
。詳情請參閱「簽署 CSR」。使用您建立的金鑰和憑證檔案,建立 Kubernetes TLS 密鑰:
kubectl create secret tls store-example-com \ --cert=CERTIFICATE_FILE \ --key=PRIVATE_KEY_FILE
GKE 會將憑證和金鑰儲存為 Kubernetes 資源,您可以將這些資源附加至 Gateway。
建立閘道和 HTTPRoute
將下列資訊清單儲存為
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
這個資訊清單說明具有下列屬性的閘道:
gatewayClassName: gke-l7-global-external-managed
:部署全域外部應用程式負載平衡器。protocol: HTTPS
和port: 443
:啟用 TLS 時必須提供。tls
:參照上一個步驟中建立的 Kubernetes Secret。
將資訊清單套用至叢集:
kubectl apply -f external-gateway.yaml
將下列資訊清單儲存為
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
這個資訊清單說明 HTTPRoute,該路徑會將流量比對至
store.example.com
,並傳送至store-v1
服務。將資訊清單套用至叢集:
kubectl apply -f store-external-route.yaml
驗證閘道
透過網際網路傳送要求,確認閘道是否正常運作。
取得閘道的 IP 位址:
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"
輸出結果會與下列內容相似:
203.0.113.12
這個輸出內容是公開 IP 位址,也就是說,任何可存取網際網路的用戶端都能連線至該位址。
使用
curl
存取閘道的網域:curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert CERTIFICATE_FILE -v
更改下列內容:
GATEWAY_IP_ADDRESS
:Gateway 負載平衡器的 IP 位址。CERTIFICATE_FILE
:您產生的憑證檔案。您必須將這個檔案儲存在用來連線至閘道的電腦上。由於閘道使用自行簽署的憑證,因此需要憑證來驗證閘道。
「
--resolve
」選項會將網域名稱解析為閘道的 IP 位址,因為這個網域未設定 DNS,所以必須使用這個選項。輸出結果會與下列內容相似:
... * 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. }
這項輸出內容包括成功的 TLS 握手,以及應用程式的回應。TLS 連線會在閘道終止,應用程式會安全地回應用戶端。
使用 SSL 憑證保護閘道
在本範例中,您將設定具有 Google 代管 SSL 憑證的閘道。
建立 SSL 憑證
建立 Google 代管的通用
SslCertificate
資源:gcloud compute ssl-certificates create store-example-com \ --domains=store.example.com \ --global
建立閘道和 HTTPRoute
將下列資訊清單儲存為
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
這個資訊清單說明具有下列屬性的閘道:
gatewayClassName: gke-l7-global-external-managed
:部署全域外部應用程式負載平衡器。protocol:HTTPS
和port:443
:啟用 TLS 時必須提供。tls.mode:Terminate
:使用 SSL 憑證終止 TLS。
將資訊清單套用至叢集:
kubectl apply -f external-gateway.yaml
將下列 HTTPRoute 資訊清單儲存為
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
在叢集中部署 HTTPRoute:
kubectl apply -f store-external-route.yaml
GKE 可能需要幾分鐘才能部署 Gateway。
驗證閘道
取得閘道的 IP 位址:
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"
輸出結果會與下列內容相似:
203.0.113.12
這個輸出內容是公開 IP 位址,也就是說,任何可存取網際網路的用戶端都能連線至該位址。
更新 A 或 AAAA 記錄,將網域導向閘道的 IP 位址。
只有在設定 Google 代管 SSL 憑證時,才需要執行這個步驟。如果您要設定自行管理的憑證,可以略過這個步驟。
更新 DNS 記錄後,負載平衡器最多可能需要 10 分鐘,才會開始使用 Google 代管憑證。
透過網際網路使用
curl
傳送要求,確認閘道是否正常運作:curl https://store.example.com -v
輸出結果會與下列內容相似:
... * 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" }
這項輸出內容包括成功的 TLS 握手和應用程式的回應。TLS 在閘道正確終止,且應用程式安全地回應用戶端。
使用 Certificate Manager 保護閘道安全
在本範例中,您將使用 Certificate Manager 設定 Gateway。
建立 Certificate
全球閘道
如要建立全域閘道,請參照包含一或多個憑證的憑證對應關係資源。您必須建立至少一個憑證,並將其新增為憑證對應表中的項目。
如要建立憑證,請先建立私密金鑰和憑證檔案。
載入自行管理的憑證和金鑰,建立
Certificate
資源:gcloud certificate-manager certificates create store-example-com-cert \ --certificate-file="cert.pem" \ --private-key-file="PRIVATE_KEY_FILE"
建立
CertificateMap
:gcloud certificate-manager maps create store-example-com-map
建立
CertificateMapEntry
,將憑證指派給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
區域閘道
如果是區域閘道,您要建立 Certificate
,並在建立閘道時直接指定。與全球閘道不同,您不需要建立指派憑證的 CertificateMap
。
建立私密金鑰和憑證檔案。
上傳憑證檔案和金鑰,建立
Certificate
資源:
gcloud certificate-manager certificates create "CERTIFICATE_NAME" \
--certificate-file="CERTIFICATE_FILE" \
--private-key-file="PRIVATE_KEY_FILE" \
--location="REGION"
更改下列內容:
CERTIFICATE_NAME
:憑證名稱,例如store-example-com-cert
。CERTIFICATE_FILE
:憑證檔案的名稱,例如cert.pem
。PRIVATE_KEY_FILE
:私密金鑰檔案的名稱,例如private-key.pem
。詳情請參閱「選取或建立私密金鑰」。REGION
:您要設定閘道的區域名稱,例如us-central1
。
建立閘道和 HTTPRoute
全球閘道
如要建立全域閘道,請完成下列步驟:
將下列資訊清單儲存為
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
這個資訊清單說明具有下列屬性的閘道:
gatewayClassName: gke-l7-global-external-managed
:部署全域外部應用程式負載平衡器。protocol: HTTPS
和port: 443
:啟用 TLS 時必須提供。
由於 TLS 是使用註解
networking.gke.io/certmap
,透過 Certificate Manager 設定,因此沒有 TLS 區段。將資訊清單套用至叢集:
kubectl apply -f cert-map-gateway.yaml
GKE 可能需要幾分鐘才能部署 Gateway。
如要建立 HTTPRoute,請將下列資訊清單儲存為
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
將資訊清單套用至叢集:
kubectl apply -f cert-map-http-route.yaml
區域閘道
建立區域閘道時,您可以指定由 Certificate Manager 管理的憑證,以及由 Compute Engine 管理的憑證。
如要建立地區外部閘道,請將下列資訊清單儲存為
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
這個資訊清單說明具有下列屬性的閘道:
gatewayClassName
:gke-l7-regional-external-managed
:部署區域性外部應用程式負載平衡器。protocol: HTTPS
和port: 443
:啟用 TLS 時必須提供。options
:networking.gke.io/cert-manager-certs
:由 Certificate Manager 管理的憑證。
如要在上述範例中建立區域內部閘道,請將
gatewayClassName
的值變更為gke-l7-rilb
。這會部署內部應用程式負載平衡器。將資訊清單套用至叢集:
kubectl apply -f external-gateway.yaml
如要建立 HTTPRoute,請將下列資訊清單儲存為
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
這個資訊清單說明 HTTPRoute,該 HTTPRoute 會比對
store.example.com
的流量,並將流量轉送至store-v1
服務。將資訊清單套用至叢集:
kubectl apply -f store-external-route.yaml
驗證閘道
取得閘道的 IP 位址:
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"
輸出結果會與下列內容相似:
203.0.113.12
這個輸出內容是公開 IP 位址,也就是說,任何可存取網際網路的用戶端都能連線至該位址。
更新 A 或 AAAA 記錄,將網域導向閘道的 IP 位址。
只有在設定 Google 代管 SSL 憑證時,才需要執行這個步驟。如果您要設定自行管理的憑證,可以略過這個步驟。
更新 DNS 記錄後,負載平衡器最多可能需要 10 分鐘,才會開始使用 Google 代管憑證。
使用
curl
存取閘道的網域:curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert CERTIFICATE_FILE -v
更改下列內容:
GATEWAY_IP_ADDRESS
:Gateway 負載平衡器的 IP 位址。CERTIFICATE_FILE
:您產生的憑證檔案。您必須將這個檔案儲存在用來連線至閘道的電腦上。由於閘道使用自行簽署的憑證,因此需要憑證來驗證閘道。
輸出結果會與下列內容相似:
... * 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" }
這項輸出內容包括成功的 TLS 握手和應用程式的回應。TLS 在閘道正確終止,且應用程式安全地回應用戶端。
使用 TLS 保護負載平衡器與應用程式之間的流量
您可以使用 ports[].appProtocol
欄位,加密從負載平衡器到後端 Pod 的流量。appProtocol
支援的欄位包括:HTTP
、HTTPS
、HTTP2
和 kubernetes.io/h2c
。
下列資訊清單說明 Service,其中指定負載平衡器必須使用 HTTPS 流量與後端 Pod 通訊:
apiVersion: v1
kind: Service
metadata:
name: store-v2
spec:
selector:
app: store
version: v2
ports:
- port: 8080
targetPort: 8080
appProtocol: HTTPS
負載平衡器不會驗證後端 Pod 使用的憑證。您有責任確保後端 Pod 使用的憑證有效。
使用 SSL 政策保護用戶端到負載平衡器的流量
透過使用 HTTPS 的外部閘道公開應用程式時,請務必使用最新通訊協定,或指定最低 SSL 或 TLS 版本。您可以使用 SSL 政策,保護用戶端到負載平衡器的流量。
如要進一步瞭解可附加至閘道的 SSL 政策,以及如何建立這些政策,請參閱「設定 SSL 政策,確保用戶端到負載平衡器的流量安全無虞」。
使用 Google Cloud Armor 保護後端
Google Cloud Armor 安全性政策可協助您保護負載平衡應用程式,防範網路攻擊。設定 Google Cloud Armor 安全性政策後,您可以在套用至 Kubernetes 服務的 GCPBackendPolicy
中參照該政策。
如要透過 Gateway 設定 Google Cloud Armor 政策,請參閱「設定 Google Cloud Armor 安全性政策,保護後端服務」。
使用 Identity-Aware Proxy 驗證對後端的要求
Identity-Aware Proxy 可驗證傳送應用程式要求的用戶端,並強制執行以角色為基礎的流量授權,協助您保護後端免受不必要的流量影響。啟用 GKE 適用的 Identity-Aware Proxy 後,您可以在套用至 Kubernetes 服務的 GCPBackendPolicy
中參照 OAuth 憑證。
如要透過閘道設定 Identity-Aware Proxy,請參閱「設定 Identity-Aware Proxy」。
後續步驟
- 進一步瞭解閘道安全性。