安全

このセクションには、CloudNativePG のセキュリティに関する情報が含まれており、コード、コンテナー、およびクラスターの 3 つの異なるレイヤーで分析されます。

警告

このページに含まれる情報は、Kubernetes クラスターでの通常の InfoSec 業務の実行を免除するものであってはなりません。 Overview of Cloud Native Security についてよく理解してください。

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

EDB が CloudNativePG のセキュリティで採用したアプローチの理解と背景を理解するためのブログ記事。

コード

CloudNativePG のソース コードは、 セキュリティの問題 を含む静的分析の目的で 体系的にスキャン され、CI/CD パイプラインで直接

GolangCI-Lint と呼ばれる Go 用の一般的なオープンソース

リンターを使用します。 GolangCI-Lint は、同じソース コードで複数の linter を実行できます。

これらの 1 つは Golang Security Checker 、または単に gosec です。これは、ハードコードされた資格情報などのコードに隠されている既知の脆弱性、脅威、および弱点の発見を目的とした一連のルールに対してソースの抽象構文ツリーをスキャンするリンターです。 、整数オーバーフロー、 SQLインジェクションなどがあります。

重要

CI/CD パイプラインの静的コード分析フェーズでの失敗は、CloudNativePG の配信全体のブロッカーです。つまり、各コミットは GolangCI-Lint によって定義されたすべてのリンターに対して検証されます。

容器

CloudNativePG の一部であるすべてのコンテナー イメージは、すべてのコミットに続いて CI/CD パイプラインを介して自動的に構築されます。このようなイメージには、演算子だけでなくオペランドも含まれます。具体的には、サポートされているすべての PostgreSQL バージョンです。パイプライン内で、画像は次の方法でスキャンされます。

  • Dockle : コンテナのビルド プロセスに関するベスト プラクティス

重要

すべてのオペランド イメージは、ベース イメージとパッケージ レベルでのセキュリティ更新の場合にパイプラインによって 1 日に 1 回自動的に再構築され、EDB が配布するコンテナー イメージに **パッチ レベルの更新**を提供します。

コンテナー レベルのセキュリティでは、次のガイドラインとフレームワークが考慮されています。

EDB が CloudNativePG のコンテナー レベルでセキュリティに対して採用したアプローチの詳細については、ブログ記事を参照してください。

集まる

クラスター レベルのセキュリティでは、コントロール プレーンとノードの両方を形成するすべての Kubernetes コンポーネントと、クラスターで実行されるアプリケーション (PostgreSQL を含む) が考慮されます。

役割ベースのアクセス制御 (RBAC)

オペレーターは、cnpg-manager という専用のサービス アカウントを使用して Kubernetes API サーバーと対話します。 Kubernetes では、これはデフォルトで cnpg-system 名前空間にインストールされ、このサービス アカウントとオペレーターに付与されるルール/リソース/動詞のセットを定義する cnpg-manager クラスター ロールとの間のクラスター ロール バインディングを使用します。

重要

上記のアクセス許可は、オペレーターのサービス アカウントが Kubernetes API サーバーと対話するために排他的に予約されています。 Cluster 、Pooler 、Backup 、および ScheduledBackup リソースのみと対話するオペレーターのユーザーは、それらに直接アクセスできません。

以下に、いくつかの例と、最も重要なこととして、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 を参照してください。

nodes : オペレーターは Affinity と AntiAffinity のラベルを取得する必要があるため、特にノードが異なるアベイラビリティーゾーンにある場合に、レプリカが同じノードに配置されるのを防ぐためにポッドをスケジュールできるノードを決定できます。この権限は、ノードがスケジュールされているかどうかを判断するためにも使用され、まったく作成できない Pod の作成を回避します。

オペレーターが必要とするすべての権限を確認するには、kubectl describe clusterrole cnpg-manager を実行します。

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

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

重要

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

透過性のために、サービス アカウントに関連付けられたアクセス許可は

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 : インスタンス マネージャーは、update および patch に対して、独自の Cluster リソースのステータスのみを必要とします。

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

backups/status : インスタンス マネージャーは、名前空間内の Backup リソースのステータスを update および patch に要求します。

ポッド セキュリティ ポリシー

ポッドがクラスターで実行するために満たす必要があるセキュリティ ルールと仕様を定義する Kubernetes の方法です。 InfoSec の理由から、すべての Kubernetes プラットフォームはそれらを実装する必要があります。

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

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

オペレータは、必要なセキュリティ コンテキストを明示的に設定します。

AppArmor を使用して Pod アクセスを制限する

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

警告

この種のアノテーションを使用すると、クラスターが機能しなくなる可能性があります。この場合、注釈は Cluster から安全に削除できます。

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

これが状況ではなく、Cluster の作成時に注釈が追加された場合、ポッドは作成されません。一方、Cluster が作成された後に注釈を追加すると、クラスター内のポッドを開始できなくなり、次のようなエラーが発生します。

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

このような場合は、Kubernetes 管理者に問い合わせて、適切な AppArmor プロファイルを使用するよう依頼してください。

ネットワーク ポリシー

Cluster リソースによって作成されたポッドは、Kubernetes

ネットワーク ポリシー によって制御できます。

IP および TCP レベルでのインバウンドおよびアウトバウンド ネットワーク アクセスを有効/無効にします。

重要

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

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

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

公開ポート

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

システム | システム |ポート番号 |公開 |名前 |証明書 |認証: ————— | :———— | :——————————– | :——————————– | :———— | :————– 演算子 | 9443 | Webhook サーバー | webhook-server | TLS |はいオペレーター | 8080 |メトリック | metrics | TLS なし |インスタンス マネージャーなし | 9187 |メトリック | metrics | TLS なし |インスタンス マネージャーなし | 8000 |ステータス | status | TLS なし |オペランドなし | 5432 | PostgreSQL インスタンス | postgresql |オプションの TLS |はい

PostgreSQL

CloudNativePG の現在の実装では、postgres スーパーユーザーとデータベース所有者のパスワードと .pgpass ファイルが自動的に作成されます。

パスワードの暗号化に関する限り、CloudNativePG は PostgreSQL のデフォルトの動作に従います。

重要

ユーザー名/パスワード認証 を参照してください

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

enableSuperuserAccess を false に設定することで、シークレットによる postgres ユーザー パスワードの管理を無効にすることができます。

注釈

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

詳細については、 秘密 を参照してください。

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

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

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

オペレーターによる pg_hba.conf の管理方法の詳細については、ドキュメントの PostgreSQL の設定 を参照してください。

重要

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