GKE 1.29 にアップグレードする前に TLS 証明書の互換性を確認する


バージョン 1.29 以降を実行している GKE クラスタは、SHA-1 アルゴリズムで署名された Transportation Layer Security(TLS)証明書をサポートしていません。クラスタへの影響を防ぐには、クラスタをバージョン 1.29 にアップグレードする前に、Webhook拡張機能 API サーバー バックエンドの互換性のない証明書を互換性のある署名アルゴリズムを使用する証明書に置き換える必要があります。

この削除のクラスタへの影響

クラスタがバージョン 1.29 と互換性のない証明書を使用していることを検出すると、GKE は自動アップグレードを一時停止します。互換性のある署名アルゴリズムの証明書に証明書を置き換えるか、バージョン 1.28 のサポートが終了すると、GKE はアップグレードを自動的に再開します。

1.29 にアップグレードする前に互換性のない証明書を置き換えないと、クラスタで次の問題が発生する可能性があります。

  • 認証の失敗により、SHA-1 アルゴリズムで署名された TLS 証明書を使用する GKE Webhook バックエンドが機能しなくなります。Kubernetes コントロール プレーンが互換性のない証明書を使用して Webhook と通信すると、Webhook 呼び出しが失敗します。構成によっては(特にアドミッション Webhook を使用している場合は)、Webhook との接続に失敗すると、クラスタでのリソース作成(Pod の作成など)がブロックされる可能性があり、これは大きな混乱を招く可能性があります。
  • 拡張機能 API サーバーによって提供される API の呼び出しは失敗します。

Kubernetes がこの機能を削除する理由

GKE はオープンソースの Kubernetes を運用しています。この Kubernetes は kube-apiserver コンポーネントを使用し、TLS 経由で Webhook と拡張 API サーバー バックエンドに接続します。kube-apiserver コンポーネントは Go プログラミング言語で記述されています。

Go バージョン 1.18 以降、Go では SHA-1 アルゴリズムで署名された TLS 証明書が拒否されていますが、移行プロセスを容易にするため、以前の動作を有効にするデバッグ スイッチ x509sha1=1 が用意されています。GKE バージョン 1.24 は、Go バージョン 1.18 を使用してビルドされた最初のバージョンです。Kubernetes の GKE ビルドでは、バージョン 1.29 までこのデバッグ スイッチが有効になっています。このスイッチは Go 1.24 で削除される予定です。GKE 1.29 では、Go でのデバッグ スイッチの削除に備えて、スイッチを無効にして Kubernetes をビルドしています。GKE がクラスタをバージョン 1.29 にアップグレードすると、SHA-1 アルゴリズムで署名された TLS 証明書を提供するクラスタ内の Webhook または拡張機能 API サーバーに対するクラスタのコントロール プレーンからの呼び出しは失敗します。

影響を受けるクラスタを特定する

SHA-1 アルゴリズムで署名された TLS 証明書を使用する Webhook または拡張機能 API サーバー バックエンドのあるクラスタを特定できるように、GKE はクラスタをモニタリングし、Recommender サービスを使用して分析情報と推奨事項という形式でガイダンスを提供しています。また、ログを参照して、影響を受けるバックエンドに対するクラスタからの呼び出しを特定することもできます。

分析情報と推奨事項を取得する方法

バージョン 1.24 以降を実行しているクラスタの場合は、分析情報と推奨事項を表示するの説明に従って操作します。分析情報を取得するには、gcloud CLI または Recommender API を使用し、サブタイプ DEPRECATION_K8S_SHA_1_CERTIFICATE でフィルタリングします。

ログの取得方法

Cloud Logging が有効な状態で 1.24 以降を実行しているクラスタの場合、Cloud Audit Logs ログを使用して、影響を受けるバックエンドの呼び出しを特定できます。次のフィルタを使用してログを検索できます。

logName =~ "projects/.*/logs/cloudaudit.googleapis.com%2Factivity"
resource.type = "k8s_cluster"
operation.producer = "k8s.io"
"insecure-sha1.invalid-cert.kubernetes.io"

監査ログには、影響を受けたバックエンドのホスト名が含まれます。結果の解釈方法については、次のセクションをご覧ください。

分析情報と推奨事項のガイダンスを解釈する

推奨事項では、影響を受けるバックエンドのホスト名が提示されます。また、それが Webhook と拡張機能 API サーバーのどちらであるかも示されます。クラスタ内の Service を参照するホスト名は <service-name>.<namespace>.svc の形式になります。

影響を受けるバックエンド証明書が Webhook サーバーからのものである場合、ホスト名はクラスタ内の Service または URL のいずれかになります。詳細については、Webhook への接続をご覧ください。

影響を受ける証明書が拡張機能 API サーバーのものである場合、ホスト名はクラスタ内の Service になります。詳細については、拡張機能 API サーバーへの接続をご覧ください。

影響を受けるバックエンドを特定したら、Service の証明書を検査するまたは URL バックエンドの証明書を検査するの手順に沿って操作します。

過去 30 日間に、影響を受ける証明書を使用してクラスタがサーバーを呼び出していない場合、推奨事項は表示されません。

推奨事項のサンプル

推奨事項の例を以下に示します。

RECOMMENDATION_ID                     PRIMARY_IMPACT_CATEGORY  RECOMMENDATION_STATE  LAST_REFRESH_TIME               PRIORITY  RECOMMENDER_SUBTYPE                DESCRIPTION
26bfcb32-6f2a-407c-874f-8cf55b3af912  RELIABILITY              ACTIVE                2024-02-15T01:09:04.454456273Z  P2        DEPRECATION_K8S_SHA_1_CERTIFICATE  Update the webhook and/or extension API servers that use certificates signed with SHA-1 algorithm to use certificates with compatible signing algorithms prior to upgrading the cluster to version 1.29. [Learn more](https://cloud.google.com/kubernetes-engine/docs/deprecations/sha1-1-29#mitigate_the_risk_of_upgrading_to_129).

クラスタと Service の詳細を取得するには、推奨事項を取得しますdefault Namespace の example-webhook という Service の出力は次のようになります。

associatedInsights:
- insight: projects/<CLUSTER_PROJECT_NUMBER>/locations/<CLUSTER_LOCATION>/insightTypes/google.container.DiagnosisInsight/insights/d76887a8-9eed-41a0-9459-d49dee43455e
content:
  overview:
    featureDeprecationRecommendation:
    - featureName: x.509_certificate_signature_algorithm
      featureReplacementValue: algorithm [compatible with GKE v1.29](https://cloud.google.com/kubernetes-engine/docs/deprecations/sha1-1-29#compatible-signing-algorithms)
      featureValue: SHA1
      stopServingVersion: '1.29'
      targetType: hostname
      targetValue: example-webhook.default.svc
    targetClusters:
    - clusterId: 3be916a554724c79a2314c8baee3fd57cf1c39df1ad34c3daf291db701b6d541
      clusterUri: //container.googleapis.com/projects/<CLUSTER_PROJECT_NUMBER>/locations/<CLUSTER_LOCATION>/clusters/<CLUSTER_NAME>
description: Update the webhook and/or extension API servers that use certificates
  signed with SHA-1 algorithm to use certificates with compatible signing algorithms
  prior to upgrading the cluster to version 1.29. [Learn more](https://cloud.google.com/kubernetes-engine/docs/deprecations/sha1-1-29#mitigate_the_risk_of_upgrading_to_129).
etag: '"ad50aac8278951d5"'
lastRefreshTime: '2024-02-15T01:09:04.454456273Z'
name: projects/<CLUSTER_PROJECT_NUMBER>/locations/<CLUSTER_LOCATION>/recommenders/google.container.DiagnosisRecommender/recommendations/26bfcb32-6f2a-407c-874f-8cf55b3af912
primaryImpact:
  category: RELIABILITY
  reliabilityProjection:
    risks:
    - SERVICE_DISRUPTION
priority: P2
recommenderSubtype: DEPRECATION_K8S_SHA_1_CERTIFICATE
stateInfo:
  state: ACTIVE
targetResources:
- //container.googleapis.com/projects/<CLUSTER_PROJECT_NUMBER>/locations/<CLUSTER_LOCATION>/clusters/<CLUSTER_NAME>

Service の証明書を検査する

Service では、Webhook と拡張機能 API サーバーの両方がサポートされます。

検査するバックエンド サービスを特定したら、次の手順でサービスの証明書を検査し、SHA-1 アルゴリズムを使用する証明書と更新する必要がある証明書を確認します。

  1. Service のセレクタとターゲット ポートを確認します。

    kubectl describe service --namespace=NAMESPACE SERVICE_NAME
    

    NAMESPACESERVICE_NAMEtargetValue の値に置き換えます。

    出力は次のようになります。

    Name: example-service
    Namespace: default
    Labels: run=nginx
    Selector: run=nginx
    Type: ClusterIP
    IP: 172.21.xxx.xxx
    Port: 443
    TargetPort: 444
    

    この出力は、example-service にセレクタ run=nginx とターゲット ポート 444 があることを示しています。

  2. セレクタに一致する Pod を見つけます。

    kubectl get pods --namespace=NAMESPACE --selector=run=nginx
    

    出力は次のようになります。

    NAME          READY   STATUS    RESTARTS   AGE
    example-pod   1/1     Running   0          21m
    

    この出力は、一致する Pod が example-pod であることを示しています。

  3. kubectl localhost から Pod へのポート転送を設定します。

    kubectl port-forward --namespace=NAMESPACE pods/example-pod 8888:SERVICE_TARGET_PORT &
    

    SERVICE_TARGET_PORT は、Service の TargetPort 値に置き換えます。TargetPort が含まれていない場合は、Port 値を使用します。

  4. openssl を使用して、Service が使用する証明書を表示します。

    openssl s_client -connect localhost:8888 </dev/null | openssl x509 -noout -text
    

    次の出力例は、SHA-256 アルゴリズムで署名された有効な証明書を示しています。

    Certificate:
        Data:
            ...
            Signature Algorithm: sha256WithRSAEncryption
    ...
        Signature Algorithm: sha256WithRSAEncryption
    

    次の出力例は、SHA-1 アルゴリズムで署名された無効な証明書を示しています。

    Certificate:
        Data:
            ...
            Signature Algorithm: sha1WithRSAEncryption
    ...
        Signature Algorithm: sha1WithRSAEncryption
    

    証明書からの出力がこれと類似している場合は、互換性のある署名アルゴリズムを使用するように証明書を更新する必要があります。たとえば、certificate.k8s.io API を使用してクラスタ内の TLS 証明書を管理する場合は、証明書署名リクエストを作成の手順に沿って操作します。

ポート転送をクリーンアップする

バックグラウンドで実行されているポート転送をクリーンアップするには、プロセスを特定して終了します。

  1. 次のコマンドを実行して、実行中のプロセスを一覧表示します。

    jobs
    

    出力を参照して、終了するプロセスの ID を取得します。

    [1]+  Running                 kubectl port-forward pods/example-pod 8888:444 &
    

    この出力例は、プロセス ID が 1 であることを示しています。

  2. PROCESS_ID を置き換えて、プロセスを終了します。

    kill %PROCESS_ID
    

    次の出力例をご覧ください。

    [1]+  Terminated              kubectl port-forward pods/example 8888:444
    

    この出力例は、プロセスが終了したことを示しています。

URL バックエンドの証明書を検査する

Webhook が url バックエンドを使用する場合は、URL で指定されたホスト名に直接接続します。たとえば、URL が https://example.com:123/foo/bar の場合、次の openssl コマンドを使用して、バックエンドが使用する証明書を表示します。

openssl s_client -connect example.com:123 </dev/null | openssl x509 -noout -text

次の出力例は、SHA-256 アルゴリズムで署名された有効な証明書を示しています。

Certificate:
    Data:
        ...
        Signature Algorithm: sha256WithRSAEncryption
...
    Signature Algorithm: sha256WithRSAEncryption

次の出力例は、SHA-1 アルゴリズムで署名された無効な証明書を示しています。

Certificate:
    Data:
        ...
        Signature Algorithm: sha1WithRSAEncryption
...
    Signature Algorithm: sha1WithRSAEncryption

証明書からの出力がこれと類似している場合は、互換性のある署名アルゴリズムを使用するように証明書を更新する必要があります。たとえば、certificate.k8s.io API を使用してクラスタ内の TLS 証明書を管理する場合は、証明書署名リクエストを作成の手順に沿って操作します。

1.29 へのアップグレードによるリスクを軽減する

SHA-1 アルゴリズムで署名された証明書を使用して影響を受けるクラスタとそのバックエンド サービスを特定したら、クラスタをバージョン 1.29 にアップグレードする前に、互換性のある署名アルゴリズムの証明書を使用するように Service を更新する必要があります。

影響を受けるクラスタは GKE によって自動的に検出されます。互換性のない証明書が使用されなくなるか、バージョン 1.28 がサポート終了になるまで、バージョン 1.29 への自動アップグレードは行われません。1.28 がサポート終了になると、クラスタは 1.29 に自動的にアップグレードされます。

互換性のある署名アルゴリズム

GKE バージョン 1.29 は、Go x509 パッケージでサポートされているアルゴリズムと互換性があります。これには、次のアルゴリズムが含まれます。

  • SHA256WithRSA
  • SHA384WithRSA
  • SHA512WithRSA
  • ECDSAWithSHA256
  • ECDSAWithSHA384
  • ECDSAWithSHA512
  • SHA256WithRSAPSS
  • SHA384WithRSAPSS
  • SHA512WithRSAPSS
  • PureEd25519

使用可能なアルゴリズムを確認するには、x509.go のソースファイルUnknownSignatureAlgorithm SignatureAlgorithm = iota を検索してください。Go x509 パッケージがサポートするアルゴリズムは、この行を含む const ブロックに示されています。安全でないサポート対象外の署名アルゴリズムを見つけるには、ファイル内で InsecureAlgorithmError を検索します。

リソース

この変更について詳しくは、次のリソースをご覧ください。