Sep 19, 2020
Sep 19, 2020
N/A Views
MD
warning
この記事は2年以上前に更新されたものです。情報が古くなっている可能性があります。

Kubernetesのmanifestをgitで管理するとき、Secretの扱いが課題になりがちです。
基本的にデプロイに必要なKubernetesリソースのyamlは全てGitに管理したいですが、
Secretリソースは機密情報がbase64エンコードまたは平文で保存されており、

KubernetesのSecretをサポートするプロジェクトとして、

が有名です。

External SecretsではSecretの内容をHashicorp VaultやAWS Secrets Managerといった外部のSecret Managerに管理します。
ExternalSecretリソースに外部Secret Managerの参照を定義し、そこからSecretオブジェクトを生成します。
ExternalSecretリソースのYAMLはgit管理可能です。

Sealed SecretsではSealedSecretリソースにクライアントサイドで暗号化したSecretの内容を設定し、サーバーサイドで復号してSecretオブジェクトを生成します。暗号化にはkubeseal CLIを使用します。
SealedSecretリソースのYAMLはgit管理可能です。

どちらも汎用的にSecretを扱えますが、動機が"自動生成したパスワードをSecretに設定したい"だけであれば、
手間が大きく、やりたいことに対して複雑に感じます。

サーバーサイドでパスワードや証明書を自動生成したいだけであれば、Quarks Secretがシンプルです。

Quarks Secretの簡単な使い方を紹介します。

Note: QuarksはSuseが主に開発を進めている、Cloud FoundryのBOSHでデプロイしていたソフトウェアをKubernetesにデプロイするために変換するController群です。
その中でもQuarks SecretはBOSHで使われていた機密情報自動生成機能を移行したもので、この部分だけスタンドアローンで利用できます。

同様なツールとしてはsecretgen-controllerがあります。

Quarks Secretのインストール

インストールはHelmで行います。

helm repo add quarks https://cloudfoundry-incubator.github.io/quarks-helm/
helm install qsecret quarks/quarks-secret --namespace quarks --create-namespace --wait

インストールが完了したら、quarkssecrets.quarks.cloudfoundry.orgというカスタムリソースが出来ます。

$ kubectl get crd | grep quarks
quarkssecrets.quarks.cloudfoundry.org                   2020-09-19T13:27:52Z

このQuarksSecretオブジェクトを作成するとSecretオブジェクトを自動生成できます。自動生成できるSecretの種類は

  • password
  • certificate
  • tls
  • ssh
  • rsa
  • basic-auth
  • dockerconfigjson
  • copy
  • templatedconfig

です。個々の使い方はドキュメントサンプルで学べます。

デフォルトではstaging Namespaceのみ監視対象になります。
他のNamespaceも対象としたい場合は、Namespaceリソースのquarks.cloudfoundry.org/monitoredラベルにqsecret-quarks-secret(Helmでインストールした場合のデフォルト値)を設定する必要があります。
この設定がないとQuarksSecretオブジェクトを作成してもSecretは生成されません。

ここではdefault Namespaceにそのラベルを設定します。

kubectl patch namespace default --type=json -p '[{"op": "add", "path": "/metadata/labels", "value": {"quarks.cloudfoundry.org/monitored": "qsecret-quarks-secret"}}]'

Passwordの自動生成

次のdemo.ymlを作成します。

apiVersion: quarks.cloudfoundry.org/v1alpha1
kind: QuarksSecret
metadata:
  name: demo
spec:
  type: password
  secretName: demo
$ kubectl apply -f demo.yml 
quarkssecret.quarks.cloudfoundry.org/demo created

QuarksSecretリソースを作成するとdemoという名前のSecretができていることがわかります。

$ kubectl get secret,quarkssecret demo
NAME          TYPE     DATA   AGE
secret/demo   Opaque   1      5s

NAME                                        COPIED   GENERATED
quarkssecret.quarks.cloudfoundry.org/demo   true     true

生成されたSecretの値(password)を確認します。

$ kubectl get secret demo -o go-template='{{index .data "password" | base64decode}}'
niBhcLk5NKBOSDeA6cS1APeKcmIFppNGKcyCRuZCq8lnJf9PfMbhC15ezuAbeTfE

Passwordのローテート

Passwordはローテート可能です。次のようなrotate.ymlを作成します。

apiVersion: v1
kind: ConfigMap
metadata:
  name: rotate
  labels:
    quarks.cloudfoundry.org/secret-rotation: "true"
data:
  secrets: '["demo"]'
$ kubectl apply -f rotate.yml 
quarkssecret.quarks.cloudfoundry.org/demo created

生成されたpasswordの値を確認します。

$ kubectl get secret demo -o go-template='{{index .data "password" | base64decode}}'
57BzENCpDmqFBVrnxOoMnlZzEvfA0iGY2S5cmV9cJVK2p4cwWbtgCY35wmKOcXGN

Basic Authの自動生成

ユーザー名、パスワードをまとめて生成できます。次のauth.ymlを作成します。

apiVersion: quarks.cloudfoundry.org/v1alpha1
kind: QuarksSecret
metadata:
  name: auth
spec:
  type: basic-auth
  secretName: auth
$ kubectl apply -f auth.yml 
quarkssecret.quarks.cloudfoundry.org/auth created

kubernetes.io/basic-auth TypeのSecretが生成されます。

$ kubectl get secret,quarkssecret auth
NAME          TYPE                       DATA   AGE
secret/auth   kubernetes.io/basic-auth   2      33s

NAME                                        COPIED   GENERATED
quarkssecret.quarks.cloudfoundry.org/auth   true     true

生成されたSecretの値(username及びpassword)を確認します。

$ kubectl get secret auth -o go-template='{{index .data "username" | base64decode}}'
wfdfcank0141g7B6hCbl7953uzFWofYp8RKQAgsEyVbEeSPPCj2Q46wf5lGHfbWY
$ kubectl get secret auth -o go-template='{{index .data "password" | base64decode}}'
ZtsfXWGfqqDHlMjBJchLHDER3uN2m8nvmq2P6qon5zQvVkWoG5tYAtQQbrH9V0Iq

アプリケーションのサンプル

実用例として、gitで管理するアプリケーションのマニフェストサンプルを示します。

hello.ymlを作成します。このファイルはgitで管理できますし、これ以外のファイルは管理する必要がありません。

apiVersion: v1
kind: Namespace
metadata:
  name: demo
  labels:
    quarks.cloudfoundry.org/monitored: qsecret-quarks-secret
---
apiVersion: quarks.cloudfoundry.org/v1alpha1
kind: QuarksSecret
metadata:
  name: hello-password
  namespace: demo
spec:
  type: password
  secretName: hello-password
---	
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: demo
  name: demo
  labels:
    app: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: hello
        image: ghcr.io/making/hello
        env:
        - name: SPRING_SECURITY_USER_PASSWORD
          valueFrom:
            secretKeyRef:
              name: hello-password
              key: password      
---
apiVersion: v1
kind: Service
metadata:
  namespace: demo
  name: demo
  labels:
    app: demo
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: demo
  type: ClusterIP
kubectl apply -f hello.yml

ServiceをPort Forwardします。

kubectl port-forward -n demo service/demo 8080:80

生成されたパスワードを取得します。

PASSWORD=$(kubectl get secret -n demo hello-password -o go-template='{{index .data "password" | base64decode}}')

パスワード有無でそれぞれアクセスします。

$ curl localhost:8080 -v
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 401 
< Set-Cookie: JSESSIONID=C88CB80B86495DBF086159105F93FBE2; Path=/; HttpOnly
< WWW-Authenticate: Basic realm="Realm"
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Sat, 19 Sep 2020 14:40:55 GMT
< 
{"timestamp":"2020-09-19T14:40:55.679+00:00","status":401,"error":"Unauthorized","message":"","path":"/"}

$ curl localhost:8080 -u user:${PASSWORD} -v
> GET / HTTP/1.1
> Host: localhost:8080
> Authorization: Basic dXNlcjpHY1hSall6c2J5MzRCaENGb3FUclk0Nm94VjhicFQ5UUNJRFBIUkY2U05ROXFBb0RHSm9lazRlUE1JblVsblZO
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 200 
< Set-Cookie: JSESSIONID=6AE2EF09AEFA5F44EA4C32F4A3A5A9D6; Path=/; HttpOnly
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 15
< Date: Sat, 19 Sep 2020 14:52:04 GMT
< 
Hello World!

Quarks Secretで簡単にサーバーサイドでパスワードを自動生成できました。
シンプルな例であれば、SecretだけGitとは別に管理するという面倒くさいことをしなくても済みます。

Found a mistake? Update the entry.
Share this article: