CVE-2026-119115 AWS PCA Issuer|影響と更新前確認

  • URLをコピーしました!
目次

はじめに

2026 年 10 月 29 日(米国太平洋時間)、AWS は AWS Private CA Connector for Kubernetes(aws-privateca-issuer)の認可不備 CVE-2026-119115 を Security Bulletin 2026-156-AWS で公表しました。aws-privateca-issuer は、cert-manager の外部 Issuer として AWS Private CA に証明書の署名を依頼するコンポーネントで、Amazon EKS では EKS add-on としても提供されています。

修正版の v1.10.1 は脆弱性を修正する一方で、証明書要求の issuerRef.kind を厳密に検証するようになりました。従来の緩い解決処理に依存していた Certificate や Ingress は、更新後に証明書の自動更新が止まる可能性があります。脆弱性対応の更新が、証明書の期限切れによる障害の原因にならないよう、更新前の棚卸しが重要です。

この記事でわかること
  • CVE-2026-119115 の内容と、AWSPCAIssuer / AWSPCAClusterIssuer の認可境界
  • 影響する提供形態(Helm 等 / EKS add-on / 派生コード)と修正版
  • 更新前に実施する読み取り専用の棚卸し手順
  • v1.10.1 で発行や自動更新が止まる issuerRef.kind の設定パターンと修正方法
  • 更新後の確認項目と、すぐに更新できない場合の暫定対策

結論として、aws-privateca-issuer v1.10.1 未満、または EKS add-on v1.10.1-eksbuild.1 未満を導入している環境は、修正版への更新を推奨します。ただし、v1.10.1 は issuerRef.kind が AWSPCAIssuer または AWSPCAClusterIssuer と完全に一致し、参照先の種類とも一致することを要求するため、更新前に Certificate と Ingress の設定を修正する必要があります。修正せずに更新すると、該当する証明書の更新が止まり、証明書の期限切れ時にサービスへ影響します。

なお、本記事は公開されている一次情報と修正コードに基づく解説であり、筆者による実機検証は行っていません。

CVE-2026-119115 の概要と認可不備

CVE-2026-119115 は、aws-privateca-issuer が証明書要求の参照先 Issuer を解決する処理の認可不備(CWE-863)です。名前空間スコープの Issuer しか承認されていない認証済みの主体が、承認されていないクラスタースコープの Issuer から証明書を取得できる可能性があります。

脆弱性の基本情報

項目内容
CVE IDCVE-2026-119115
AdvisoryAWS Security Bulletin 2026-156-AWS、GHSA-hjrh-q6pg-mh82
公表日2026 年 10 月 29 日(米国太平洋時間)
修正版のリリース日2026 年 10 月 13 日(GitHub の v1.10.1 リリース)
深刻度CVSS v3.1 8.5(High)、AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:N(GHSA)
脆弱性の種類CWE-863(不適切な認可)
攻撃の前提証明書要求を作成できる認証済みの主体(PR:L)
悪用状況AWS Bulletin と GHSA に悪用事例の記載なし(2026 年 11 月 3 日時点)

参考: GitHub Security Advisory GHSA-hjrh-q6pg-mh82
“does not correctly enforce the distinction between namespace-scoped and cluster-scoped issuers”
(Issuer 解決処理が、名前空間スコープの Issuer とクラスタースコープの Issuer の区別を正しく適用していません。)
https://github.com/cert-manager/aws-privateca-issuer/security/advisories/GHSA-hjrh-q6pg-mh82

AWSPCAIssuer と AWSPCAClusterIssuer の認可境界

aws-privateca-issuer は 2 種類の Issuer リソースを提供します。どちらも AWS Private CA の CA を参照する点は同じで、違いは参照できる範囲です。

AWSPCAIssuer

名前空間スコープの Issuer です。同じ namespace の Certificate や CertificateRequest から参照され、チームやアプリケーション単位で利用できる CA を分ける用途に使われます。

AWSPCAClusterIssuer

クラスタースコープの Issuer です。名前空間に属さず、すべての namespace から参照できます。共通の CA や、上位の CA を参照する用途で使われることがあります。

cert-manager では、CertificateRequest に Approved 条件が付かない限り、Issuer は署名しません。aws-privateca-issuer も承認済みの要求だけを処理します。承認を行う approver(cert-manager 内部の承認コントローラーや approver-policy など)は、要求の spec.issuerRef(name / kind / group)を基に承認可否を判断します。つまり、承認ポリシーは「どの Issuer を使うか」を要求に書かれた参照先で判断し、その参照先を実際の Issuer へ解決するのは aws-privateca-issuer 側です。

修正前の Issuer 解決処理で起きていたこと

修正コミット(9ae225b)の差分によると、修正前の Issuer 解決処理は、まず要求と同じ namespace から AWSPCAIssuer を名前で検索し、見つからない場合は同じ名前の AWSPCAClusterIssuer を検索していました。kind の値は、AWSPCAClusterIssuer の場合に namespace を外す判定にしか使われていませんでした。

この結果、承認側は「名前空間スコープの Issuer への要求」として承認したにもかかわらず、実際にはクラスタースコープの Issuer が署名する、という承認内容と実行内容のずれが生じ得ました。修正版では、kind が指定した種類のリソースだけを検索します。

参考: aws-privateca-issuer 修正コミット 9ae225b
“the lookup now follows issuerRef.kind”
(Issuer の検索は issuerRef.kind に従うようになりました。)
https://github.com/cert-manager/aws-privateca-issuer/commit/9ae225b69557023025040845ab5f157b88815a94

下位 CA 証明書が影響に含まれる意味と、影響の範囲

AWS は、取得し得る証明書に下位 CA 証明書が含まれると説明しています。下位 CA 証明書と秘密鍵を不正に入手した主体は、その CA を信頼するクライアントに対して有効な証明書を自ら発行できる可能性があります。これは個別のサーバー証明書の不正取得より影響範囲が広くなり得るため、CVSS で完全性(I)が High と評価されている点と整合します。

ただし、下位 CA 証明書を実際に発行できるかは環境に依存します。aws-privateca-issuer は要求の用途や Issuer の spec.pcaTemplate 設定に応じて AWS Private CA の証明書テンプレートを選択するため、クラスタースコープ Issuer の設定や AWS Private CA 側の構成によって結果は異なります(編集上の整理)。また、次の点も区別して判断してください。

  • 認証不要の攻撃ではなく、証明書要求を作成できる認証済み主体による条件付きの認可不備です。
  • AWS Private CA サービス自体の侵害ではなく、クラスター内で動作する Issuer コンポーネントの不備です。
  • 公表資料に悪用事例の記載はありませんが、悪用が存在しないことを示すものではありません。

影響する環境と修正版

影響を受けるのは、aws-privateca-issuer を導入しているクラスターです。cert-manager を使っていても、aws-privateca-issuer を導入していない環境は対象外です。提供形態ごとの影響範囲と修正版は次のとおりです。

提供形態主な管理方法影響範囲修正版
aws-privateca-issuerHelm チャート、マニフェストv1.10.1 未満(GHSA の表記では 1.10.0 以下)v1.10.1
AWS Private CA Connector for Kubernetes EKS add-on(aws-privateca-connector-for-kubernetes)EKS add-onv1.10.1-eksbuild.1 未満v1.10.1-eksbuild.1
Fork、派生コード、再ビルドされたコンテナイメージ各提供元修正内容を取り込んでいないもの修正の取り込みを提供元で確認

Helm 等で管理している環境と EKS add-on では、バージョンの確認方法と更新手順が異なります。EKS add-on の名前空間は aws-privateca-issuer です。AWS は、Fork や派生コードを利用している場合も修正内容を取り込むよう求めています。サードパーティーが再パッケージしたイメージを使っている場合は、提供元のアドバイザリで修正の取り込み状況を確認してください。

参考: AWS Security Bulletin 2026-156-AWS
“v1.10.1 enforces that issuerRef.kind is exactly AWSPCAIssuer or AWSPCAClusterIssuer”
(v1.10.1 は、issuerRef.kind が AWSPCAIssuer または AWSPCAClusterIssuer と完全に一致することを強制します。)
https://aws.amazon.com/security/security-bulletins/2026-156-aws/

更新前に確認する Issuer と証明書設定

更新前に、影響判定と互換性問題の洗い出しを読み取り専用のコマンドで行います。このセクションのコマンドはいずれもリソースを変更しません。<cluster-name> などの山括弧は環境に合わせて置き換えてください。

手順
Connector / EKS add-on の導入有無とバージョンを確認する

EKS add-on の場合は、add-on のバージョンを確認します。

aws eks describe-addon --cluster-name <cluster-name> --addon-name aws-privateca-connector-for-kubernetes --query 'addon.addonVersion' --output text

Helm で導入している場合は、リリース一覧の CHART と APP VERSION を確認します。

helm list -A

導入方法が不明な場合や、独自にビルドしたイメージを使っている可能性がある場合は、稼働中の Deployment のイメージを確認します。

kubectl get deploy -A -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,IMAGE:.spec.template.spec.containers[*].image' | grep -i privateca
手順
AWSPCAIssuer / AWSPCAClusterIssuer の一覧を確認する

どの namespace にどの AWSPCAIssuer があり、どの名前の AWSPCAClusterIssuer があるかを確認します。後の手順で、証明書の参照先と照合するために使います。

kubectl get awspcaissuers -A
kubectl get awspcaclusterissuers

後続の手順で参照先と照合するため、Issuer、Certificate、Ingress を JSON で作業端末に保存します。ファイルを保存するだけで、クラスターのリソースは変更しません。

kubectl get awspcaissuers -A -o json > awspcaissuers.json
kubectl get awspcaclusterissuers -o json > awspcaclusterissuers.json
kubectl get certificates -A -o json > certificates.json
kubectl get ingress -A -o json > ingresses.json
手順
CertificateRequest の issuerRef を確認する

既存の CertificateRequest の issuerRef.name / kind / group と状態を一覧にします。kind や group が未設定の場合は <none> と表示されます。group が awspca.cert-manager.io の行で、kind が AWSPCAIssuer、AWSPCAClusterIssuer 以外のものは、修正版で Failed になる設定が使われていた痕跡です。

kubectl get certificaterequests -A -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,ISSUER:.spec.issuerRef.name,KIND:.spec.issuerRef.kind,GROUP:.spec.issuerRef.group,READY:.status.conditions[?(@.type=="Ready")].reason'

Certificate を介さずに CertificateRequest を直接作成する仕組みを使っている場合は、その仕組みの設定で Issuer の kind をどう指定しているかも確認対象です。

手順
Certificate の issuerRef を確認する

今後の更新に直接影響するのは Certificate の設定です。group で絞り込むと、group の省略や誤りを見落とすため、すべての Certificate を対象に issuerRef.name / kind / group と、手順 2 で保存した実在する Issuer を照合します。次の判定条件を check-certificates.jq として保存します。

($ns[0].items | map("\(.metadata.namespace)/\(.metadata.name)")) as $nsi
| ($cl[0].items | map(.metadata.name)) as $cli
| .items[]
| (.spec.issuerRef.name // "") as $n
| (.spec.issuerRef.kind // "") as $k
| (.spec.issuerRef.group // "") as $g
| "\(.metadata.namespace)/\($n)" as $key
| ($nsi | index($key)) as $hasNs
| ($cli | index($n)) as $hasCl
| (if $g == "awspca.cert-manager.io" then
     (if $k == "AWSPCAIssuer" then (if $hasNs != null then "OK" elif $hasCl != null then "PENDING_RISK" else "NOT_FOUND" end)
      elif $k == "AWSPCAClusterIssuer" then (if $hasCl != null then "OK" else "NOT_FOUND" end)
      else "FAILED_RISK" end)
   elif ($k == "AWSPCAIssuer" or $k == "AWSPCAClusterIssuer" or $hasNs != null or $hasCl != null) then "CHECK_GROUP"
   else "OTHER" end) as $r
| [$r, .metadata.namespace, .metadata.name, $n, (if $k == "" then "(none)" else $k end), (if $g == "" then "(none)" else $g end)]
| @tsv
jq -r --slurpfile ns awspcaissuers.json --slurpfile cl awspcaclusterissuers.json -f check-certificates.jq certificates.json

出力の 1 列目が判定結果です。判定の意味と対応は次のとおりです。この判定は本稿で用意した確認用の分類で、修正版の挙動は AWS Bulletin と GHSA、修正前の挙動は修正コミットの差分に基づいています。

判定意味対応
OKgroup、kind、参照先の種類が一致している対応不要
FAILED_RISKgroup は awspca.cert-manager.io だが、kind が省略または AWSPCAIssuer / AWSPCAClusterIssuer 以外修正版で Failed になるため、kind を修正
PENDING_RISKkind は AWSPCAIssuer だが、同じ namespace に同名の AWSPCAIssuer がなく、同名の AWSPCAClusterIssuer がある修正版で Pending になるため、意図した参照先に合わせて kind または name を修正
NOT_FOUND指定した種類の Issuer が存在しない参照先の名前、namespace、kind を確認
CHECK_GROUPkind や name は aws-privateca-issuer を指しているが、group が省略または別の値意図した Issuer を確認し、group を明示
CHECK_CLUSTER_ISSUERIngress の cluster-issuer 注釈が AWSPCAClusterIssuer と同じ名前を指しているissuer、issuer-kind、issuer-group の注釈へ書き換えを検討
OTHERaws-privateca-issuer 以外の Issuer を参照していると判断したもの名前の重複がないかを目視で確認
手順
Ingress の cert-manager 関連注釈を確認する

Ingress の注釈から Certificate を自動生成している場合、Issuer の指定元は Ingress です。cert-manager の注釈を持つすべての Ingress について、issuer、cluster-issuer、issuer-kind、issuer-group を同じ考え方で判定します。次の内容を check-ingresses.jq として保存します。

($ns[0].items | map("\(.metadata.namespace)/\(.metadata.name)")) as $nsi
| ($cl[0].items | map(.metadata.name)) as $cli
| .items[]
| (.metadata.annotations // {}) as $a
| select($a | to_entries | any(.key | startswith("cert-manager.io/")))
| ($a["cert-manager.io/issuer"] // "") as $n
| ($a["cert-manager.io/cluster-issuer"] // "") as $c
| ($a["cert-manager.io/issuer-kind"] // "") as $k
| ($a["cert-manager.io/issuer-group"] // "") as $g
| "\(.metadata.namespace)/\($n)" as $key
| ($nsi | index($key)) as $hasNs
| ($cli | index($n)) as $hasCl
| (if $c != "" and ($cli | index($c)) != null then "CHECK_CLUSTER_ISSUER"
   elif $g == "awspca.cert-manager.io" then
     (if $k == "AWSPCAIssuer" then (if $hasNs != null then "OK" elif $hasCl != null then "PENDING_RISK" else "NOT_FOUND" end)
      elif $k == "AWSPCAClusterIssuer" then (if $hasCl != null then "OK" else "NOT_FOUND" end)
      else "FAILED_RISK" end)
   elif $n != "" and ($k == "AWSPCAIssuer" or $k == "AWSPCAClusterIssuer" or $hasNs != null or $hasCl != null) then "CHECK_GROUP"
   else "OTHER" end) as $r
| [$r, .metadata.namespace, .metadata.name, (if $n == "" then "-" else $n end), (if $c == "" then "-" else $c end), (if $k == "" then "(none)" else $k end), (if $g == "" then "(none)" else $g end)]
| @tsv
jq -r --slurpfile ns awspcaissuers.json --slurpfile cl awspcaclusterissuers.json -f check-ingresses.jq ingresses.json

判定結果の意味は手順 4 の表と同じです。issuer-group が awspca.cert-manager.io で issuer-kind が (none) の Ingress は、修正版で Failed になる設定です。

手順
設定から判定できない証明書を Secret から補完する

group と kind をどちらも省略し、名前も一致しない設定や、Certificate 以外の仕組みで発行された証明書は、手順 4、5 の判定で漏れる可能性があります。cert-manager が発行した証明書の Secret には発行元を示す注釈が付くため、現在 aws-privateca-issuer で発行されている証明書を Secret 側から一覧にし、手順 4、5 の結果と突き合わせます。

kubectl get secrets -A --field-selector type=kubernetes.io/tls -o json | jq -r '.items[] | select(.metadata.annotations["cert-manager.io/issuer-group"] == "awspca.cert-manager.io") | [.metadata.namespace, .metadata.name, (.metadata.annotations["cert-manager.io/certificate-name"] // "-"), (.metadata.annotations["cert-manager.io/issuer-kind"] // "(none)"), (.metadata.annotations["cert-manager.io/issuer-name"] // "-")] | @tsv'

このコマンドには Secret の読み取り権限が必要です。出力は注釈の値だけで、秘密鍵は表示しません。issuer-kind が (none) や AWSPCAIssuer / AWSPCAClusterIssuer 以外の Secret は、元の Certificate や Ingress の設定を確認してください。

手順
承認ポリシーと RBAC の設定を確認する

証明書要求の承認権限(cert-manager の signers リソースに対する approve)を持つ ClusterRole を抽出し、kubectl describe clusterrole <name> で resourceNames を確認します。

kubectl get clusterroles -o json | jq -r '.items[] | select(any(.rules[]?; (.resources // [] | index("signers")) and (.verbs // [] | index("approve")))) | .metadata.name'

approver-policy を導入している場合は、CertificateRequestPolicy の selector を確認します。

kubectl get certificaterequestpolicies -o yaml

cert-manager の内部承認コントローラーで外部 Issuer を自動承認している場合は、cert-manager の Helm 値の approveSignerNames を確認します。awspcaclusterissuers.awspca.cert-manager.io/* のように、クラスタースコープ Issuer への要求を一律に承認する設定になっていないかが確認ポイントです。

helm get values <cert-manager-release> -n <cert-manager-namespace>
手順
証明書の有効期限と次回更新予定を確認する

aws-privateca-issuer を参照する Certificate を、次回更新予定(renewalTime)の早い順に並べます。更新予定が近いものほど、設定の誤りがあれば早くサービス影響につながるため、修正と確認の優先度を上げます。group の省略を見落とさないよう、kind が AWSPCAIssuer / AWSPCAClusterIssuer のものも対象に含めています。

jq -r '[.items[] | select(.spec.issuerRef.group == "awspca.cert-manager.io" or .spec.issuerRef.kind == "AWSPCAIssuer" or .spec.issuerRef.kind == "AWSPCAClusterIssuer")] | sort_by([(.status.renewalTime == null), .status.renewalTime]) | .[] | [.metadata.namespace, .metadata.name, (.spec.issuerRef.kind // "(none)"), (.status.renewalTime // "(未設定)"), (.status.notAfter // "(未設定)")] | @tsv' certificates.json

renewalTime が未設定の Certificate は一覧の末尾に「(未設定)」と表示されます。まだ発行が完了していない、または発行に失敗している可能性があるため、更新予定の近い証明書とは別に、手順 3 の CertificateRequest の状態を確認してください。

v1.10.1 更新時の issuerRef.kind の注意点

修正版では、issuerRef.kind が参照先 Issuer の種類と一致しない要求は処理されません。AWS は、従来の緩い解決処理に依存していた証明書要求は更新後に renewal が止まり、その証明書に依存するサービスは証明書の期限切れ時に影響を受けると説明しています。

修正版で変わる判定

issuerRef.kind実在する参照先修正前(v1.10.0 以前)修正版(v1.10.1 以降)
AWSPCAIssuer同じ namespace の同名 AWSPCAIssuer発行される発行される
AWSPCAClusterIssuer同名の AWSPCAClusterIssuer発行される発行される
AWSPCAIssuer同名の AWSPCAClusterIssuer のみAWSPCAClusterIssuer で発行されるPending のまま進まない
Issuer、省略、その他の値同名の AWSPCAIssuer または AWSPCAClusterIssuer名前で解決されて発行されるFailed

修正版の列は AWS Bulletin と GHSA の説明、修正前の列は修正コミットの差分から読み取れる挙動を整理したものです。修正版のコードでは、Failed の場合は unsupported issuer kind、Pending の場合は issuer could not be found というメッセージが CertificateRequest の Ready 条件に設定されます。

Ingress 注釈で kind を省略した場合の既定値

Ingress の cert-manager.io/issuer 注釈は、kind を指定しない場合に cert-manager の Issuer を参照する前提で Certificate を生成します。AWS は、Ingress 注釈で issuer kind を指定しない場合に cert-manager が設定する kind: Issuer も、修正版では Failed になると明記しています。

参考: cert-manager Documentation(Annotated Ingress resource)
“It will default to cert-manager.io Issuer”
(cert-manager.io の Issuer が既定値になります。)
https://cert-manager.io/docs/usage/ingress/

aws-privateca-issuer を Ingress から使う場合は、名前空間スコープ、クラスタースコープのどちらでも cert-manager.io/issuer に Issuer 名を指定し、cert-manager.io/issuer-kind と cert-manager.io/issuer-group を併記します。cert-manager.io/cluster-issuer は cert-manager 自身の ClusterIssuer 用の短縮指定であり、AWSPCAClusterIssuer の指定には使えません。AWSPCAClusterIssuer を参照する場合の例は次のとおりです。

metadata:
  annotations:
    cert-manager.io/issuer: example-cluster-issuer
    cert-manager.io/issuer-kind: AWSPCAClusterIssuer
    cert-manager.io/issuer-group: awspca.cert-manager.io

Certificate を直接定義している場合は、issuerRef に kind と group を明示します。名前空間スコープの Issuer を参照する場合は、kind を AWSPCAIssuer にし、同じ namespace に同名の AWSPCAIssuer があることを確認します。

spec:
  issuerRef:
    name: example-cluster-issuer
    kind: AWSPCAClusterIssuer
    group: awspca.cert-manager.io

CertificateRequest は直接編集しない

Failed や Pending になった CertificateRequest の issuerRef を書き換えて回避することはできません。CertificateRequest は一度きりの要求を表すリソースで、spec は作成後に変更できません。

参考: cert-manager Documentation(CertificateRequest resource)
“are immutable and cannot be modified after creation”
(作成後は変更できない、不変のフィールドです。)
https://cert-manager.io/docs/usage/certificaterequest/

修正は、CertificateRequest を生成している設定元に対して行います。Ingress から生成された Certificate は ingress-shim が Ingress の注釈に合わせて管理するため、Certificate ではなく Ingress の注釈を修正します。直接定義した Certificate は、その issuerRef を修正します。修正した設定は、次回の更新時に新しい CertificateRequest へ反映されます。次回更新を待たずに確認したい場合は cmctl renew <certificate-name> -n <namespace> で再発行を手動で開始でき、cert-manager が新しい CertificateRequest を作成します。

Argo CD や Flux などで Kubernetes マニフェストを管理している場合は、Git 上のマニフェストや Helm 値を修正してください。クラスター上のリソースだけを直接修正すると、同期時に元の設定へ戻され、更新後に再び発行が止まる可能性があります。

更新を安全に進める順序

正しい kind の指定は修正前のバージョンでも受け付けられるため、設定の修正を先に済ませてから修正版へ更新すると、互換性問題と脆弱性対応を切り分けられます(編集上の推奨)。全証明書を更新前に再発行する必要はありません。棚卸しと設定修正は対象を絞って短期間で済ませ、修正版の適用を不必要に遅らせないことを推奨します。

手順
設定元の kind を修正する

棚卸しで見つかった Ingress の注釈と Certificate の issuerRef を、参照先の種類に合わせて修正します。

手順
影響の小さい対象で再発行を確認する

検証環境の証明書や、影響の小さい代表的な証明書を選び、cmctl renew で再発行して、新しい CertificateRequest の kind が正しく、Certificate が Ready になることを確認します。cmctl renew は実際の再発行を開始するコマンドです。Certificate の spec.privateKey.rotationPolicy が Always の場合は秘密鍵も新しく生成されるため、証明書や鍵を固定して参照しているシステムがある対象は避けてください。

手順
検証環境で修正版へ更新し、動作を確認する

更新後は、次のセクションの確認項目で発行と状態を確認します。EKS add-on の場合は、利用可能なバージョンに v1.10.1-eksbuild.1 以降が含まれることを確認してから更新します。add-on の設定値をカスタマイズしている場合は、EKS の add-on 更新手順で競合時の扱いを確認してください。

aws eks describe-addon-versions --addon-name aws-privateca-connector-for-kubernetes --query 'addons[].addonVersions[].addonVersion'
aws eks update-addon --cluster-name <cluster-name> --addon-name aws-privateca-connector-for-kubernetes --addon-version v1.10.1-eksbuild.1

Helm の場合は、チャートのバージョンとアプリケーションのバージョンが異なる場合があるため、APP VERSION が 1.10.1 以降のチャートを確認してから、現在の values ファイルを指定して更新します。

helm repo update
helm search repo awspca/aws-privateca-issuer --versions
helm upgrade <release> awspca/aws-privateca-issuer -n <namespace> --version <chart-version> -f <current-values.yaml>
手順
本番環境を段階的に更新する

検証環境で発行と更新を確認できたら、影響の小さいクラスターから順に更新し、各クラスターで次のセクションの確認を行います。

更新後の確認と暫定対策

更新後は、新しい証明書要求が正しい Issuer で処理されること、既存の証明書が次回更新でも Ready を維持できることを確認します。すぐに更新できない環境では、承認ポリシーと RBAC の範囲を絞る暫定対策を検討します。

更新後に確認する項目

まず、CertificateRequest の Ready 条件の理由とメッセージを確認し、unsupported issuer kind(Failed)や issuer could not be found(Pending)が出ていないかを確認します。REASON が <none> の行は Ready 条件がまだ設定されていない要求で、承認待ちなどで処理が進んでいない可能性があるため、あわせて確認します。

kubectl get certificaterequests -A -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,KIND:.spec.issuerRef.kind,REASON:.status.conditions[?(@.type=="Ready")].reason,MESSAGE:.status.conditions[?(@.type=="Ready")].message'

次に、Ready が True でない Certificate と、Ready 条件そのものが設定されていない Certificate を抽出します。自動更新に失敗した証明書や、発行処理が始まっていない証明書もここで検出できます。

kubectl get certificates -A -o json | jq -r '.items[] | ([.status.conditions[]? | select(.type == "Ready")] | .[0]) as $c | select($c == null or $c.status != "True") | [.metadata.namespace, .metadata.name, (.spec.issuerRef.kind // "(none)"), (if $c == null then "(Ready 条件なし)" else ($c.status + " " + ($c.reason // "")) end)] | @tsv'

個別の証明書は cmctl status certificate で、関連する CertificateRequest、Secret、Issuer の状態とイベントをまとめて確認できます。

cmctl status certificate <certificate-name> -n <namespace>

controller のログでは、更新後に Issuer の解決に失敗していないかを確認します。Deployment 名は導入方法によって異なるため、kubectl get deploy -n <namespace> で確認してから指定してください。

kubectl logs -n <issuer-namespace> deploy/<issuer-deployment> --since=1h
kubectl logs -n <cert-manager-namespace> deploy/<cert-manager-deployment> --since=1h

最後に、アプリケーション側で新しい証明書が使われていることを TLS 接続で確認します。発行元と有効期限が想定どおりかを確認してください。

openssl s_client -connect <host>:443 -servername <host> </dev/null 2>/dev/null | openssl x509 -noout -issuer -dates

更新直後に問題がなくても、kind の誤りは次回更新のタイミングで表面化します。棚卸しの手順 8 で確認した renewalTime の近い証明書から、更新後の初回 renewal が成功したかを追跡することを推奨します。継続的な監視には、cert-manager の Prometheus メトリクスの活用も検討できます。

すぐに更新できない場合の暫定対策

AWS は、すぐに更新できない場合の回避策として、証明書の承認ポリシーと RBAC ルールを Issuer の名前と kind の両方で絞ることを挙げています。具体的には次の点を確認します。

  • approver-policy の selector.issuerRef で name、kind、group を完全一致で指定し、kind の省略や *Issuer のようなワイルドカードを避けます。
  • approve 権限の resourceNames は、名前空間スコープ Issuer なら awspcaissuers.awspca.cert-manager.io/<namespace>.<name>、クラスタースコープ Issuer なら awspcaclusterissuers.awspca.cert-manager.io/<name> の形式で個別に指定し、/* による一括許可を必要最小限にします。
  • 下位 CA 証明書を発行する必要がない要求には、approver-policy の allowed で isCA: false(または未指定)とし、CA 証明書の要求を承認しないようにします。

参考: cert-manager Documentation(approver-policy API Reference)
“An omitted field matches all kinds.”
(kind を省略すると、すべての kind に一致します。)
https://cert-manager.io/docs/policy/approval/approver-policy/api-reference/

名前、kind、group を限定した CertificateRequestPolicy の例は次のとおりです。approver-policy の allowed は、省略した項目を「許可しない」と扱うため、実際の要求に含まれる DNS 名や用途に合わせて調整が必要です(approver-policy の公式ドキュメント)。

apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
  name: team-a-awspca
spec:
  allowed:
    isCA: false
    dnsNames:
      values:
      - "*.team-a.example.com"
    usages:
    - "digital signature"
    - "key encipherment"
    - "server auth"
  selector:
    issuerRef:
      name: "team-a-issuer"
      kind: "AWSPCAIssuer"
      group: "awspca.cert-manager.io"
    namespace:
      matchNames:
      - "team-a"

このポリシーは作成するだけでは評価されません。approver-policy は、selector に一致し、かつ要求の作成主体が RBAC でポリシーの use 権限を持つ場合にだけ、そのポリシーで要求を評価します。前提として、cert-manager 本体の自動承認を無効化し、approver-policy が aws-privateca-issuer の signer を承認対象にするよう設定されている必要があります。ポリシーをバインドする例は次のとおりです。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cert-manager-policy:team-a-awspca
rules:
- apiGroups: ["policy.cert-manager.io"]
  resources: ["certificaterequestpolicies"]
  verbs: ["use"]
  resourceNames: ["team-a-awspca"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cert-manager-policy:team-a-awspca
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cert-manager-policy:team-a-awspca
subjects:
- kind: ServiceAccount
  name: <cert-manager-serviceaccount>
  namespace: <cert-manager-namespace>

Certificate から生成される CertificateRequest の作成主体は、利用者ではなく cert-manager コントローラーの ServiceAccount です。そのため、Certificate 経由の要求を対象にする場合は cert-manager の ServiceAccount をバインドします。この場合、バインドだけでは namespace ごとの利用者を区別できないため、例のように selector の namespace や issuerRef で対象を絞ることが重要です。CertificateRequest を利用者が直接作成する運用では、その利用者や ServiceAccount をバインドします。

ただし、修正前の実装は、kind が AWSPCAIssuer の要求でも、対象 namespace に同名の AWSPCAIssuer が存在しない場合は同名の AWSPCAClusterIssuer へフォールバックします。問題は名前が同じこと自体ではなく、名前空間スコープ Issuer が見つからないときにクラスタースコープ Issuer で解決されてしまう処理です。そのため、ポリシーで kind を限定するだけでは防げない経路が残ります。承認対象とする AWSPCAIssuer が各 namespace に実在するかを確認し、実在しない名前への要求が意図しない AWSPCAClusterIssuer に解決され得ないかを、AWSPCAClusterIssuer の一覧と照合してください(修正コミットの差分に基づく編集上の推論)。棚卸しの手順 4、5 で PENDING_RISK と判定された設定が、この経路に該当します。いずれの暫定対策も修正版への更新を代替するものではありません。

標準の Kubernetes RBAC で制御できるのは、誰が Certificate や CertificateRequest を作成できるか、誰が承認できるかまでです。要求の issuerRef にどの name や kind を書けるかといった内容の検査は、cert-manager の承認の仕組み(approver-policy など)の役割です。両者を組み合わせて、要求できる主体と承認される内容の両方を絞ってください。

まとめ

CVE-2026-119115 は、aws-privateca-issuer が issuerRef.kind を無視して Issuer を解決していたことによる認可不備です。修正版への更新は必要ですが、同じ修正が kind の厳密な検証を導入するため、更新前の設定確認と修正が対応の中心になります。

  • 影響は aws-privateca-issuer v1.10.1 未満と EKS add-on v1.10.1-eksbuild.1 未満です。
  • 認証済み主体が承認外のクラスタースコープ Issuer を使える可能性があります。
  • 下位 CA 証明書の発行可否は Issuer と CA の構成に依存します。
  • 修正版では kind の誤りや省略が Failed、種類の不一致が Pending になります。
  • Ingress は issuer-kind と issuer-group の注釈を明示する必要があります。
  • CertificateRequest は編集せず、Certificate や Ingress などの設定元を修正します。
  • 更新後は次回 renewal まで追跡し、自動更新の失敗を早期に検出します。

以上、最後までお読みいただきありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

関西を拠点に活動する、現役インフラエンジニア。経験20年超。

大手通信キャリアにて、中〜大規模インフラ(ネットワーク・サーバ・クラウド・セキュリティ)の設計・構築およびプロジェクトマネジメントに従事。現場で直面した技術課題への対処や、最新の脆弱性情報への実務対応を、一次情報として発信しています。

保有資格
CCIE Lifetime Emeritus(取得から20年以上)/ VCAP-DCA / Azure Solutions Architect Expert

▶ 運営者プロフィール(詳細)

目次