Security

CloudNativePGは、スタックのすべてのレイヤーにわたって「最小特権」の原則に従って、デフォルトで安全になるように設計されています。このドキュメントでは、セキュリティガバナンス、サプライチェーンの完全性、およびコード、コンテナ、クラスターの3つの異なるレイヤーで分析された技術的制御の概要を説明します。

警告

このページに含まれる情報は、Kubernetesクラスターで通常のInfoSec業務を実行することから免責されてはなりません。

Overview of Cloud Native Security についてよく理解してください

Kubernetesドキュメントのページ。

The 4C’s Security Model in Kubernetes を参照してください。

ブログ記事


ガバナンスと信頼

脆弱性報告

重要 GitHubの公開問題を介してセキュリティ脆弱性を報告しないでください。

CloudNativePGは、調整された開示モデルに従います。脆弱性を非公開で報告する方法については、 Security Policy on GitHub を参照してください。

リリースの完全性とサプライチェーン

CloudNativePGは OpenSSF Software Producer Security (OSPS) Baseline に従います。 Kubernetesマニフェストやコンテナイメージを含むすべての公式リリースアセットは、暗号的に署名され検証可能です。

インストール中にこれらのアセットを検証するクイックスタート手順については、 Installation Guide を参照してください。 画像署名 および 証明書 の詳細情報

以下で見つけることができます。


コード

CloudNativePGのソースコードは、 CI / CDパイプラインに直接統合されているGoの人気のオープンソースリンター GolangCI-Lint を使用して、セキュリティ脆弱性のチェックを含む体系的な静的分析を受けます。 GolangCI-Lintは、同じソースコードで複数のリンターを実行できます。

次のツールは、セキュリティ問題を特定するために使用されます。

  • `Golang Security Checker <https://github.com/securego/gosec>`_ ``gosec`` ) ハードコードされた資格情報、整数オーバーフロー、 SQLなどの既知の脆弱性、脅威、弱点を検出するように設計された一連のルールに対してソースコードの抽象構文ツリーをスキャンするリンター注射。 GolangCI-Lintは、スイートの一部としてgosec を実行します。

  • `govulncheck <https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck>`_ : このツールはCI / CDパイプラインで実行され、Goコードまたはコンパイラーに影響を与える既知の脆弱性を報告します。既知の脆弱性を含むGoコンパイラーのバージョンでオペレーターがビルドされている場合、 govulncheck はそれを検出します。

  • `CodeQL <https://codeql.github.com/>`_ : GitHubによって提供されるこのツールは、セキュリティ問題をスキャンし、検出された脆弱性を含むプルリクエストをブロックします。 CodeQLは、PythonやBashなどのリポジトリ内の他の言語を除き、Goコードのみをレビューするように構成されています。

  • `Snyk <https://snyk.io/>`_ : スケジュールされたジョブで毎晩コードスキャンを実行し、コードのセキュリティとライセンスの問題に関連する新しい結果を強調する週次レポートを生成します。

CloudNativePGリポジトリには、 Security section で有効になっている_“Private vulnerability Reporting”_オプションがあります。この機能を使用すると、ユーザーは一般に公開される前に、注意深い取り扱いが必要なセキュリティ問題を安全に報告できます。セキュリティバグを発見した場合は、この媒体を使用して報告してください。

注釈

CI / CDパイプラインの静的コード分析フェーズの障害は、CloudNativePGの配信プロセス全体をブロックします。すべてのコミットは、GolangCI-Lintで定義されたすべてのリンターを渡す必要があります。

コンテナ

CloudNativePGのすべてのコンテナイメージは、コミットのたびにCI / CDパイプラインを介して自動的にビルドされます。これらのイメージには、オペレーターのイメージだけでなく、特にサポートされているすべてのPostgreSQLバージョンのオペランドのイメージも含まれます。

注釈

すべてのオペランドイメージは、パイプラインによって自動的に定期的に再構築され、ベースイメージとパッケージレベルの両方で最新のセキュリティ更新が組み込まれます。これにより、コミュニティに配布されたコンテナイメージが**パッチレベルの更新**を定期的に受信できます。

CI / CDプロセス中に、次のツールを使用してイメージがスキャンされます。

  • `Dockle <https://github.com/goodwithtech/dockle>`_ : コンテナビルドプロセスのベストプラクティスを保証します。

  • `Snyk <https://snyk.io/>`_ : コンテナ内のセキュリティ問題を検出し、GitHubインターフェイスを介して結果を報告します。

画像署名

演算子と operandimages は、 sigstore の署名ツール cosign を使用して暗号的に署名されます。このプロセスはGitHub Actionsを介して自動化され、 short-lived tokens issued through OpenID Connect を活用します。

トークン発行者はhttps://token.actions.githubusercontent.com で、署名IDは cloudnative-pg リポジトリで実行されるGitHubワークフローに対応します。このワークフローでは、 cosign-installer action

署名プロセスを合理化します。

オペレーターイメージの信頼性を確認するには、イメージダイジェストで次のcosign コマンドを使用します。

cosign verify ghcr.io/cloudnative-pg/cloudnative-pg@sha256:<DIGEST> \
  --certificate-identity-regexp="^https://github.com/cloudnative-pg/cloudnative-pg/.github/workflows/release-publish.yml@refs/tags/v" \
  --certificate-oidc-issuer="https://token.actions.githubusercontent.com"

証明書

コンテナイメージには、透明性とトレーサビリティのための次の証明書が含まれています。

アーティファクトが、信頼できる分離されたGitHub Actionsランナーでプロジェクトのソースから直接ビルドされたこと。

次のコマンドを使用して、特定のイメージとプラットフォームのSBOMを取得できます。

docker buildx imagetools inspect <IMAGE> \
  --format {{ json (index .SBOM "<PLATFORM>").SPDX }}

このコマンドは、JSON形式でSBOMを出力し、ソフトウェアコンポーネントとビルドの依存関係の詳細なビューを提供します。

ビルドレベルの来歴には、次を使用します。

docker buildx imagetools inspect <IMAGE> \
  --format {{ json (index .Provenance "<PLATFORM>").SLSA }}

SLSAの出所の検証

slsa-verifier を使用してSLSAレベル3の来歴を検証できます。

コンテナイメージを検証するには、そのダイジェスト参照を渡します。

slsa-verifier verify-image \
  ghcr.io/cloudnative-pg/cloudnative-pg@sha256:<DIGEST> \
  --source-uri github.com/cloudnative-pg/cloudnative-pg

コンテナセキュリティのガイドラインとフレームワーク

コンテナレベルのセキュリティを確保するために、次のガイドラインとフレームワークが検討されています。

  • `Container Image Creation and Deployment Guide <https://dl.dod.cyber.mil/wp-content/uploads/devsecops/pdf/DevSecOps_Enterprise_Container_Image_Creation_and_Deployment_Guide_2.6-Public-Release.pdf>`_ : 米国国防総省DoDの防衛情報システム局DISAによって開発されました。

  • **

CIS Benchmark for Docker :**

インターネットセキュリティセンターCISによって開発されました。

注釈

CloudNativePGのコンテナレベルのセキュリティに関してEDBが採用したアプローチの詳細については、ブログ記事

Security and Containers in CloudNativePG を参照してください。

クラスター

クラスターレベルのセキュリティでは、コントロールプレーンとノードの両方を形成するすべてのKubernetesコンポーネント、およびクラスターで実行されるアプリケーションPostgreSQLを含むが考慮されます。最初に、このセクションの残りの部分を構成する信頼モデルとセキュリティ境界を定義します。

信頼モデルとセキュリティ境界

CloudNativePGは、セキュリティポリシーを適用するためのオペレーターとKubernetesプラットフォーム間の明確な責任の分離に従います。以下のサブセクションでは、PostgreSQLポッドに影響を与えると信頼されている人、適用境界が実際にある場所、オペレーターが管理するリソースを制限する方法、およびこれらすべてへのアクセスがRBACによって制御される方法について説明します。

信頼できるクラスターリソースライター

Cluster カスタムリソースの作成または更新権限を持つユーザーは、オペレーターが管理するPostgreSQLポッドの完全な仕様を定義すると信頼されます。これには、spec.securityContext 、spec.podSecurityContext 、spec.serviceAccountName などのセキュリティ重要フィールドが含まれます。オペレーターは、指示に従ってこれらの設定を適用します。クラスターライタがそれらをオーバーライドしない場合、オペレーターは強化されたデフォルトのポッドとコンテナセキュリティコンテキストを適用します ポッドとコンテナのセキュリティコンテキスト を参照してください。

これは、すべてのKubernetesオペレーターの動作と一貫しています。オペレーターは、高レベルのインテントを低レベルのKubernetesリソースに変換する特権エージェントとして機能します。クラスターリソースへの書き込みアクセスを誰かに付与することは、生成されるポッド、サービス、PVC、およびその他の管理対象リソースに対する制御を付与することと同じです。

同じ原則が CNPG-I plugins に適用されます。プラグインはPodのライフサイクルにフックし、Podが作成される前にPod仕様のフィールドを変更できます。したがって、プラグインのインストールは、クラスターリソースへの書き込みアクセスを付与することと同様に、クラスター管理者によって行われる明示的な信頼の決定です。

同じ権限がデータベース自分自身にも拡張されます。オペレーターはスーパーユーザーとしてPostgreSQLをリコンサイルするため、クラスターライタは、次のような文書化された目的のフィールドを介して、結果のクラスターに対してスーパーユーザーレベルの影響力を取得します。

spec.managed.roles superuser: true を設定するか、既存のロールのメンバーシップを付与でき、 COPY ... FROM PROGRAM などのPostgreSQL機能を使用してオペランドポッド内でコマンドを実行できます。

  • カスタムPostgreSQL構成

これは意図された信頼モデルであり、特権のエスカレーションではありません。

オペランドポッドで実行されているコードは、マウントされたServiceAccount の下でも実行され、独自のクラスターに関連付けられたシークレットを読み取ることができます インスタンスマネージャーによるAPIサーバーへの呼び出し を参照してください

および シークレット )。したがって、クラスターライタは、 名前空間の分離 によってクラスター自分自身の名前空間に制限されたこれらのシークレットを読み取ることができます。

注釈

これらの信頼境界は、プロジェクトの self security assessment でもカバーされています。

Kubernetes Admission Control

オペレーターは、標準のKubernetes APIを介してポッドを作成します。つまり、すべてのポッドがクラスターに構成されている完全なアドミッション制御チェーンを通過します。これには

Pod Security Admission が含まれます

PSA、 Pod Security Standards を適用するビルトインKubernetesメカニズム

名前空間レベル、および使用中のサードパーティポリシーエンジンで。名前空間がPSA restricted またはbaseline プロファイルを適用する場合、Kubernetes APIサーバーは、オペレーターが作成したポッドを含む、ポリシーに違反するポッドを拒否します。

上記の信頼できるクラスターライターは任意のポッドフィールドを設定できるため、このアドミッション制御チェーンオペレーターではなく、環境にポッドセキュリティポリシーを適用する境界となります。

名前空間の分離

オペレーターは、すべての管理対象リソースを親クラスターの名前空間に制限します。インスタンスポッドは常にクラスターと同じ名前空間に作成され、他の関係から推測されるのではなく明示的かつ決定論的に設定されます。 Kubernetesの所有者参照は単一の名前空間に制限されているため、オペレーターは他の名前空間にリソースの所有権を確立することもできません。

カスタムリソースの#### RBAC

CloudNativePGカスタムリソースへのアクセスは、標準のKubernetes RBACによって管理されます。クラスターリソースへの書き込みアクセスは、結果のポッドの制御を意味するため、 cnpg.io/podPatch ユーザー指定パッチを管理対象ポッドに適用する cnpg.io/validation 、cnpg.io/reconciliationLoop のようなアノテーションは、クラスターリソース自分自身と同じRBACルールの対象となります。

特に、 cnpg.io/validation をdisabled に設定すると、 cnpg.io/podPatch で実行される構文と適用性チェックを含む、そのクラスターのオペレーター独自の検証用アドミッションWebhookがバイパスされます。したがって、CloudNativePGのWebhook検証は勧告です。クラスターを書き込むことができるアクターと同じアクターがオフにできるため、セキュリティ境界ではありません。 Kubernetesアドミッションコントロールは、このアノテーションに関係なく、結果のポッドに適用されます。

同じ理由がDatabaseRole リソースに適用されます。その仕様では、superuser: true と、 postgres ロール自分自身を含むinRoles を介した既存のロールのメンバーシップが許可されています。したがって、名前空間内のDatabaseRole オブジェクトへの書き込みアクセスは、その名前空間のPostgreSQLクラスターへのスーパーユーザーアクセスと同等であり、 Cluster リソースへの書き込みアクセスと同じ注意が必要です。

これらのリソースへの書き込みアクセスを高特権付与として扱います。マルチテナント展開の場合、テナントを別の名前空間に分離し、Kubernetes RBACで名前空間ごとにスコープを設定し、 名前空間の分離 に依存して影響を制限します。

ここで説明するRBACは、CloudNativePG独自のカスタムリソースへのアクセスを制御します。次のセクションでは、補完的な側、つまり、オペレーター自分自身が依存して、お客様に代わってKubernetesリソースを管理するRBACについて説明します。

ロールベースのアクセス制御RBAC

このセクションでは、上記の RBAC on Custom Resources で説明したカスタムリソースへのユーザーアクセスとは対照的に、オペレーターの_own_ RBAC に代わってKubernetesリソースを管理するために使用するサービスアカウントとロールについて説明します。

オペレーターは、cnpg-manager という名前の専用サービスアカウントを使用してKubernetes APIサーバーと対話します。このサービスアカウントは、通常、オペレーター名前空間、一般的にcnpg-system にインストールされます。ただし、名前空間は、展開方法によって異なる場合があります以下のサブセクションを参照してください。

同じ名前空間に、cnpg-manager サービスアカウントとロールの間にバインディングがあります。このロールの具体的な名前とタイプ Role またはClusterRole も、展開方法によって異なります。このロールは、オペレーターが正常に機能するために必要な権限を定義します。これらのロールの詳細については、展開方法に応じて、 kubectl describe clusterrole またはkubectl describe role コマンドを使用できます。

注釈

上記の権限は、Kubernetes APIサーバーと対話するためにオペレーターのサービスアカウント専用に予約されています。これらは、 Cluster 、Pooler 、Backup 、ScheduledBackup 、Database 、Publication 、Subscription 、ImageCatalog 、および`ClusterImageCatalog` リソースとのみ対話するオペレーターのユーザーは直接アクセスできません。

以下に、いくつかの例と、最も重要な理由を提供します。CloudNativePGが標準のKubernetes名前空間または非名前空間リソースの完全または部分的な管理を必要とする理由。

configmaps

オペレーターは、Prometheusエクスポーターモニタリングメトリックのデフォルトの構成マップを作成および管理する必要があります。

deployments

オペレーターは、標準のKubernetes Deployment リソースを使用してPgBouncer接続プーラーを管理する必要があります。

jobs

オペレーターは、ジョブを処理して、さまざまなCluster のフェーズを管理する必要があります。

persistentvolumeclaims

PGDATA が存在するボリュームは、PostgreSQL Cluster リソースの中心的な要素です。オペレーターは、選択したストレージクラスと対話して、定義されたスケジューリングポリシーに基づいて、要求されたボリュームを動的にプロビジョニングする必要があります。

pods

オペレーターは、Cluster のインスタンスを管理する必要があります。

secrets

Cluster オブジェクトに証明書とパスワードを提供しない限り、オペレーターは、ランダムに生成されたパスワードとTLS証明書をセルフプロビジョニングし、シークレットに保存することにより、「構成より規約」パラダイムを採用します。

serviceaccounts

オペレーターは、インスタンスマネージャーPostgreSQLサーバーを制御するコンテナの_PID 1_プロセスがKubernetes APIサーバーと安全に通信してアクションを調整し、Cluster の信頼できるステータスを継続的に提供できるサービスアカウントを作成する必要があります。

services

オペレーターは、アプリケーションからPostgreSQLクラスターまたは接続プーラーへのネットワークアクセスを制御し、自動化された方法でフェールオーバー/スイッチオーバー操作を適切に管理する必要がありますたとえば、サービスの正しいエンドポイントを適切なプライマリに割り当てるPostgreSQLインスタンス)。

validatingwebhookconfigurations およびmutatingwebhookconfigurations

オペレーターは、自己署名Webhook CAを両方のWebhook構成に注入します。これらは、管理するすべてのリソースを検証および変更するために必要です。詳細については、

Kubernetes documentation を参照してください。

volumesnapshots

オペレーターは、PostgreSQLサーバーのバックアップを取得するために、VolumeSnapshots オブジェクトを生成する必要があります。 VolumeSnapshotは、復元プロセスを開始する前に検証するために読み取られます。

nodes

オペレーターは、アフィニティとアンチアフィニティのラベルを取得して、ポッドをスケジュールできるノードを決定できるようにする必要があります。これは、たとえば、レプリカが同じノードでスケジュールされるのを防ぐ場合に役立ちます。ノードが異なるアベイラビリティーゾーンにある場合に特に重要です。この権限は、ノードがスケジュールされているかどうかを判断し、スケジュールされていないノードでのポッドの作成を防止、またはプライマリがスケジュールされていないノードに存在する場合にスイッチオーバーをトリガーするためにも使用されます。

デプロイメントとClusterRole リソース

前述のように、各展開方法には、サービスアカウントの名前空間の場所、ロールバインディング、および各ロールの名前とタイプが異なる場合があります。

Kubernetesマニフェスト経由

Kubernetesマニフェストを使用してCloudNativePGをインストールする場合、権限はデフォルトでClusterRoleBinding に設定されます。次を実行して、オペレーターに必要な権限を検査できます。

kubectl describe clusterrole cnpg-manager

OLM経由

セキュリティの観点から、Operator Lifecycle ManagerOLMは、より柔軟な展開方法を提供します。すべての名前空間または特定の名前空間を監視するようにオペレーターを構成できるため、より詳細な権限管理が可能になります。

注釈

OLMでは、オペレーターを独自の名前空間に展開し、CloudNativePGクラスターに使用される特定の名前空間を監視するように構成できます。この設定は、権限を含め、より効果的にアクセスを制限するのに役立ちます。

クラスターロールのアクセス許可が必要なのはなぜですか?

現在、オペレーターがnodes およびClusterImageCatalog オブジェクトを読み取るには、ClusterRole 権限が必要です。他のすべての権限は、名前空間スコープつまりRole またはクラスター全体つまりClusterRole にすることができます。

これらの権限でも、誰かがServiceAccount へのアクセスを取得した場合、リソースの表示に制限されているget 、list 、およびwatch 権限のみがあります。ただし、無許可のユーザーがServiceAccount へのアクセスを取得した場合、それはより重大なセキュリティ問題を示しています。

したがって、ユーザーがオペレーターのServiceAccount および昇格した権限で他のServiceAccount にアクセスしないようにすることが重要です。

インスタンスマネージャーによるAPIサーバーへの呼び出し

オペランドコンテナのエントリポイントであるインスタンスマネージャーは、Kubernetes APIサーバーへのいくつかの呼び出しを行って、一部のリソースのステータスが正しく更新されることを確認し、そのPostgresクラスターに関連付けられている構成マップとシークレットにアクセスする必要があります。 。このような呼び出しは、同じPostgreSQL Cluster リソース名を共有するオペレーターによって作成された専用のServiceAccount を介して実行されます。

注釈

このオペランドは、APIサーバーを介してリソースの特定の限定されたサブセットにのみアクセスできます。サービスアカウントは recommended way to access the API server from within a Pod です。

共有サービスアカウントを使用する

デフォルトでは、CloudNativePGはクラスターごとに専用のServiceAccount を作成し、クラスター自分自身にちなんで名前を付けます。ただし、IAMロールAWS IRSA、GCP Workload Identity、Azure Workload Identityなどを使用するクラウド環境では、独自のServiceAccount を作成する各クラスターは、新しいクラスターごとに個別のIAM構成を必要とし、複数のクラスターを管理する際のスケーリングが困難になります。

CloudNativePGでは、クラスター仕様でserviceAccountName フィールドを指定することにより、複数のクラスターが単一のServiceAccount を共有できます。これにより、そのServiceAccount を使用するすべてのクラスターで機能するワンタイムIAM構成が有効になります。

重要 共有ServiceAccount を使用する場合、ServiceAccount を自分自身で作成および管理する責任があります。オペレーターは、指定されたServiceAccount が存在することを検証しますが、作成または変更しません。

次に、共有ServiceAccount を使用する例を示します。

#  Create the shared ServiceAccount once

apiVersion: v1
kind: ServiceAccount
metadata:
  name: postgres-cloud-sa
  annotations:
    # AWS IRSA annotation
    eks.amazonaws.com/role-arn: arn:aws:iam:us-east-1:123456789012:role/PostgresRole
- --

#  Reference it from multiple clusters

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-prod
spec:
  serviceAccountName: postgres-cloud-sa
  instances: 3
  storage:
    size: 100Gi

注釈

serviceAccountName フィールドは`serviceAccountTemplate` と相互排他的です。オペレーターに`ServiceAccount` を管理させるか、オプションで`serviceAccountTemplate` でカスタマイズするか、serviceAccountName で既存のを参照できますが、両方はできません。

警告

serviceAccountName フィールドは、一度設定されると変更できません。 ServiceAccount を変更する必要がある場合は、クラスターを再作成する必要があります。

注釈

複数のクラスターが`ServiceAccount` を共有する場合、オペレーターはクラスターごとに個別の`Role` および`RoleBinding` を作成します。共有`ServiceAccount` は、それを使用するすべてのクラスターのKubernetes RBAC権限を蓄積します。各`Role` のスコープは特定のクラスターのリソースに狭いため、これは特権エスカレーションを構成しません。

プーラーでの共有サービスアカウントの使用

同じ共有ServiceAccount 機能はPooler リソースでも使用できます。 IAM統合を使用するクラウド環境にPgBouncerプーラーを展開する場合、プーラー仕様のserviceAccountName フィールドを指定して、オペレーターにプーラーごとに1つ作成させる代わりに、既存のServiceAccount を参照できます。

apiVersion: postgresql.cnpg.io/v1
kind: Pooler
metadata:
  name: pooler-prod
spec:
  cluster:
    name: cluster-prod
  serviceAccountName: pgbouncer-cloud-sa
  instances: 3
  pgbouncer:
    poolMode: session

警告

クラスターと同様に、プーラーの`serviceAccountName` フィールドは、一度設定されると変更できません。 ServiceAccount を変更する必要がある場合は、プーラーを再作成する必要があります。

透明性を維持するために、サービスアカウントに関連付けられている権限は roles.go

ファイル。たとえば、 myns 名前空間の汎用mypg クラスターの権限を取得するには、次のコマンドを入力します。

kubectl get role -n myns mypg -o yaml

次に、ロールがサービスアカウントにバインドされていることを確認します。

kubectl get rolebinding -n myns mypg -o yaml

注釈

**ロールは特定の名前空間**に制限されていることに注意してください。

以下に、汎用のKubernetesリソースのサービスアカウントに関連付けられた権限の簡単な概要を提供します。

configmaps

インスタンスマネージャーは、カスタムモニタリングクエリなど、同じクラスターに関連する構成マップのみを読み取ることができます

secrets

インスタンスマネージャーは、同じクラスターに関連するシークレットのみを読み取ることができます。ストリーミングレプリケーションユーザー、アプリケーションユーザー、スーパーユーザー、LDAP認証ユーザー、クライアントCA、サーバーCA、サーバー証明書、バックアップ資格情報、カスタムモニタリングクエリー

events

インスタンスマネージャーは、クラスターのイベントを作成し、PostgreSQLインスタンスのライフサイクルの特定の側面についてAPIサーバーに通知できます

ここでは、代わりに、CloudNativePGに固有のリソースに関する同じ概要を提供します。

clusters

インスタンスマネージャーは、独自のCluster リソースに対してのみ、読み取り専用権限、つまりget 、list 、およびwatch が必要です

clusters/status

インスタンスマネージャーは、自分自身のCluster リソースのみのステータスをupdate およびpatch する必要があります

backups

インスタンスマネージャーが名前空間内のBackup リソースを読み取るには、 get およびlist 権限が必要です。さらに、オブジェクトストアに対応するものがないBackup オブジェクトを削除することにより、Kubernetesクラスターをクリーンアップするには、 delete 権限が必要です。通常はリテンションポリシーのため

backups/status

インスタンスマネージャーは、名前空間内のBackup リソースのステータスをupdate およびpatch する必要があります。

ポッドとコンテナのセキュリティコンテキスト

Security Context

ポッドまたはコンテナの特権とアクセス制御設定を定義します。

CloudNativePGは、コンテナの実行に_privileged_モードを必要としません。 PostgreSQLコンテナは、 postgres システムユーザーとして実行されます。 root として実行する必要があるコンポーネントはありません。

同様に、ボリュームアクセスには、_privileged_モードもroot 特権も必要ありません。 Kubernetesプラットフォームおよび/または管理者が適切な権限を割り当てる必要があります。 PostgreSQLコンテナは、読み取り専用のルートファイルシステムつまり書き込み可能なレイヤーなしで実行されます。

オペレーターは、PostgreSQLクラスターのすべてのポッドとコンテナのセキュリティコンテキストの設定を管理します。

Seccomp Profile

PostgreSQLコンテナに使用するサービスは、 Cluster リソースのspec.seccompProfile セクションで構成できます。このセクションが空白のままの場合、コンテナはseccompプロファイルType またはRuntimeDefault 、つまりコンテナランタイムのデフォルトを使用します。

デフォルトのseccompProfile を使用するPostgreSQLコンテナのセキュリティコンテキストは次のようになります。

securityContext:
  allowPrivilegeEscalation: false
  capabilities:
    drop:
    - ALL
  privileged: false
  readOnlyRootFilesystem: true
  runAsNonRoot: true
  seccompProfile:
    type: RuntimeDefault

セキュリティコンテキストのカスタマイズ

CloudNativePGは、それぞれspec.podSecurityContext およびspec.securityContext フィールドを介して、ポッドとコンテナの両方のセキュリティコンテキストのきめの細かい制御を提供します。

注釈

セキュリティコンテキストを変更すると、PostgreSQLクラスターのセキュリティ状態に大きな影響を与える可能性があり、ポッドが正常に起動または動作しない場合があります。変更を行う前に、どのフィールドをオーバーライドするか、演算子のデフォルトとマージする方法を確認し、非運用環境で変更をテストし、必要な最小限の十分に文書化された変更を適用します。

ポッドセキュリティコンテキスト spec.podSecurityContext これにより、すべてのPostgreSQLクラスターポッドに適用されるデフォルトのPodSecurityContext をオーバーライドできます。指定すると、演算子のデフォルト設定とマージされ、明示的に設定されたフィールドの値が優先されます。

例

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  instances: 3
  podSecurityContext:
    runAsUser: 26
    runAsGroup: 26
    fsGroup: 26
    supplementalGroups: [2000, 3000]
    fsGroupChangePolicy: "OnRootMismatch"

コンテナセキュリティコンテキスト spec.securityContext これにより、PostgreSQLクラスターポッド内のすべてのコンテナに適用されるデフォルトのSecurityContext をオーバーライドできます。 podSecurityContext と同様に、演算子のデフォルトとマージします。

例

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  instances: 3
  securityContext:
    allowPrivilegeEscalation: false
    # Note: capabilities are not merged with operator defaults.
    # If specified, they fully replace any defaults.
    capabilities:
      drop:
        - ALL
      add:
        - NET_BIND_SERVICE
    readOnlyRootFilesystem: true
    runAsNonRoot: true

注釈

明示的に設定していないフィールドの場合、オペレーターは安全なデフォルトを適用します。これにより、部分的な構成でもセキュリティのベストプラクティスを維持できます。

注釈

これらのフィールドは、 Pod Security Standards を使用する場合に特に役立ちます。

restricted プロファイル、ポッドとコンテナのセキュリティコンテキストの厳密な要件があります。 Kubernetes Admission Control で説明しているように、結果のPodにこのようなプロファイルを適用するのは、オペレーターではなくこのアドミッションチェーンです。

セキュリティコンテキストの制約

Security Context Constraints (SCC) を利用している環境で実行されている場合

オペレーターは、PostgreSQLクラスターポッドのセキュリティコンテキストを明示的に設定せず、ポッドが既に定義されている制限されたセキュリティコンテキストコンストレインを継承することを許可します。

AppArmorを使用してポッドアクセスを制限する

container.apparmor.security.beta.kubernetes.io アノテーションを介して、すべてのCluster ポッド内のpostgres 、initdb 、join 、full-recovery 、およびbootstrap-controller コンテナに AppArmor プロファイルを割り当てることができます。例

kind: Cluster
metadata:
  name: cluster-apparmor
  annotations:
    container.apparmor.security.beta.kubernetes.io/postgres: runtime/default
    container.apparmor.security.beta.kubernetes.io/initdb: runtime/default
    container.apparmor.security.beta.kubernetes.io/join: runtime/default

警告

この種類のアノテーションを使用すると、クラスターが動作を停止する可能性があります。この場合、アノテーションは`Cluster` から安全に削除できます。

AppArmor構成はKubernetesノードレベルである必要があります。つまり、基になるオペレーティングシステムでこのオプションを有効にし、適切に構成する必要があります。

これは状況ではなく、アノテーションがCluster 作成時に追加された場合、ポッドは作成されません。一方、Cluster が作成された後にアノテーションを追加すると、クラスター内のポッドは起動できず、次のようなエラーが発生します。

metadata.annotations[container.apparmor.security.beta.kubernetes.io/postgres]: Forbidden: may not add AppArmor annotations]

このような場合、Kubernetes管理者に連絡し、使用する適切なAppArmorプロファイルを聞いてください。

ネットワークポリシー

Cluster リソースによって作成されたポッドは、Kubernetesによって制御できます network policies

IPおよびTCPレベルでインバウンドおよびアウトバウンドのネットワークアクセスを有効/無効にします。詳細については、 networking document をご覧ください。

注釈

オペレーターは、TCPポート8000で各インスタンスと通信して、PostgreSQLサーバーのステータスに関する情報を取得する必要があります。ネットワークポリシーを追加する場合にこれを念頭に置いて、より詳細な制御のためにCloudNativePGが使用するポートのリストについては、以下の「公開ポート」セクションを参照してください。

ネットワークポリシーは、このドキュメントの範囲外です。 Network policies を参照してください。

詳細については、Kubernetesドキュメントのセクションを参照してください。

公開ポート

CloudNativePGは、以下の表にリストされているように、オペレーター、インスタンスマネージャー、およびオペランドレベルでポートを公開します。

System

Port number

Exposing

Name

TLS

Authentication

operator

9443

webhook server

webhook-server

Yes

Yes

operator

8080

metrics

metrics

No

No

instance manager

9187

metrics

metrics

Optional

No

instance manager

8000

status

status

Yes

Partial (1)

operand

5432

PostgreSQL instance

postgresql

Optional

Yes

(1)ステータス、状態、およびプローブエンドポイントは認証されていません。 オペレーターからインスタンスへの認証 `GHSA-7qwx-x8ff-3px9 <オペレーターからインスタンスへの認証 GHSA-7qwx-x8ff-3px9>` で説明しているように、機密エンドポイントバックアップ、pg_controldata 、部分的なWALアーカイブ、およびインスタンスマネージャーのアップグレードは、オペレーターのクライアント証明書が必要です

以下。

オペレーターからインスタンスへの認証

オペレーターは、起動時にメモリに自己署名ECDSAクライアント証明書を生成し、クラスターの.status.operatorCertificateFingerprint でSHA-256公開キーフィンガープリントを公開します。インスタンスマネージャーは、そのフィンガープリントを固定し、一致する証明書を提示しない機密エンドポイントbackup、pg_controldata 、部分的なWALアーカイブ、およびインスタンスマネージャーのアップグレードへの呼び出しを拒否します。ステータス、状態、およびプローブエンドポイントは認証されないままです。

証明書はディスクに書き込まれることはなく、オペレーターが再起動するたびに再生成されるため、CA検証ではなくフィンガープリントのピンニングから信頼が得られます。

この保護には、ステータスポート がTLSで提供される必要があります というハード要件があります。これは、v1.24以降のデフォルトです。クライアント証明書はTLS接続でのみ提示できるため、ステータスポートがTLSを使用する場合にのみ、オペレーターが保護されたエンドポイントに到達できます。

警告

ステータスポートがTLSで提供されていない場合、インスタンスマネージャーはオペレーターを認証できず、401 Unauthorized で保護されたエンドポイントbackup、pg_controldata 、部分的なWALアーカイブ、およびインスタンスマネージャーのアップグレードへのすべての呼び出しを**永久に**拒否します。これは一時的な状態ではなく、自然に解決されることはありません。インスタンスマネージャーがこの認証を強制するバージョンにアップグレードされると、v1.24より古いオペレーターによって作成されたインスタンスに影響を与える可能性があります。このようなインスタンスは、TLSでポッドが再作成されるようにロールアウトする必要があります。有効なステータスポート。新しく作成されたインスタンスは常にステータスポートでTLSを有効にし、影響を受けません。

PostgreSQL

CloudNativePGの現在の実装は、データベース所有者と、 enableSuperuserAccess をtrue に設定して要求された場合にのみ、 postgres スーパーユーザーのパスワードと.pgpass ファイルを自動的に作成します。

警告

enableSuperuserAccess は、オペレーターのセキュリティバイデフォルト姿勢を向上させるためにデフォルトで`false` に設定され、PostgreSQLへの変更が`Cluster` リソースの`spec` を介して宣言的な方法で実行されるマイクロサービスアプローチを促進しながら、開発者に内部のフルパワーを提供しますデータベース所有者ユーザーを介してデータベースにアクセスします。

パスワードの暗号化に関する限り、CloudNativePGはPostgreSQLのデフォルト動作に従います。PostgreSQL 14以降、password_encryption はデフォルトでscram-sha-256 に設定されますが、以前のバージョンではmd5 に設定されています。

注釈

Password authentication を参照してください。

詳細については、PostgreSQLドキュメントのセクションを参照してください。

注釈

オペレーターは、enableSuperuserAccess オプションのトグルをサポートしています。実行中のクラスターで無効にすると、オペレーターはシークレットの内容を無視し、削除し、オペレーターが以前に生成した場合、postgres ユーザーのパスワードを`NULL` に設定しますパスワード認証を介したリモートアクセスを事実上無効にします。

注釈

PostgreSQL documentation で記載されているように、PostgreSQLでは、一部のロール操作のログに平文のロールパスワードが含まれる場合があります。 CloudNativePGは、 postgres ロギングステートメントロギングとErrorステートメントロギングの両方が、パスワードを使用したCREATE / ALTER ROLE操作で一時的に抑制されるため、パスワードの漏洩を防ぎます。

詳細については、 シークレット を参照してください。

これらのファイルを使用して、データベースへのアプリケーションのアクセスを構成できます。

デフォルトでは、すべてのレプリカは、streaming_replica と呼ばれる特別なユーザーを使用して、現在のプライマリインスタンスに 物理非同期ストリーミングレプリケーション で接続するように自動的に構成されます。ノード間の接続は 暗号化 され、認証は TLSクライアント証明書 を介して行われます。詳細については、 Client TLS/SSL connections ページを参照してください。デフォルトでは、オペレーターはTLS v1.3接続を必要とします。

現在、オペレーターは、管理者がpostgresql 構成のpg_hba セクションの一部としてマニフェストにpg_hba.conf 行を直接追加できます。マニフェストで定義された行は、デフォルトのpg_hba.conf に追加されます。

オペレーターによるpg_hba.conf の管理方法の詳細については、ドキュメントの マウンティングとPostgreSQLの構成 を参照してください。

管理者は、デフォルトでローカルのpostgresユーザーをデータベース内のpostgresユーザーにのみマップするpg_ident.conf ファイルの内容をカスタマイズすることもできます。

オペレーターによるpg_ident.conf の管理方法の詳細については、ドキュメントの マウンティングとPostgreSQLの構成 を参照してください。

注釈

例では、Kubernetesクラスターがプライベートで安全なネットワークで実行されていることを前提としています。

スキーマの解決とsearch_path の強化

データベースに対する特権を持つユーザーは、public などの書き込み可能なスキーマにオブジェクトファンクション、演算子、テーブル、またはタイプを植え付け、データベースまたはロールレベルのsearch_path たとえば ALTER DATABASE ... SET search_path またはALTER ROLE ... SET search_path を変更できます。後でそのデータベースに接続する特権セッションは、テナント制御のsearch_path を継承するため、クエリのいずれかにおける非修飾参照は、目的のオブジェクトではなく植えられたオブジェクトに解決される場合があります。これは、 CWE-426 (Untrusted Search Path) に似た特権エスカレーションベクターであり、よく知られた CVE-2018-1058 と同じクラスの問題です。

これを防ぐために、CloudNativePGは、データベースまたは接続ロールで構成されているsearch_path に関係なく、PostgreSQLへの接続を開くすべての接続でsearch_path をpg_catalog, public, pg_temp の固定値に固定します。

  • pg_catalog が最初に検索されるため、ビルトインオブジェクトは常に別のスキーマに植えられた同じ名前のオブジェクトより優先されます。

  • pg_temp セッションプライベート一時スキーマは、最初に検索されるのではなく最後に検索されるため、リレーションまたはデータ型をシャドウできません。

さらに、PgBouncer統合で使用されるSECURITY DEFINER ルックアップファンクションは、独自の固定されたsearch_path で作成され、モニタリングクエリーは、 バックアップの進行状況のモニタリング で説明しているようにsearch_path が固定されているトランザクション内で実行されます。

注釈

ユーザー作成SQLブートストラップ中の`postInitSQL` /postInitApplicationSQL /postInitTemplateSQL 、および論理インポートのインポート後クエリーは、標準の`"$user", public` 解像度で実行されるため、プレーンのPostgreSQLセッションと同様に動作し続けます。 search_path から独立する必要がある場合、これらのスクリプトのオブジェクト参照をスキーマ修飾します。

ストレージ

CloudNativePGは、保存時の暗号化を基になるストレージクラスに委任します。運用環境でのデータ保護のために、保存時の暗号化をサポートするストレージクラスを選択することを強くお勧めします。