このページでは、次のようなセキュリティ機能を使用して Gateway を保護する方法について説明します。
SSL ポリシー。Gateway が必要な安全なプロトコルとアルゴリズムを使用していることを確認します。
証明書。クライアントから Gateway へのトラフィックと Gateway からバックエンドへのトラフィックを TLS で保護するために使用します。
Google Cloud Armor セキュリティ ポリシー。DDoS 攻撃からサービスを保護します。
Identity-Aware Proxy(IAP)、Service へのアクセスを許可する前に認証と認可のレイヤを提供します。
Gateway のセキュリティの詳細については、Gateway のセキュリティをご覧ください。
始める前に
作業を始める前に、次のタスクが完了していることを確認してください。
- Google Kubernetes Engine API を有効にする。 Google Kubernetes Engine API の有効化
- このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化する。すでに gcloud CLI をインストールしている場合は、
gcloud components updateコマンドを実行して最新のバージョンを取得します。以前のバージョンの gcloud CLI では、このドキュメントのコマンドを実行できない場合があります。
GKE Gateway コントローラの要件
- Gateway API は、VPC ネイティブ クラスタでのみサポートされます。
- リージョンまたはクロスリージョンの GatewayClass を使用している場合は、プロキシ専用サブネットを有効にする必要があります。
- クラスタで
HttpLoadBalancingアドオンが有効になっている必要があります。 - Istio を使用している場合は、Istio を次のいずれかのバージョンにアップグレードする必要があります。
- 1.15.2 以降
- 1.14.5 以降
- 1.13.9 以降
共有 VPC を使用している場合は、ホスト プロジェクトで、サービス プロジェクトの GKE サービス アカウントに
Compute Network Userロールを割り当てる必要があります。既存の Autopilot クラスタまたは Standard クラスタがあることを確認します。必要な場合は、Autopilot クラスタを作成します。
制限事項
GKE Gateway Controller の制限事項と制限に加えて、Gateway のセキュリティには次の制限があります。
Gateway で SSL 証明書または Certificate Manager を使用する TLS 構成は、GKE バージョン 1.28.4-gke.1083000 ではサポートされていません。この GKE バージョンでは、回避策として Kubernetes Secret を使用してください。
同じ Gateway リソースに対して、
tls.certificateRefsとnetworking.gke.io/certmapアノテーションを使用することはできません。Gateway でCertificateMapを参照すると、GKE はこれをエラーとして扱います。Certificate Manager は、セルフマネージド証明書と Google マネージド証明書の両方をサポートしています。Google マネージド証明書は、リージョン Gateway およびグローバル Gateway と互換性があります。
Google マネージド SSL 証明書を使用する場合は、Gateway に接続する前に GKE の外部で SSL 証明書を作成する必要があります。
GCPBackendPolicyで Google Cloud Armor バックエンド セキュリティ ポリシーを参照している場合、同じサービスをリージョン Gateway とグローバル Gateway のバックエンドとして使用することはできません。このユースケースでは、2 つのサービスとポリシーを個別に作成する必要があります。Gateway Controller は
ManagedCertificateリソースをサポートしていません。Gateway Controller は
networking.gke.io/managed-certificatesアノテーションをサポートしていません。
サポートされている Gateway API フィールドと、GKE で使用可能な GatewayClass リソースの機能の一覧については、GatewayClass の機能をご覧ください。
Kubernetes Secret を使用して Gateway を保護する
この例では、Kubernetes Secret を使用して Gateway を構成します。
証明書を Kubernetes Secret に保存する
認証局(CA)によって発行および検証された証明書を使用するか、自己署名証明書を作成できます。次の手順では、自己署名証明書を使用します。
秘密鍵を作成します。
openssl genrsa -out PRIVATE_KEY_FILE 2048PRIVATE_KEY_FILEは、秘密鍵ファイルの名前(private-key.pemなど)に置き換えます。詳細については、秘密鍵を選択または作成するをご覧ください。OpenSSL 構成ファイルを作成します。
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 EOFCONFIG_FILEは、新しい構成ファイルの名前(config-file.cnfなど)に置き換えます。証明書署名リクエスト(CSR)ファイルを作成するには、次の操作を行います。
openssl req -new -key PRIVATE_KEY_FILE \ -out CSR_FILE \ -config CONFIG_FILECSR_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 30CERTIFICATE_FILEは、コマンドによって生成されたファイルのパスと名前(cert-file.pemなど)に置き換えます。詳細については、CSR に署名するをご覧ください。作成した鍵と証明書ファイルを使用して Kubernetes TLS Secret を作成します。
kubectl create secret tls store-example-com \ --cert=CERTIFICATE_FILE \ --key=PRIVATE_KEY_FILEGKE は、Gateway に接続できる Kubernetes リソースとして証明書と鍵を保存します。
Gateway と HTTPRoute を作成する
次のマニフェストを
external-gateway.yamlとして保存します。kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http spec: gatewayClassName: gke-l7-global-external-managed listeners: - name: https protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs: # Directly reference the Kubernetes Secret containing the TLS certificate and private key. - name: store-example-com # The name of the TLS secret.このマニフェストでは、次のプロパティを持つゲートウェイが記述されています。
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/v1 metadata: name: store-external labels: gateway: external-http spec: parentRefs: - name: external-http # Link this route to the 'external-http' Gateway. hostnames: - "store.example.com" # Match traffic for this hostname. rules: - backendRefs: # Define where to forward the traffic. - name: store-v1 port: 8080このマニフェストには、
store.example.comへのトラフィックを照合してstore-v1Service に送信する HTTPRoute が記述されています。マニフェストをクラスタに適用します。
kubectl apply -f store-external-route.yaml
Gateway を確認する
インターネット経由でリクエストを送信して、Gateway が動作することを確認します。
Gateway の IP アドレスを取得します。
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"出力は次のようになります。
203.0.113.12この出力はパブリック IP アドレスです。つまり、インターネットにアクセスできるクライアントであれば、このアドレスに接続できます。
curlを使用して Gateway のドメインにアクセスします。curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert CERTIFICATE_FILE -v次のように置き換えます。
GATEWAY_IP_ADDRESS: Gateway ロードバランサの IP アドレス。CERTIFICATE_FILE: 生成した証明書ファイル。Gateway への接続に使用しているマシンに、このファイルを保存する必要があります。Gateway は自己署名証明書を使用するため、Gateway の認証には証明書が必要です。
--resolveオプションは、ドメイン名を Gateway の 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 # This block shows the certificate details presented by the Gateway. # The value of the 'common name' field matches the requested hostname. * 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 handshake が成功した後のアプリケーションからのレスポンスが含まれます。TLS 接続はゲートウェイで終端し、アプリケーションはクライアントに安全に応答します。
SSL 証明書を使用して Gateway を保護する
この例では、Google マネージド SSL 証明書を使用して Gateway を構成します。
SSL 証明書の作成
Google マネージドのグローバル
SslCertificateリソースを作成します。gcloud compute ssl-certificates create store-example-com \ --domains=store.example.com \ --global
Gateway と HTTPRoute を作成する
次のマニフェストを
external-gateway.yamlとして保存します。kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http spec: gatewayClassName: gke-l7-global-external-managed listeners: - name: https protocol: HTTPS port: 443 tls: mode: Terminate # Terminate TLS using your SSL certificate. options: networking.gke.io/pre-shared-certs: store-example-com # Specify the Google Cloud SSL certificate resource name.このマニフェストでは、次のプロパティを持つゲートウェイが記述されています。
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/v1 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.yamlGKE が Gateway をデプロイするまでに数分かかることがあります。
Gateway を確認する
Gateway の IP アドレスを取得します。
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"出力は次のようになります。
203.0.113.12この出力はパブリック IP アドレスです。つまり、インターネットにアクセスできるクライアントであれば、このアドレスに接続できます。
A レコードまたは AAAA レコードを更新して、ドメインをゲートウェイの IP アドレスにリダイレクトします。
この手順は、Google マネージド SSL 証明書を構成する場合にのみ必要です。セルフマネージド証明書を構成する場合は、この手順をスキップできます。
DNS レコードの更新後、ロードバランサが Google マネージド証明書の使用を開始するまでに最大で 10 分かかることがあります。
curlを使用してインターネット経由でリクエストを送信し、Gateway が機能していることを確認します。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 handshake が成功した後のアプリケーションからのレスポンスが含まれます。ゲートウェイで TLS が正しく終端され、アプリケーションがクライアントに安全に応答します。
Certificate Manager を使用して Gateway を保護する
この例では、Certificate Manager を使用して Gateway を構成します。
Certificate を作成する
グローバル Gateway
グローバル Gateway を作成するには、1 つ以上の証明書を含む証明書マップ リソースを参照します。少なくとも 1 つの証明書を作成し、証明書マップへのエントリとして追加する必要があります。
証明書を作成するには、まず秘密鍵と証明書ファイルを作成します。
セルフマネージド証明書と鍵を読み込んで、
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証明書を
CertificateMapに割り当てるCertificateMapEntryを作成します。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
リージョン Gateway
リージョン Gateway の場合は、Gateway の作成時に直接指定する Certificate を作成します。グローバル Gateway とは異なり、証明書が割り当てられる 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: Gateway を構成するリージョンの名前(例:us-central1)。
Gateway と HTTPRoute を作成する
グローバル Gateway
グローバル Gateway を作成するには、次の操作を行います。
次のマニフェストを
cert-map-gateway.yamlとして保存します。kind: Gateway apiVersion: gateway.networking.k8s.io/v1 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 # No TLS section is included here because TLS is handled by the certmap annotation.このマニフェストでは、次のプロパティを持つゲートウェイが記述されています。
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.yamlGKE が Gateway をデプロイするまでに数分かかることがあります。
HTTPRoute を作成するには、次のマニフェストを
cert-map-http-route.yamlとして保存します。apiVersion: gateway.networking.k8s.io/v1 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
リージョン Gateway
リージョン Gateway を作成するときに、Certificate Manager で管理されている証明書と Compute Engine で管理されている証明書を指定できます。
リージョン外部 Gateway を作成するには、次のマニフェストを
external-gateway.yamlとして保存します。kind: Gateway apiVersion: gateway.networking.k8s.io/v1 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 # TLS is terminated at the Gateway. options: # Specifies a comma-separated list of Certificate Manager certificates to use for TLS termination. networking.gke.io/cert-manager-certs: store-example-com-cert1, store-example-com-cert2 # These certificates are directly managed by Certificate Manager. allowedRoutes: kinds: - kind: HTTPRoute namespaces: from: Allこのマニフェストでは、次のプロパティを持つ Gateway が記述されています。
gatewayClassName:gke-l7-regional-external-managed: リージョン外部アプリケーション ロードバランサをデプロイします。protocol: HTTPSとport: 443: TLS を有効にするために必要です。options:networking.gke.io/cert-manager-certs: Certificate Manager で管理されている証明書。
リージョン内部 Gateway を作成するには、上記の例で
gatewayClassNameの値をgke-l7-rilbに変更します。これにより、内部アプリケーション ロードバランサがデプロイされます。マニフェストをクラスタに適用します。
kubectl apply -f external-gateway.yamlHTTPRoute を作成するには、次のマニフェストを
store-external-route.yamlとして保存します。apiVersion: gateway.networking.k8s.io/v1 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このマニフェストには、
store.example.comのトラフィックを照合してstore-v1Service に転送する HTTPRoute が記述されています。マニフェストをクラスタに適用します。
kubectl apply -f store-external-route.yaml
Gateway を確認する
Gateway の IP アドレスを取得します。
kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}"出力は次のようになります。
203.0.113.12この出力はパブリック IP アドレスです。つまり、インターネットにアクセスできるクライアントであれば、このアドレスに接続できます。
A レコードまたは AAAA レコードを更新して、ドメインをゲートウェイの IP アドレスにリダイレクトします。
この手順は、Google マネージド SSL 証明書を構成する場合にのみ必要です。セルフマネージド証明書を構成する場合は、この手順をスキップできます。
DNS レコードの更新後、ロードバランサが Google マネージド証明書の使用を開始するまでに最大で 10 分かかることがあります。
curlを使用して Gateway のドメインにアクセスします。curl https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert CERTIFICATE_FILE -v次のように置き換えます。
GATEWAY_IP_ADDRESS: Gateway ロードバランサの IP アドレス。CERTIFICATE_FILE: 生成した証明書ファイル。Gateway への接続に使用しているマシンに、このファイルを保存する必要があります。Gateway は自己署名証明書を使用するため、Gateway の認証には証明書が必要です。
出力は次のようになります。
... * 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 handshake が成功した後のアプリケーションからのレスポンスが含まれます。ゲートウェイで TLS が正しく終端され、アプリケーションがクライアントに安全に応答します。
TLS を使用してロードバランサからアプリケーションへのトラフィックを保護する
ports[].appProtocol フィールドを使用して、ロードバランサからバックエンド Pod へのトラフィックを暗号化できます。appProtocol でサポートされているフィールドは、HTTP、HTTPS、HTTP2、kubernetes.io/h2c です。
次のマニフェストでは、ロードバランサがバックエンド Pod との通信に HTTPS トラフィックを使用する必要があることを指定する Service を記述しています。
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 ポリシーを使用することで、クライアントからロードバランサのトラフィックを保護できます。
Gateway に接続できる SSL ポリシーとその作成方法の詳細については、クライアントからロードバランサのトラフィックを保護する SSL ポリシーの構成をご覧ください。
Google Cloud Armor を使用してバックエンドを保護する
Google Cloud Armor セキュリティ ポリシーは、負荷分散されたアプリケーションをウェブベースの攻撃から保護するのに役立ちます。Google Cloud Armor セキュリティ ポリシーを構成すると、Kubernetes Services に適用される GCPBackendPolicy で参照できます。
Gateway で Google Cloud Armor ポリシーを構成するには、バックエンド サービスを保護する Google Cloud Armor セキュリティ ポリシーを構成するをご覧ください。
Identity-Aware Proxy を使用してバックエンドへのリクエストを認証する
Identity-Aware Proxy は、アプリケーションにリクエストを送信するクライアントを認証し、ロールベースのトラフィック認可を適用することで、不要なトラフィックからバックエンドを保護します。GKE 用 Identity-Aware Proxy を有効にすると、Kubernetes Service に適用された GCPBackendPolicy で OAuth 認証情報を参照できます。
Gateway を使用して Identity-Aware Proxy を構成するには、Identity-Aware Proxy を構成するをご覧ください。
次のステップ
- Gateway のセキュリティの詳細を確認する。
- ポリシーを使用して Gateway リソースを構成する方法を学習する。
- Gateway をデプロイする方法を学習する。
- Gateway API の詳細を確認する