ほとんどの事例で、Kubernetes External Secrets Operator連携を推奨します。本ページでは、外部シークレットオペレーターを使用しない連携方法について解説します。
機能
Kubernetes内にKeeperボルトからシークレットを取り込みます
すべてのポッドでKeeperボルトのシークレットにリアルタイムにアクセスできます
Keeperボルトからローカルファイルシステムにファイル添付を安全にコピーします
Keeper Secrets Manager機能の完全なリストについては、概要 をご参照ください。
前提条件
このページでは、Secrets ManagerとKubernetesとの連携について説明します。 この連携を利用するための必要条件は以下のとおりです。
Keeper Secrets Managerへのアクセス(詳細は、クイックスタートガイド をご参照ください)
KeeperアカウントのSecrets Managerアドオンの有効化
Secrets Manager強制ポリシーが有効化されたロールを割り当てられたメンバーシップ
概説
Keeper Secrets ManagerをK8sクラスタに統合して、すべてのポッドでKeeperシークレットにリアルタイムにアクセスできます。
設定
Secrets Managerの設定を作成
Commanderを使用して、Kubernetes用のSecrets Managerデバイスの設定を作成します。この設定はIPが固定されておらず、事前に初期化されていることにご注意ください。
次のコマンドを使用して、Commanderで設定を作成します。
secrets-manager client add --app <APP NAME> --unlock-ip --config-init k8s
例:
コピー My Vault> sm client add --app MyAdd --unlock-ip --config-init k8s
Successfully generated Client Device
====================================
Initialized Config:
apiVersion: v1
data:
config: ewog2N...ICIxMCIKfQ==
metadata:
name: ksm-config
namespace: default
type:Opaque
IP Lock:Disabled
Token Expires On:2021-10-13 12:45:45
App Access Expires on:Never
上記の例では、8行目から14行目までをコピーし、secret.yamlという名前のファイルに挿入します。 次に、Kubectl がインストールされたマシンを使用していて、クラスタにアクセスできる場合は、KSM SDKの設定をKubernetesシークレットに追加します。
コピー $ kubectl apply -f secret.yaml
Secrets Mangerの設定の作成について詳しくは、設定のドキュメント をご参照ください。
代替方法:ワンタイムアクセストークンとKSM CLI
または、Commander(もしくはVault UI)でワンタイムアクセストークンを生成し、Keeper Secrets Manager CLI でワンタイムアクセストークンを使用した、以下に示すような設定(XX:XXXは置き換えます)を作成することもできます。
コピー $ ksm init k8s XX:XXX
apiVersion : v1
data :
config : ewog2N[...]ICIxMCIKfQ==
kind:Secret
metadata :
name : ksm-config
namespace : default
type:Opaque
Kubectl がインストールされたマシンを使用していて、クラスタにアクセスできる場合は、--apply
パラメータを設定して、KSM SDKの設定をKubernetesシークレットに自動的に追加できます。
トークンの引き換えの出力をファイルにパイプし、Kubectl で適用できます。 以下に例を示します。
コピー $ ksm init k8s XX:XXX > secret.yaml
$ kubectl apply -f secret.yaml
secret/ksm-config created
KSM設定の使用
KSM設定は、シークレット を使用してK8sコンテナにプルできます。
コピー apiVersion: v1
kind:Pod
metadata:
name: secret-env-pod
spec:
containers:
- name: mycontainer
image: my_container:XXXXX
env:
- name:KSM_CONFIG
valueFrom:
secretKeyRef:
name: ksm-config
key: config
restartPolicy:Never
K8sクラスタで実行されているKeeper Developer SDKは、実行時に環境変数KSM_CONFIG を使用してデバイス設定を取得し、Keeperボルトと通信します。
例
例1 - SDKを使用したカスタムアプリ
ウェブアプリケーションを使用してデータベースシークレットを表示するデプロイメントとサービスを生成する簡単な例を以下に示します。この例では、ウェブアプリケーション用のKeeper Python Developer SDKを使用します。このSDKでKubernetesシークレットから設定を取得し、KeeperボルトからPostgreSQLデータベース記録の情報を取得します。
Keeperボルトから、以下の情報を使用して「データベース」記録タイプが作成されます。
では、ウェブアプリケーションを作成しましょう。ウェブページは、任意の開発者用SDKを使用して作成できます。この例では、Python SDKを使用します。単一のエンドポイントを指定する単純なFlaskアプリケーションは、ボルトの記録シークレットを含むHTMLを表示します。シークレットは、Keeper表記法 構文を使用して取得されます。
コピー from flask import Flask
from keeper_secrets_manager_core import SecretsManager
import os
app = Flask(__name__)
@app.route("/")
def hello_world():
sm = SecretsManager()
return """
<h1>Database</h1>
<ul>
<li>Type: {}</li>
<li>Host: {}</li>
<li>Port: {}</li>
<li>Login: {}</li>
<li>Password: {}</li>
</ul>
""".format(
sm.get_notation(os.environ.get("DB_TYPE")),
sm.get_notation(os.environ.get("DB_HOST")),
sm.get_notation(os.environ.get("DB_PORT")),
sm.get_notation(os.environ.get("DB_LOGIN")),
sm.get_notation(os.environ.get("DB_PASS")))
次のパートでは、Dockerfile を作成します。以下のDockerfileのベースは、Docker HubのPython Debianイメージです。
Python SDKは、暗号化モジュールを使用します。このモジュールはRust言語をインストールする必要があります。RustがプレインストールされているDocker Hubイメージもあります。
コピー FROM python:3.10.0-slim-bullseye
RUN apt-get update \
&& apt-get install -y gcc make libffi-dev curl libssl-dev \
&& apt-get clean
RUN pip3 install --upgrade pip wheel
# 暗号化のビルドにRustが必要
RUN curl https://sh.rustup.rs -sSf > /tmp/rust.sh \
&& chmod a+x /tmp/rust.sh \
&& /tmp/rust.sh -y
ENV PATH $PATH:/root/.cargo/bin
RUN pip3 install \
flask \
keeper-secrets-manager-core
RUN groupadd -g 5000 demo
RUN useradd -g demo demo
# アプリケーションをイメージにコピー
COPY demo.py /demo.py
USER demo
ENV FLASK_APP demo
EXPOSE 5000
CMD ["flask", "run"]
次に、ksm_demoという名前のDockerイメージをビルドします。
コピー $ docker build -t ksm_demo .
Kubernetesクラスタにアクセスできると仮定すると、設定はワンタイムアクセストークンから生成されて、自動的に適用されます。
コピー $ ksm init k8s --apply XX:XXXXXXXXXXX
secret/ksm-config created
Created secret for KSM config.
kubectl get secret
と入力すると、シークレットのエントリが表示されます。
コピー $ kubectl get secret ksm-config
NAME TYPE DATA AGE
ksm-config Opaque 1 55s
これで、ksm_demo Dockerイメージのデプロイメントとサービスを作成できます。この例では、ファイルにksm_demo.yaml という名前を付けます。
必要なシークレットとSDKの設定は、コンテナ の一覧のenv セクションで定義します。このセクションでは、KSM_CONFIG 環境変数を定義して、ksm-config Kubernetesシークレット、特にシークレットのconfig キーの値を取得します。
他の環境変数は単なる名前/値のリストです。この値はKeeper表記法で、ウェブアプリケーションによってSDKの表記法取得メソッドに送信されます。
ksm_demo.yaml ファイルの2番目の記録は、サービス の定義です。これは、Kubernetesクラスタで動作するサービスであれば何にでも変更できます。この例では、外部IPアドレスを使用します。この例では、KubernetesノードのIPアドレスのいずれかを使用するのが安全です。たとえば、10.0.1.18を使用します。
コピー ---
apiVersion: apps/v1
kind:Deployment
metadata:
name: ksm-demo-deployment
labels:
app: ksm-demo
spec:
replicas:1
selector:
matchLabels:
app: ksm-demo
template:
metadata:
labels:
app: ksm-demo
spec:
nodeSelector:
kubernetes.io/hostname: work
dnsPolicy:"None"
dnsConfig:
nameservers:
- 10.0.1.207
- 1.1.1.1
containers:
- name: ksm-demo
image: ksm_demo:latest
imagePullPolicy:IfNotPresent
ports:
- containerPort:5000
protocol:TCP
env:
- name:KSM_CONFIG
valueFrom:
secretKeyRef:
name: ksm-config
key: config
- name:DB_TYPE
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/Type"
- name:DB_HOST
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/host[hostName]"
- name:DB_PORT
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/host[port]"
- name:DB_LOGIN
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/login"
- name:DB_PASS
value: "keeper://IUCvqyWcx7sG-BGIK1R9-g/field/password"
---
apiVersion: v1
kind:Service
metadata:
name: ksm-demo-service
spec:
ports:
- name: http
port:5000
targetPort:5000
protocol:TCP
selector:
app: ksm-demo
externalIPs:
- 10.0.1.18
これで、デプロイメントとサービスを適用する準備ができました。
コピー $ kubectl apply -f ksm_demo.yaml
deployment/ksm-demo-deployment created
service/ksm-demo-service created
デプロイメントの準備ができるまで待ちます。コマンドラインまたはKubernetesダッシュボードを使用して監視します。
コピー $ kubectl get deployment ksm-demo-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
ksm-demo-deployment 1/1 1 1 46m
$ kubectl get svc ksm-demo-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ksm-demo-service ClusterIP 10.107.91.89 10.0.1.18 5000/TCP 56m
最後に、ウェブブラウザを使用して外部IPアドレスのポート5000にアクセスすると、Keeperボルトのデータベース記録のシークレットが表示されます。
例2 - NGINX SSL証明書
この例では、Keeperボルトから取得したデフォルトのNGINX DockerイメージとSSL証明書を含むポッドが作成されます。
SSL証明書、秘密鍵、証明書のパスワードを格納するログイン記録がボルトに作成されます。
ワンタイムトークンが生成され、KubernetesのConfigMapに追加されます。
コピー $ ksm init k8s XX:XXX > secret.yaml
$ kubectl apply -f secret.yaml
secret/ksm-config created
例のウェブサイトは、単なるインデックスHTMLページです。このHTMLをConfigMapに保存して、ドキュメントのルートディレクトリにマウントできます。
コピー ---
apiVersion : v1
kind:ConfigMap
metadata :
name : nginx-html-config
namespace : default
labels :
app : nginx
data :
index.html : |
<html>
<head>
<title>Nginx Test Page</title>
</head>
<body>
<h1>Hello From Keeper Secrets Manager!</h1>
</body>
</html>
default.conf
は、この例によって上書きされます。証明書、鍵、パスワードは、/etc/keys
ディレクトリに格納されます。非対話型起動の場合、NGINXは証明書のパスワードをファイルに格納し、サーバー設定でssl_password_file
を指定する必要があります。
コピー ---
apiVersion : v1
kind:ConfigMap
metadata :
name : nginx-config
namespace : default
labels :
app : nginx
data :
default.conf : |
server {
listen 80 default;
server_name localhost;
location / {
root /var/www/nginx-default;
index index.html index.htm;
}
}
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/keys/example.com.crt;
ssl_certificate_key /etc/keys/example.com.key;
ssl_password_file /etc/keys/global.pass;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /var/www/nginx-default;
index index.html index.htm;
}
}
この例のデプロイメントは以下のようになります。
コピー ---
apiVersion : apps/v1
kind:Deployment
metadata :
name : nginx-deployment
labels :
app : nginx
spec :
replicas:1
selector :
matchLabels :
app : nginx
template :
metadata :
labels :
app : nginx
spec :
initContainers :
- name : ksm
image : keeper/keeper-secrets-manager-writer:latest
env :
- name:KSM_CONFIG
valueFrom :
secretKeyRef :
name : ksm-config
key : config
- name:SECRETS
value : |
5x0v0VFwYj2VvuhamrJhzQ/field/password > file:/etc/keys/global.pass
5x0v0VFwYj2VvuhamrJhzQ/file/example.com.crt > file:/etc/keys/example.com.crt
5x0v0VFwYj2VvuhamrJhzQ/file/example.com.key > file:/etc/keys/example.com.key
volumeMounts :
- mountPath : "/etc/keys"
name : keys-volume
containers :
- name : nginx
image : nginx:1.21.4-alpine
imagePullPolicy:IfNotPresent
ports :
- containerPort:80
protocol:TCP
- containerPort:443
protocol:TCP
volumeMounts :
- mountPath : "/etc/keys"
name : keys-volume
- mountPath : "/etc/nginx/conf.d/default.conf"
name : nginx-config-file
subPath : default.conf
- mountPath : "/var/www/nginx-default/index.html"
name : nginx-html-file
subPath : index.html
volumes :
- name : keys-volume
emptyDir : {}
- name : nginx-config-file
configMap :
name : nginx-config
- name : nginx-html-file
configMap :
name : nginx-html-config
imagePullSecrets :
- name : my-docker-hub-secrets
初期化コンテナには、dockerイメージkeeper/keeper-secrets-manager-writer
が使用されます。コンテナはシークレットを取得し、NGINXで使用できるようにディスクに書き込みます。シークレットはポッドのemptyDirボリュームに書き込まれ、/etc/keysにマウントされます。このディレクトリは、ポッドが削除されると削除されます。
Keeper Secrets Manager Writerのドキュメントはこちら で入手できます。
また、メインコンテナは、ポッドのemptyDirボリュームを/etc/keysにマウントします。さらに、default.conf
を/etc/nginx/conf.dにマウントし、index.html
ファイルをサーバーのドキュメントルートにマウントします。
最後は、以下に示すように、NGINXにアクセスするサービスを作成します。
コピー ---
apiVersion: v1
kind:Service
metadata:
name: nginx-service
spec:
ports:
- name: http
port:80
targetPort: 80
protocol:TCP
- name: https
port:443
targetPort:443
protocol:TCP
selector:
app: nginx
externalIPs:
- XXX.XXX.XXX.XX
サービスは、httpsで外部IP(https://XXX.XXX.XXX.XXX)にアクセスしてテストできます。アドレスバーの鍵が証明書が有効であることを示していることにご注意ください。
外部シークレット
外部シークレットは、外部APIからのシークレットを同期してKubernetesに注入するKubernetesオペレータです。KeeperボルトからKubernetesにシークレットを同期するために外部シークレットをセットアップする方法の詳細については、こちらをご参照ください。
次の手順
この時点で、Secrets Manager SDK のいずれかを使用して、Keeper Secrets ManagerをK8sデプロイメントに統合できるようになりました。