問題: 「Secret を除くすべての K8s 構成を git で管理できます。」
解決策: Secret を SealedSecret に暗号化します。これは、パブリック リポジトリ内であっても安全に保存できます。 SealedSecret を復号化できるのは、ターゲット クラスター内で実行されているコントローラーだけであり、他の誰も (元の作成者であっても) SealedSecret から元の Secret を取得することはできません。
概要
シークレットのテンプレートとしての SealedSecrets
公開鍵/証明書
スコープ
インストール
自作
Macポート
Linux
ソースからのインストール
カスタマイズする
ヘルムチャート
コントローラ
クベシール
アップグレード
使用法
既存のシークレットの管理
既存のシークレットにパッチを適用する
既存のシークレットを更新する
Raw モード (実験的)
封印された秘密を検証する
シークレットローテーション
封印キーのリニューアル
ユーザーシークレットのローテーション
早期の鍵更新
キーの更新に関するよくある誤解
手動キー管理 (上級)
再暗号化(上級)
詳細(上級)
暗号
現像
よくある質問
クラスターにアクセスできなくなった場合でも復号化できますか?
SealedSecrets のバックアップを作成するにはどうすればよいですか?
バックアップ キーを使用してオフラインでシークレットを復号化できますか?
kubeseal ではどのようなフラグが利用できますか?
シールされたシークレットで暗号化された JSON/YAML/TOML/.. ファイルの一部を更新するにはどうすればよいですか?
自分の (事前に生成された) 証明書を持ち込むことはできますか?
コントローラーがkube-system
名前空間内で実行されていない場合に kubeseal を使用するにはどうすればよいですか?
画像を確認するにはどうすればよいですか?
名前空間のサブセットに対して 1 つのコントローラーを使用する方法
コントローラーのシール解除の再試行を構成できますか
コミュニティ
関連プロジェクト
Sealed Secrets は 2 つの部分で構成されています。
クラスター側のコントローラー/オペレーター
クライアント側ユーティリティ: kubeseal
kubeseal
ユーティリティは、非対称暗号を使用して、コントローラーのみが復号化できるシークレットを暗号化します。
これらの暗号化されたシークレットはSealedSecret
リソースにエンコードされており、シークレットを作成するためのレシピとして表示できます。その様子は次のとおりです。
apiVersion: bitnami.com/v1alpha1kind: SealedSecretmetadata: name: mysecret 名前空間: mynamespacespec: encryptedData: foo: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq....
封印が解除されると、これと同等のシークレットが生成されます。
apiVersion: v1kind: Secretmetadata: name: mysecret namespace: mynamespacedata: foo: YmFy # <- Base64 エンコードされた「bar」
この通常の Kubernetes シークレットは数秒後にクラスターに表示され、直接作成したシークレットを使用する場合と同様に使用できます (例: Pod
から参照)。
起動して実行するには、「インストール」セクションに移動してください。
「使用法」セクションでは、 SealedSecret
リソースを作成する方法を詳しく説明します。
前の例では、暗号化されたシークレット アイテム自体にのみ焦点を当てていましたが、 SealedSecret
カスタム リソースとそれが封印を解除するSecret
との関係は、多くの点で (すべてではありませんが) よく知られているDeployment
とPod
の関係に似ています。
特に、 SealedSecret
リソースのアノテーションとラベルは、そこから生成されるSecret
のアノテーションと同じではありません。
この違いを把握するために、 SealedSecret
オブジェクトには、コントローラーが unsealed Secret
に含めるすべてのフィールドをエンコードするtemplate
セクションがあります。
デフォルトの Go Text Template 関数に加えて、Sprig 関数ライブラリも利用できます。
metadata
ブロックはそのままコピーされます (無効にしない限り、 ownerReference
フィールドは更新されます)。
他の秘密フィールドは個別に処理されます。 type
フィールドとimmutable
フィールドがコピーされ、 data
フィールドを使用してSecret
の複雑な値をテンプレート化できます。現在、他のフィールドはすべて無視されます。
apiVersion: bitnami.com/v1alpha1kind: SealedSecretmetadata: name: mysecret namespace: mynamespace 注釈: "kubectl.kubernetes.io/last-applied-configuration": ....spec: encryptedData: .dockerconfigjson: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.... .テンプレート: タイプ: kubernetes.io/dockerconfigjson immutable: true # これは、出力シークレット メタデータに追加されるラベルと注釈の例です: ラベル: "jenkins.io/credentials-type": usernamePassword annotations: "jenkins.io/credentials-description ": Kubernetes からの認証情報
コントローラーはそれを次のようなものに解凍します。
apiVersion: v1kind: Secretmetadata: name: mysecret namespace: mynamespace ラベル: "jenkins.io/credentials-type": usernamePassword 注釈: "jenkins.io/credentials-description": Kubernetes ownerReferences からの認証情報: - apiVersion: bitnami.com/v1alpha1 コントローラー: true 種類: SealedSecret 名: mysecret uid: 5caff6a0-c9ac-11e9-881e-42010aac003etype: kubernetes.io/dockerconfigjsonimmutable: truedata: .dockerconfigjson: ewogICJjcmVk...
ご覧のとおり、生成されたSecret
リソースはSealedSecret
の「依存オブジェクト」であるため、 SealedSecret
オブジェクトが更新または削除されるたびに更新および削除されます。
キー証明書 (公開キー部分) は秘密を封印するために使用され、 kubeseal
が使用される場合はどこでも利用できる必要があります。証明書は機密情報ではありませんが、正しい証明書を使用していることを確認する必要があります。
kubeseal
実行時にコントローラーから証明書を取得します (Kubernetes API サーバーへの安全なアクセスが必要です)。これはインタラクティブな使用には便利ですが、間にファイアウォールがあるプライベート GKE クラスターなど、特別な構成のクラスターをユーザーが使用している場合には脆弱であることが知られています。コントロールプレーンとノード。
別のワークフローは、 kubeseal --fetch-cert >mycert.pem
を使用して証明書をどこか (ローカル ディスクなど) に保存し、 kubeseal --cert mycert.pem
を使用してオフラインで使用することです。証明書は起動時にコントローラーのログにも出力されます。
v0.9.x 以降、証明書は 30 日ごとに自動的に更新されます。あなたとあなたのチームがオフライン証明書を定期的に更新することをお勧めします。これを助けるために、v0.9.2 以降、 kubeseal
URL も受け入れます。信頼できる場所に証明書を発行するように内部自動化を設定できます。
kubeseal --cert https://your.intranet.company.com/sealed-secrets/your-cluster.cert
SEALED_SECRETS_CERT
環境変数も認識します。 (プロのヒント: direnv も参照してください)。
注: 当社は、暗号化を HSM ベースのモジュールまたは KMS などのマネージド クラウド暗号ソリューションにオフロードするキー管理メカニズムの提供に取り組んでいます。
SealedSecrets は、エンド ユーザーの視点からは「書き込み専用」デバイスです。
その考え方は、SealedSecret はターゲット クラスター内で実行されているコントローラーによってのみ復号化でき、他の誰も (元の作成者であっても) SealedSecret から元の Secret を取得できないということです。
ユーザーはターゲット クラスターに直接アクセスできる場合と、そうでない場合があります。より具体的には、ユーザーはコントローラーによって封印が解除されたシークレットにアクセスできる場合とできない場合があります。
k8s で RBAC を設定する方法はたくさんありますが、特権の低いユーザーによる Secret の読み取りを禁止するのが非常に一般的です。また、より高い権限を持つ 1 つ以上の名前空間をユーザーに付与することも一般的です。これにより、シークレットの作成と読み取り (および/またはそれらのシークレットを参照できるデプロイメントの作成) が可能になります。
暗号化されたSealedSecret
リソースは、そこに隠されている秘密について何も知らなくても安全に閲覧できるように設計されています。これは、ユーザーがアクセスできない名前空間向けの SealedSecret を読み取り、シークレットを読み取ることができる名前空間にそのコピーをプッシュすることを許可することはできないことを意味します。
したがって、Sealed-secret は、あたかも各名前空間が独自の独立した暗号化キーを持っているかのように動作するため、名前空間のシークレットを一度封印すると、その秘密を別の名前空間に移動してそこで復号化することはできません。
技術的には、名前空間ごとに独立した秘密キーを使用しませんが、代わりに暗号化プロセス中に名前空間名を含めることで、実質的に同じ結果を達成します。
さらに、名前空間は、RBAC 構成が誰がどのシークレットを参照できるかを決定できる唯一のレベルではありません。実際、ユーザーは特定の名前空間内のfoo
というシークレットにはアクセスできるが、同じ名前空間内の他のシークレットにはアクセスできない可能性があります。したがって、デフォルトでは、ユーザーがSealedSecret
リソースの名前を自由に変更できるようにすることはできません。そうしないと、悪意のあるユーザーが名前を変更するだけで、ユーザーがアクセスできる 1 つのシークレットを上書きするだけで、その名前空間の SealedSecret を復号化できてしまいます。暗号化キーに名前空間を含めるのに使用したのと同じメカニズムを使用して、シークレット名も含めます。
とはいえ、このレベルの保護を気にしないシナリオも数多くあります。たとえば、クラスターにアクセスできるのは管理者のみであるか、 Secret
リソースをまったく読み取ることができないかのどちらかです。シールされたシークレットを他の名前空間に移動するユースケースがあるかもしれません (たとえば、名前空間名が事前にわからないかもしれません)、またはシークレットの名前がわからないかもしれません (たとえば、シークレットのハッシュに基づく一意のサフィックスが含まれている可能性があります)。内容など)。
可能なスコープは次のとおりです。
strict
(デフォルト): シークレットは、まったく同じ名前と名前空間でシールされる必要があります。これらの属性は暗号化されたデータの一部となるため、名前や名前空間を変更すると「復号化エラー」が発生します。
namespace-wide
: 指定された名前空間内でシールされたシークレットの名前を自由に変更できます。
cluster-wide
: シークレットはどの名前空間でも封印を解除でき、任意の名前を付けることができます。
nameとnamespaceの制限とは対照的に、シークレット項目(つまり、 spec.encryptedData.my-key
のような JSON オブジェクト キー) は、封印されたシークレットを復号化する機能を失うことなく、任意に名前を変更できます。
スコープは--scope
フラグで選択されます。
kubeseal --scope クラスター全体のsealed-secret.json
kubeseal
に渡す入力シークレットのアノテーションを介してスコープをリクエストすることもできます。
sealedsecrets.bitnami.com/namespace-wide: "true"
-> namespace-wide
の場合
sealedsecrets.bitnami.com/cluster-wide: "true"
-> cluster-wide
の場合
このような注釈がまったくない場合は、 strict
モードを意味します。両方が設定されている場合は、 cluster-wide
優先されます。
注: 次のリリースでは、これが 1 つの
sealedsecrets.bitnami.com/scope
アノテーションに統合されます。
最新リリースと詳細なインストール手順については、https://github.com/bitnami-labs/sealed-secrets/releases を参照してください。
クラウド プラットフォーム固有の注意事項と手順:
GKE
マニフェストをデプロイすると、 SealedSecret
リソースが作成され、コントローラーがkube-system
名前空間にインストールされ、サービス アカウントと必要な RBAC ロールが作成されます。
しばらくすると、コントローラーが起動し、キー ペアが生成され、操作の準備が整います。そうでない場合は、コントローラーのログを確認してください。
公式のコントローラー マニフェスト インストール メカニズムは単なる YAML ファイルです。
場合によっては、カスタム名前空間の設定や環境変数の設定など、独自のカスタマイズを適用する必要がある場合があります。
kubectl
それをネイティブにサポートしています。kusTOMize を参照してください。
Sealed Secrets ヘルム チャートが正式にサポートされ、この GitHub リポジトリでホストされるようになりました。
Helm リポジトリに sealed-secrets を追加 https://bitnami-labs.github.io/sealed-secrets
注: ヘルム チャートのバージョン管理スキームは、Sealed Secret プロジェクト自体のバージョン管理スキームとは異なります。
元々、ヘルム チャートはコミュニティによって保守されており、最初のバージョンではメジャー バージョン 1 が採用されていましたが、Sealed Secrets プロジェクト自体はまだメジャー 0 のままでした。ヘルム チャート自体のバージョンが必ずしもそのバージョンである必要はないため、これは問題ありません。アプリ自体の。ただし、これは混乱を招くため、現在のバージョン管理ルールは次のとおりです。
SealedSecret
コントローラーのバージョン スキーム: 0.XY
Helm チャートのバージョン スキーム: 1.XY-rZ
したがって、静的 YAML マニフェストやコントローラー イメージ自体には影響を与えずに、ヘルム チャートにのみ適用される修正を含む、ヘルム チャートの複数のリビジョンが存在する可能性があります。
注: ヘルム チャートの Readme には非推奨の通知がまだ含まれていますが、現実を反映していないため、次のリリースで削除される予定です。
注: ヘルム チャートはデフォルトで
sealed-secrets
という名前のコントローラーをインストールしますが、kubeseal
コマンド ライン インターフェイス (CLI) はsealed-secrets-controller
という名前のコントローラーにアクセスしようとします。--controller-name
CLI に明示的に渡すことができます。
kubeseal --controller-name sealed-secrets
あるいは、チャートのインストール時にfullnameOverride
設定して名前をオーバーライドすることもできます。 kubeseal
、デフォルトでコントローラーがkube-system
名前空間内にインストールされていることを前提としていることに注意してください。したがって、予想されるコントローラー名と名前空間を渡さずにkubeseal
CLI を使用したい場合は、次のように Helm Chart をインストールする必要があります。
helm install sealed-secrets -n kube-system --set-string fullnameOverride=sealed-secrets-controller sealed-secrets/sealed-secrets
企業によっては、クラスター全体ではなく、単一の名前空間へのアクセスのみが与えられる場合があります。
遭遇する可能性のある最も制限の厳しい環境の 1 つは次のとおりです。
namespace
、何らかのservice account
で割り当てられました。
クラスターの残りの部分にはアクセスできず、クラスター CRD にもアクセスできません。
名前空間にさらにサービス アカウントやロールを作成することさえできない場合があります。
すべての展開にリソース制限を含める必要があります。
これらの制限があっても、Sealed Secret Helm Chart をインストールすることはできます。前提条件は 1 つだけです。
クラスターには、Sealed Secret CRD がすでにインストールされている必要があります。
管理者が CRD をインストールしたら、CRD がまだ存在していない場合は、次のような YAML 構成ファイルを準備してチャートをインストールできます。
サービスアカウント: 作成: false 名前: {割り当てられたサービスアカウント} rbac: 作成: false クラスターロール: falseリソース: 制限: CPU: 150メートル メモリ: 256Mi
ご了承ください:
サービス アカウントは作成されず、代わりに割り当てられたアカウントが使用されます。
{allocated-service-account}
クラスターに割り当てられたservice account
の名前です。
名前空間にもクラスターにも RBAC ロールは作成されません。
リソース制限を指定する必要があります。
制限は動作するはずのサンプルですが、特定の設定で確認することをお勧めします。
ファイルの準備ができたら、 config.yaml
名前を付けた場合は、次のようにシールされたシークレット Helm チャートをインストールできます。
helm install sealed-secrets -n {allocated-namespace} sealed-secrets/sealed-secrets --skip-crds -f config.yaml
ここで、 {allocated-namespace}
は、クラスター内に割り当てられたnamespace
の名前です。
kubeseal
クライアントは自作でも入手できます。
醸造インストールkubeseal
kubeseal
クライアントは MacPorts でも利用できます。
ポートインストールkubeseal
kubeseal
クライアントは Nixpkgs でも入手できます: (免責事項: bitnami-labs によって保守されていません)
nix-env -iA nixpkgs.kubeseal
kubeseal
クライアントは、以下のコマンドを使用して Linux にインストールできます。
KUBESEAL_VERSION='' # これを、たとえば KUBESEAL_VERSION='0.23.0'curl -OL "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION:?}" に設定します。 /kubeseal-${KUBESEAL_VERSION:?}-linux-amd64.tar.gz"tar -xvzf kubeseal-${KUBESEAL_VERSION:?}-linux-amd64.tar.gz kubeseal sudo install -m 755 kubeseal /usr/local/bin/kubeseal
マシンにcurl
とjq
がインストールされている場合は、この方法でバージョンを動的に取得できます。これは、自動化などで使用される環境に役立ちます。
# Fetch the latest sealed-secrets version using GitHub API KUBESEAL_VERSION=$(curl -s https://api.github.com/repos/bitnami-labs/sealed-secrets/tags | jq -r '.[0].name' | cut -c 2-) # Check if the version was fetched successfully if [ -z "$KUBESEAL_VERSION" ]; then echo "Failed to fetch the latest KUBESEAL_VERSION" exit 1 fi curl -OL "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz" tar -xvzf kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz kubeseal sudo install -m 755 kubeseal /usr/local/bin/kubeseal
ここで、 KUBESEAL_VERSION
は、使用する kubeseal リリースのバージョン タグです。例: v0.18.0
。
最新のクライアント ツールだけが必要な場合は、次のコマンドを使用して$GOPATH/bin
にインストールできます。
github.com/bitnami-labs/sealed-secrets/cmd/kubeseal@main をインストールしてください
main
代わりにリリース タグまたはコミット SHA を指定できます。
go install
コマンドは、 kubeseal
バイナリを$GOPATH/bin
に配置します。
$(go env GOPATH)/bin/kubeseal
クライアント ツールやコントローラーをアップグレードするときに発生する可能性のある重大な変更に関するガイダンスについては、必ずリリース ノートを確認してください。
現在、実稼働環境では Sealed Secrets の最新バージョンのみがサポートされています。
Sealed Secrets コントローラーは、安定した Kubernetes API に依存することで、Kubernetes のさまざまなバージョンとの互換性を保証します。通常、Kubernetes バージョン 1.16 以降は互換性があるとみなされます。ただし、現在推奨されている Kubernetes バージョンは正式にサポートされています。さらに、1.24 以降のバージョンでは、リリースごとに CI プロセスによる徹底的な検証が行われます。
# json/yaml でエンコードされた Secret を何らかの方法で作成します:# (`--dry-run` の使用に注意してください - これは単なるローカル ファイルです!)echo -n bar | kubectl create secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o json >mysecret.json# これは重要な部分です:kubeseal -f mysecret.json -w mysealedsecret.json#この時点で、mysealedsecret.json は Github に安全にアップロードできます。# Twitter に投稿することもできます。# 最終的に:kubectl create -f mysealedsecret.json# 利益!kubectl シークレット mysecret を取得
SealedSecret
とSecret
同じ名前空間と名前を持つ必要があることに注意してください。これは、同じクラスター上の他のユーザーが封印されたシークレットを再利用できないようにする機能です。詳細については、「スコープ」セクションを参照してください。
kubeseal
入力シークレットから名前空間を読み取り、明示的な--namespace
引数を受け入れ、 kubectl
デフォルトの名前空間を (この順序で) 使用します。元のSecret
のラベル、注釈などは保持されますが、 SealedSecret
には自動的には反映されません。
設計上、このスキームはユーザーを認証しません。言い換えれば、誰でも好きなSecret
を含むSealedSecret
を作成できます (名前空間/名前が一致する場合)。目的のSealedSecret
のみがクラスターにアップロードされるかどうかは、既存の構成管理ワークフロー、クラスター RBAC ルールなどによって異なります。既存の Kubernetes からの唯一の変更点は、クラスター外ではSecret
の内容が非表示になることです。
Sealed Secrets コントローラーで既存のSecret
を管理したい場合は、 Secret
にsealedsecrets.bitnami.com/managed: "true"
アノテーションを付けることができます。同じ名前と名前空間を持つSealedSecret
アンシールすると、既存のSecret
が上書きされ、 SealedSecret
Secret
の所有権を取得します (そのため、 SealedSecret
が削除されるとSecret
も削除されます)。
v0.23.0の新機能
Secret
全体を置き換えるのではなく、既存のSecret
の一部のキーを追加または変更するだけのユースケースがいくつかあります。このために、 Secret
にsealedsecrets.bitnami.com/patch: "true"
の注釈を付けることができます。このアノテーションを使用すると、 SealedSecret
に存在しないSecret
内の秘密キー、ラベル、およびアノテーションが削除されず、 SealedSecret
に存在する秘密キー、ラベル、およびアノテーションがSecret
に追加されます (存在する秘密キー、ラベル、およびアノテーション)。 Secret
とSealedSecret
の両方がSealedSecret
によって変更されます)。
このアノテーションは、 SealedSecret
にSecret
の所有権を取得させるものではありません。 patch
とmanaged
アノテーションの両方を追加して、 Secret
の所有権を取得しながらパッチ適用動作を取得できます。
SealedSecret
とSecret
を独立させたい場合、つまりSealedSecret
削除してもSecret
一緒に消えないようにするには、その Secret に注釈sealedsecrets.bitnami.com/skip-set-owner-references: "true"
を付ける必要があります。 sealedsecrets.bitnami.com/skip-set-owner-references: "true"
。 SealedSecret
が更新されたときにシークレットも更新されるように、 sealedsecrets.bitnami.com/managed: "true"
をSecret
に追加することもできます。
他の項目の平文を持たずに既存のシールされたシークレットを追加または更新したい場合は、新しい暗号化されたデータ項目をコピー&ペーストして、既存のシールされたシークレットにマージするだけです。
更新されたアイテムを互換性のある名前と名前空間でシールするように注意する必要があります (上記のスコープに関する注意を参照)。
コピー&ペーストしたくない場合は、 --merge-into
コマンドを使用して既存のシールされたシークレットを更新できます。
エコー -n バー | kubectl シークレット汎用作成 mysecret --dry-run=client --from-file=foo=/dev/stdin -o json | kubeseal > mysealedsecret.jsonecho -n baz | kubectl create secret generic mysecret --dry-run=client --from-file=bar=/dev/stdin -o json | kubeseal --merge-into mysealedsecret.json
kubectl
コマンドを使用して一時的な Secret を作成し、それをkubeseal
にパイプした後に破棄するのは、非常に不親切なユーザー エクスペリエンスになる可能性があります。私たちは CLI エクスペリエンスの全面的な見直しに取り組んでいます。それまでの間、kubeseal が stdout への値の暗号化のみを考慮し、それをSealedSecret
リソース内に配置するのはユーザーの責任である代替モードを提供します (他の k8s リソースと同様)。
また、エディター/IDE 統合の構成要素としても役立ちます。
欠点は、シーリング スコープ、名前空間、名前との一貫性を保つように注意する必要があることです。
スコープを参照
strict
スコープ (デフォルト):
$ echo -n foo | kubeseal --raw --namespace bar --name mysecretAgBChHUWLMx...
namespace-wide
スコープ:
$ echo -n foo | kubeseal --raw --namespace bar --scope namespace-wideAgAbbFNkM54...
SealedSecret
にsealedsecrets.bitnami.com/namespace-wide
アノテーションを含めます。
メタデータ: 注釈: sealedsecrets.bitnami.com/namespace-wide: "true"
cluster-wide
スコープ:
$ echo -n foo | kubeseal --raw --scope クラスター全体の AgAjLKpIYV+...
SealedSecret
にsealedsecrets.bitnami.com/cluster-wide
アノテーションを含めます。
メタデータ: アノテーション: sealedsecrets.bitnami.com/cluster-wide: "true"
既存のシールされたシークレットを検証したい場合、 kubeseal
は--validate
フラグが付いています。
次のシールされたシークレットを含むsealed-secrets.yaml
という名前のファイルを指定します。
apiVersion: bitnami.com/v1alpha1kind: SealedSecretmetadata: name: mysecret 名前空間: mynamespacespec: encryptedData: foo: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq....
シールされたシークレットが適切に作成されたかどうかを検証できます。
$ cat sealed-secrets.yaml | kubeseal --検証
無効なシールされたシークレットの場合、 kubeseal
次のように表示します。
$ cat sealed-secrets.yaml | kubeseal --validateerror: 封印された秘密を復号化できません
シークレットは常にローテーションする必要があります。ただし、シークレットは別のシークレットで暗号化されるため、正しい決定を下すには、これら 2 つの層がどのように関係しているかを理解する必要があります。
TL;DR:
シーリング秘密キーが侵害された場合は、実際のシークレット値をローテーションする前に、以下の「早期キー更新」セクションの手順に従う必要があります。
SealedSecret キーの更新および再暗号化機能は、実際のシークレット値の定期的なローテーションに代わるものではありません。
シーリング キーは 30 日ごとに自動的に更新されます。これは、新しいシーリング キーが作成され、コントローラーがSealedSecret
リソースのシールを解除するために使用できるアクティブなシーリング キーのセットに追加されることを意味します。
最後に作成されたシーリング キーは、 kubeseal
使用するときに新しいシークレットをシールするために使用されるキーであり、 kubeseal --fetch-cert
使用するときに証明書がダウンロードされるキーです。
更新時間の 30 日は妥当なデフォルトですが、 SealedSecret
コントローラーのポッド テンプレート内のコマンドの--key-renew-period=
フラグを使用して必要に応じて調整できます。 value
フィールドには、golang の継続時間フラグ (例: 720h30m
) を指定できます。 Sealed Secrets をkube-system
名前空間にインストールしていると仮定して、次のコマンドを使用してデプロイメント コントローラーを編集し、 --key-renew-period
パラメーターを追加します。テキスト エディターを閉じて、デプロイメント コントローラーが変更されると、古いポッドを置き換えるために新しいポッドが自動的に作成されます。
kubectl edit deployment/sealed-secrets-controller --namespace=kube-system
値0
を指定すると、キーの自動更新が無効になります。もちろん、シーリング キーの自動更新を無効にする有効な使用例があるかもしれませんが、経験上、新規ユーザーは、シールされたシークレットがどのように機能するかを完全に理解する前に、キーの更新を制御したいという結論に飛びつく傾向があることがわかっています。これについて詳しくは、以下のよくある誤解のセクションをご覧ください。
残念ながら、Go stdlib ではサポートされていないため、たとえば「d」を日の単位として使用することはできません。手のひらで顔を叩く代わりに、プログラマーが時間について信じている虚偽についてじっくり考える機会として捉えてください。
よくある誤解は、キーの更新がキーのローテーションの一種であると考えられていることが多く、古いキーは古いだけでなく実際に問題があるため、それを削除したいと考えられることです。この機能が歴史的に「キー ローテーション」と呼ばれてきたことは、混乱を招く可能性があります。
シールされたシークレットは自動的にローテーションされず、新しいキーが生成されても古いキーは削除されません。古いSealedSecret
リソースは引き続き復号化できます (これは、古いシーリング キーが削除されないためです)。
シーリング キーの更新と SealedSecret のローテーションは、実際のシークレットのローテーションに代わるものではありません。
このツールの核となる価値提案は次のとおりです。
Secret を SealedSecret に暗号化すると、パブリック リポジトリ内であっても安全に保存できます。
バージョン管理ストレージ、特に公開ストレージに何かを保存する場合は、その情報は決して削除できないと想定する必要があります。
何らかの理由でシーリング キーがクラスターから漏洩した場合は、そのキーで暗号化されたすべてのSealedSecret
リソースが侵害されたものと見なす必要があります。クラスター内でシーリング キーをいくらローテーションしても、既存の SealedSecrets ファイルを再暗号化しても、この状況を変えることはできません。
ベスト プラクティスは、実際のシークレットをすべて定期的にローテーションし (パスワードの変更など) 、それらの新しいシークレットを使用して新しいSealedSecret
リソースを作成することです。
しかし、 SealedSecret
コントローラーがシーリング キーを更新していない場合、攻撃者は新しいシークレットを復号するだけで済むため、そのローテーションは無意味になります。したがって、シーリング キーを定期的に更新することと、実際のシークレットをローテーションすることの両方を行う必要があります。
シーリングキーが侵害されたことがわかっている、またはその疑いがある場合は、ローテーションされた新しいシークレットのシーリングを開始する前に、できるだけ早くキーを更新する必要があります。そうしないと、攻撃者にも新しいシークレットへのアクセスを与えることになります。
現在のタイムスタンプを--key-cutoff-time
というフラグまたはSEALED_SECRETS_KEY_CUTOFF_TIME
という環境変数にコントローラに渡すことで、キーを早期に生成できます。予期される形式は RFC1123 で、 date -R
unix コマンドを使用して生成できます。
封印された秘密の封印キーは、アクセス制御キー (パスワードなど) ではありません。これらは、送信された暗号化メールを読み取るために使用する GPG キーに似ています。電子メールの例えを少し続けてみましょう。
GPG 秘密鍵が侵害された可能性があると信じる理由があると想像してください。最初に秘密キーを削除するだけでは、得るものより失うものの方が多くなります。そのキーを使用して送信された以前のすべての電子メールには (それらの電子メールの復号化されたコピーがない限り) アクセスできなくなります。また、新しいキーを使用するようにまだ伝えていない友人から送信された新しい電子メールにもアクセスできなくなります。
確かに、攻撃者が電子メールを復号できる可能性があるため、暗号化された電子メールの内容は安全ではありませんが、終わったことは終わっています。突然それらのメールを読むことができなくなったとしても、被害が元に戻るわけではありません。むしろ、攻撃者がどのような秘密を知ったのかが確実に分からなくなるため、事態はさらに悪化します。あなたが本当にしたいことは、友人があなたの古いキーの使用をやめ、今後はすべての通信が新しいキーペアで暗号化されるようにすることです(つまり、友人はその新しいキーについて知っている必要があります)。
同じロジックが SealedSecrets にも適用されます。最終的な目標は、実際の「ユーザー」の秘密を保護することです。 「封印」の秘密は単なる機構、「封筒」にすぎません。秘密が漏洩したら、もう後戻りはできず、終わったことは終わりです。
まず、新しいシークレットが古い侵害されたキーで暗号化されないことを確認する必要があります (上記の電子メールの例えでは、新しいキー ペアを作成し、すべての友人に新しい公開キーを渡します)。
論理的な 2 番目のステップは、シークレットの性質に応じて、損害を無力化することです。簡単な例はデータベース パスワードです。データベース パスワードを誤って漏洩した場合、やるべきことはデータベース パスワードを (データベース上で変更し、古いパスワードを取り消して) 変更し、 SealedSecret
リソースを更新するだけです。新しいパスワード (つまり、 kubeseal
再度実行します)。
両方の手順については、あまり詳しくはありませんが、前のセクションで説明しました。根底にある理論的根拠をより深く理解した今、これらをもう一度読むことは恥ずかしいことではありません。
SealedSecret
コントローラーと関連するワークフローは、古いシーリング キーを保持し、定期的に新しいシーリング キーを追加するように設計されています。自分が何をしているのか理解していない限り、古いキーを削除しないでください。
ただし、必要に応じて、シーリング キーを手動で管理 (作成、移動、削除) することもできます。これらは、 SealedSecret
コントローラーが存在するのと同じ名前空間 (通常はkube-system
ですが、構成可能) に存在する通常の k8s シークレットです。
シーリングキーを創造的に管理することで対処できる高度なユースケースがあります。たとえば、同じシーリング キーをいくつかのクラスター間で共有できるため、複数のクラスターにまったく同じシールされたシークレットを適用できます。シーリング キーは通常の k8s シークレットであるため、シーリング シークレット自体を使用したり、GitOps ワークフローを使用してシーリング キーを管理したりすることもできます (異なるクラスター間で同じキーを共有する場合に便利です)。
シーリング キーシークレットにactive
以外のラベルを付けると、そのキーはSealedSecret
コントローラーから事実上削除されますが、必要に応じて手動暗号化/復号化のために k8s で引き続き使用できます。
注SealedSecret
コントローラーは現在、手動で作成、削除、または再ラベル付けされたシーリング キーを自動的に取得しません。効果を適用するには、管理者がコントローラを再起動する必要があります。
古いシーリング キーを削除する前に、最新の秘密キーを使用して SealedSecret を再暗号化する必要があります。
kubeseal --re-encrypttmp.json && mv tmp.json my_sealed_secret.json
上記の呼び出しにより、シークレットがクラスターからクライアントに渡されることなく、最新のキーで新たに暗号化された新しいシールされたシークレット ファイルが生成されます。その後、そのファイルをバージョン管理システムに保存できます ( kubeseal --re-encrypt
クラスター内オブジェクトを更新しません)。
現在、古いキーは自動的にガベージ コレクションされません。
SealedSecrets を定期的に再暗号化することをお勧めします。ただし、上で述べたように、誤ったセキュリティ意識に落ち着かないでください。SealedSecret リソースの古いバージョン (無効だと思われるキーで暗号SealedSecret
されたもの) がまだ存在し、攻撃者にアクセスできる可能性があると想定する必要があります。つまり、再暗号化は、実際のシークレットを定期的にローテーションすることに代わるものではありません。
このコントローラーは、新しいSealedSecret
カスタム リソースを追加します。 SealedSecret
の興味深い部分は、base64 でエンコードされ、非対称に暗号化されたSecret
です。
コントローラーは、秘密キーと公開キーのペアのセットを kubernetes シークレットとして維持します。キーにはsealedsecrets.bitnami.com/sealed-secrets-key
というラベルが付けられ、ラベル内でactive
またはcompromised
として識別されます。起動時に、Sealed Secrets コントローラーは...
これらのキーを検索し、アクティブとしてラベル付けされている場合はローカル ストアに追加します。
新しいキーを作成する
キーローテーションサイクルを開始します
暗号化の詳細については、こちらをご覧ください。
開発ガイドラインは、開発者ガイドに記載されています。
はい、できます!シークレットを好きなだけ 1 つのファイルにドロップします。 YAML の場合は---
使用して、JSON では追加の単一オブジェクトとしてそれらを必ず分離してください。
いいえ、秘密キーはコントローラーによって管理されるシークレットにのみ保存されます (k8s オブジェクトの他のバックアップがある場合を除く)。バックドアはありません。特定の SealedSecret の暗号化に使用される秘密キーがなければ、復号化できません。暗号化キーを使用してシークレットにアクセスできず、クラスター内に存在するシークレットの復号化されたバージョンにもアクセスできない場合は、すべてのパスワードを新しいパスワードで再生成し、新しいパスワードで再度封印する必要があります。封印キーなど
暗号化秘密キーのバックアップを作成したい場合は、適切なアクセス権を持つアカウントから簡単に実行できます。
kubectl get Secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml >main.keyecho "---" >> main.key kubectl get Secret -n kube-system sealed-secrets-key -o yaml >>main.key
注: 2 番目のステートメントは、クラスターにバージョン 0.9.x より古い sealed-secret をインストールしたことがある場合にのみ必要です。
注: このファイルにはコントローラの公開キーと秘密キーが含まれるため、安全に保管する必要があります。
注: キーを更新した後、バックアップを再作成する必要があります。そうしないと、バックアップで新しい封印されたシークレットを復号化できなくなります。
災害後にバックアップから復元するには、コントローラーを起動する前にシークレットを元に戻すだけです。コントローラーがすでに起動している場合は、新しく作成したシークレットを置き換えてコントローラーを再起動します。
Helm デプロイメントの場合:
kubectl apply -f main.key kubectl delete pod -n kube-system -l app.kubernetes.io/name=sealed-secrets
controller.yaml
マニフェストを介したデプロイメントの場合
kubectl apply -f main.key kubectl delete pod -n kube-system -l name=sealed-secrets-controller
シールされたシークレットをシークレットの長期ストレージ システムとして扱うことは推奨される使用例ではありませんが、k8s クラスターがダウンし、新しいSealedSecret
コントローラー デプロイメントにバックアップを復元できない場合にシークレットを回復できるという正当な要件を持つ人もいます。実用的。
1 つ以上の秘密キーをバックアップしている場合 (前の質問を参照)、 kubeseal --recovery-unseal --recovery-private-key file1.key,file2.key,...
コマンドを使用してファイルを復号化できます。封印された秘密ファイル。
kubeseal --help
使用して利用可能なフラグを確認できます。
kubernetes Secret
リソースには複数の項目が含まれており、基本的にはキーと値のペアのフラット マップです。 SealedSecrets はそのレベルで動作し、値に何を入力しても問題ありません。言い換えれば、シークレットに設定した構造化された構成ファイルを理解することができないため、そのファイル内の個々のフィールドを更新することはできません。
これは、特にレガシー アプリケーションを扱う場合によくある問題であるため、考えられる回避策の例を示します。
はい、コントローラーに独自の証明書を提供すると、コントローラーはそれらの証明書を使用します。回避策については、こちらをご確認ください。
kube-system
名前空間内で実行されていない場合に kubeseal を使用するにはどうすればよいですか?コントローラーをデフォルトのkube-system
とは異なる名前空間にインストールした場合は、この名前空間をkubeseal
コマンドライン ツールに提供する必要があります。次の 2 つのオプションがあります。
コマンドライン オプション--controller-namespace
を使用して名前空間を指定できます。
kubeseal --controller-namespace sealed-secretsmysealedsecret.json
環境変数SEALED_SECRETS_CONTROLLER_NAMESPACE
経由:
import SEALED_SECRETS_CONTROLLER_NAMESPACE=封印された秘密 kubesealmysealedsecret.json
私たちの画像はコサインを使用して署名されています。署名は GitHub Container Registry に保存されています。
v0.20.2 までのイメージは Cosign v1 を使用して署名されました。新しいイメージは Cosign v2 で署名されています。
画像を確認するのは非常に簡単です。
# COSIGN_VARIABLE をエクスポートして、GitHub コンテナー レジストリのサインを設定します。 pathexport COSIGN_REPOSITORY=ghcr.io/bitnami-labs/sealed-secrets-controller/signs# GHCR にアップロードされたイメージを確認します。cosign verify --key .github/workflows/cosign.pub ghcr。 io/bitnami-labs/sealed-secrets-controller:latest# アップロードされたイメージを確認しますDockerhubcosign で --key .github/workflows/cosign.pub docker.io/bitnami/sealed-secrets-controller:latest を確認してください
すべての名前空間ではなく、複数の名前空間に対して 1 つのコントローラーを使用する場合は、コマンド ライン フラグ--additional-namespaces=
を使用して追加の名前空間を指定できます。コントローラーがそこでシークレットを管理できるように、ターゲットの名前空間に適切なロールとロールバインディングを必ず指定してください。
答えは「はい」です。 --max-unseal-retries
フラグを使用してコントローラーで再試行回数を構成できます。このフラグを使用すると、Sealed Secret の封印を解除するための最大再試行回数を構成できます。
Kubernetes Slack の #sealed-secrets
ここをクリックして Kubernetes Slack 組織にサインアップします。
kubeseal-convert
: https://github.com/EladLeev/kubeseal-convert
Visual Studio コード拡張機能: https://marketplace.visualstudio.com/items?itemName=codecontemplator.kubeseal
WebSeal: ブラウザーでシークレットを生成します: https://socialgouv.github.io/webseal
HybridEncrypt TypeScript の実装: https://github.com/SocialGouv/aes-gcm-rsa-oaep
[非推奨] Sealed Secrets オペレーター: https://github.com/disposab1e/sealed-secrets-operator-helm