このページでは、次のようなセキュリティ機能を使用して 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
を実行して最新のバージョンを取得する。
GKE Gateway コントローラの要件
- Standard の場合、GKE バージョン 1.24 以降を使用します。
- Autopilot の場合、GKE バージョン 1.26 以降。
- Google Cloud CLI バージョン 407.0.0 以降。
- Gateway API は、VPC ネイティブ クラスタでのみサポートされます。
- 内部 GatewayClass を使用している場合は、プロキシ専用サブネットを有効にする必要があります。
- クラスタで
HttpLoadBalancing
アドオンが有効になっている必要があります。 - Istio を使用している場合は、Istio を次のバージョンのいずれかにアップグレードする必要があります。
- 1.15.2 以降
- 1.14.5 以降
- 1.13.9 以降
- 共有 VPC を使用している場合は、ホスト プロジェクトで、サービス プロジェクトの GKE サービス アカウントに
Compute Network User
ロールを割り当てる必要があります。
制限事項
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
アノテーションをサポートしていません。サービス構成の
appProtocol
フィールドには、プロトコル値(HTTP
、HTTPS
、HTTP2
)の大文字のみを使用できます。小文字を使用すると、バックエンドにプロトコルとして HTTP が使用されます。
サポートされている Gateway API フィールドと、GKE で使用可能な GatewayClass リソースの機能の一覧については、GatewayClass の機能をご覧ください。
Kubernetes Secret を使用して Gateway を保護する
この例では、Kubernetes Secret を使用して Gateway を構成します。
証明書を Kubernetes Secret に保存する
認証局(CA)によって発行および検証された証明書を使用するか、自己署名証明書を作成できます。次の手順では、自己署名証明書を使用します。
秘密鍵を作成します。
openssl genrsa -out PRIVATE_KEY_FILE 2048
PRIVATE_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 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 Secret を作成します。
kubectl create secret tls store-example-com \ --cert=CERTIFICATE_FILE \ --key=PRIVATE_KEY_FILE
GKE は、Gateway に接続できる Kubernetes リソースとして証明書と鍵を保存します。
ゲートウェイと 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
このマニフェストには、
store.example.com
へのトラフィックを照合してstore-v1
Service に送信する 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 アドレスです。つまり、インターネットにアクセスできるクライアントであれば、このアドレスに接続できます。
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 * 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
ゲートウェイと 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 をデプロイするまでに数分かかることがあります。
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/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
リージョン Gateway
リージョン Gateway を作成するときに、Certificate Manager で管理されている証明書と Compute Engine で管理されている証明書を指定できます。
リージョン外部 Gateway を作成するには、次のマニフェストを
external-gateway.yaml
として保存します。kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: gateway namespace: corp spec: gatewayClassName: gke-17-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
このマニフェストでは、次のプロパティを持つ Gateway が記述されています。
gatewayClassName
:gke-l7-regional-external-managed
: リージョン外部アプリケーション ロードバランサをデプロイします。protocol: HTTPS
とport: 443
: TLS を有効にするために必要です。options
:networking.gke.io/cert-manager-certs
: Certificate Manager で管理されている証明書。
リージョン内部 Gateway を作成するには、上記の例で
gatewayClassName
の値をgke-17-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
このマニフェストには、
store.example.com
のトラフィックを照合してstore-v1
Service に転送する 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
です。
次のマニフェストでは、HTTPS Pod を使用してバックエンド 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 ポリシーを使用することで、クライアントからロードバランサのトラフィックを保護できます。
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 のセキュリティの詳細を確認する。