Hashicorp Vault への Cassandra Secret の保存

Hashicorp Vault への Cassandra Secret の保存

この機能によって、外部シークレット マネージャーである Hashicorp Vault に Apigee ハイブリッド用の Cassandra DB 認証情報を保存できます。外部シークレット マネージャーによって、データ所在地の管理と詳細なアクセス制御など、Kubernetes で Secret を保存する方法を管理できます。

Apigee ハイブリッド バージョン 1.10 より前は、Cassandra ユーザーにパスワードを提供する唯一の方法は、overrides.yaml でパスワードを指定することでした。これらのパスワードは Kubernetes Secret に保存されます。次に例を示します。

cassandra:
  auth:
    default:
      password: "********"
    admin:
      password: "********"
    ddl:
      password: "********"
    dml:
      password: "********"
    jmx:
      username: "jmxuser"
      password: "********"
    jolokia:
      username: "apigee"
      password: "********"

Hashicorp Vault を使用すると、Kubernetes Secrets Store CSI ドライバ API(SecretProviderClass)を介してこれらのパスワードを提供できます。これにより、Kubernetes は外部 Vault に保存されている複数の Secret、鍵、証明書をマウントできます。

Cassandra のユーザーとパスワード

次の Cassandra ユーザーのシークレットを作成する必要があります。組織のセキュリティ ポリシーに合わせてデフォルト値を変更してください。

Cassandra ユーザー デフォルトのユーザー名 デフォルトのパスワード
管理者 admin_user "********"
DDL ddl_user "********"
デフォルト cassandra 注: デフォルトのユーザー名は常に「cassandra」にする必要があります。 "********"
DML dml_user "********"
JMX "jmxuser" "********"
Jolokia "apigee" "********"

詳細については、cassandra 構成プロパティをご覧ください。

外部 Secret 統合を構成する

Apigee ハイブリッドの Vault のインテグレーションの設定は、次の手順から成り立っています。

  • 最初の 2 つの手順では、Vault を直接操作します。
  • 3 番目と 4 番目の手順では、Kubernetes クラスタに構成を適用します。

次の手順を用いて、Vault に Secret を作成し、ハイブリッド インストールをそれらにアクセスできるようにします。

Vault の Secret、ポリシー、ロールを作成する

  1. 現在の Kubernetes コンテキストがクラスタに設定されていることを確認します。
    kubectl config current-context
  2. Vault API、CLI、または UI を使用して、Cassandra Secret を作成します。作成する Secret の値は、クラスタで現在使用されている Cassandra のユーザー名とパスワードと一致している必要があります。
    • 秘密鍵: 任意の秘密鍵(または複数の鍵の組み合わせ)を使用できます。例:
      secret/data/apigee/cassandra
    • Secret データ: Apigee ハイブリッドでは、次の Cassandra ユーザーのユーザー名とパスワードのペアを想定します。
      Cassandra ユーザー
      管理者
      DDL
      デフォルト
      DML
      JMX
      Jolokia
      これらのユーザー名とパスワードの値は、任意の数の秘密鍵に分散できます。
    • Vault CLI: 次のコマンドは、必要なすべてのユーザー名とパスワードを含む単一の Secret を作成する方法を示しています。
      vault kv put secret/apigee/cassandra \
          adminUsername="ADMIN_USERNAME" \
          adminPassword="ADMIN_PASSWORD" \
          ddlUsername="DDL_USERNAME" \
          ddlPassword="DDL_PASSWORD" \
          defaultUsername="cassandra" \
          defaultPassword="DEFAULT_PASSWORD" \
          dmlUsername="DML_USERNAME" \
          dmlPassword="DML_PASSWORD" \
          jmxUsername="JMX_USERNAME" \
          jmxPassword="JMX_PASSWORD" \
          jolokiaUsername="JOLOKIA_USERNAME" \
          jolokiaPassword="JOLOKIA_PASSWORD"
      各ユーザーのデフォルトのユーザー名は次のとおりです。
      Cassandra ユーザー デフォルト値
      管理者 admin_user
      DDL ddl_user
      デフォルト cassandra
      DML dml_user
      JMX jmxuser
      Jolokia apigee
  3. Vault 内で、作成したばかりの Secret へのアクセス権を付与するポリシーを作成します。
    1. 次の内容のポリシー ファイル(推奨名: apigee-cassandra-auth.txt)を作成します。
      path "secret/data/apigee/cassandra" {
        capabilities = ["read"]
      }
      複数の Secret を作成した場合は、各 Secret をポリシー ファイルに追加する必要があります。
      path "secret/data/apigee/cassandra/admin" {
        capabilities = ["read"]
      }
      
      path "secret/data/apigee/cassandra/ddl" {
        capabilities = ["read"]
      }
    2. Vault にポリシーを適用します。
      vault policy write apigee-cassandra-auth apigee-cassandra-auth.txt

      ファイルから読み取る代わりに、標準入力を使用してポリシーを作成することもできます。

      echo 'path "secret/data/apigee/cassandra" { capabilities = ["read"] }' | vault policy write apigee-cassandra-auth -
  4. ポリシーを Apigee Cassandra Kubernetes サービス アカウントにバインドします。
    1. 次の環境変数を定義します。
      export ORG_NAME=APIGEE_ORG_NAME
      export ENVS_LIST=LIST_OF_APIGEE-ENVS
      export APIGEE_NAMESPACE=YOUR_APIGEE_NAMESPACE
      export NAMESPACES=apigee-system,${APIGEE_NAMESPACE}

      各要素の意味は次のとおりです。

      • ORG_NAME は実際の Apigee 組織の名前です。
      • ENVS_LIST は、Apigee 環境のカンマ区切りのリストです(たとえば、dev,prod)。
      • APIGEE_NAMESPACE は Apigee Namespace です。デフォルトは apigee です。
      • NAMESPACES は、Apigee、apigee-system、Apigee 名前空間の名前空間のカンマ区切りのリストです。
    2. 次の内容を含むスクリプトを作成します。スクリプトには任意の名前を付けることができます。次の例で、スクリプトの名前は create-vault-cassandra-role.sh です。
      # create-vault-cassandra-role.sh
      
      ORG=ORG_NAME  # ORG name
      ENVS=ENVS_LIST # comma separated env names, for example: dev,prod
      
      org_short_name=$(echo $ORG | head -c 15)
      encode=$(echo -n $ORG | shasum -a 256 | head -c 7)
      org_encode=$(echo "$org_short_name-$encode")
      names=apigee-manager,apigee-cassandra-default,apigee-cassandra-backup-sa,apigee-cassandra-restore-sa,apigee-cassandra-schema-setup-${org_encode},apigee-cassandra-schema-val-${org_encode},apigee-cassandra-user-setup-${org_encode},apigee-mart-${org_encode},apigee-mint-task-scheduler-${org_encode}
      
      for env in ${ENVS//,/ }
      do
        env_short_name=$(echo $env | head -c 15)
        encode=$(echo -n $ORG:$env | shasum -a 256 | head -c 7)
        env_encode=$(echo "$org_short_name-$env_short_name-$encode")
        names+=,apigee-synchronizer-${env_encode},apigee-runtime-${env_encode}
      done
      
      echo $names
      
    3. スクリプトを実行し、出力を SERVICE_ACCOUNT_NAMES 変数に割り当てます。これにより、Kubernetes サービス アカウント名のカンマ区切りのリストが作成されます。
      export SERVICE_ACCOUNT_NAMES=$(./create-vault-cassandra-role)

      変数にリストが挿入されていることを確認します。

      echo $SERVICE_ACCOUNT_NAMES
    4. Vault CLI を使用して、ポリシーを Kubernetes サービス アカウントにバインドするロールを作成します。
      vault write auth/kubernetes/role/cassandra \
          bound_service_account_names=${SERVICE_ACCOUNT_NAMES} \
          bound_service_account_namespaces=${NAMESPACES} \
          policies=apigee-cassandra-auth \
          ttl=1m

CSI ドライバと Vault プロバイダをインストールする

Apigee ハイブリッド v1.11.1 は、次の Helm チャートのバージョンをサポートしています。

ソフトウェア バージョン
Secret ストアの CSI ドライバ v1.3.4
Vault v0.25.0
  1. Secrets Store CSI ドライバのインストール手順に沿って、クラスタに CSI ドライバをインストールします。CSI ドライバには、インストール用の Helm チャートがあります。
  2. Vault CSI プロバイダをまだインストールしていない場合は、Vault CSI プロバイダのインストールの手順に沿ってインストールします。

SecretProviderClass オブジェクトを作成する

SecretProviderClass リソースは、Secret をリクエストするときに通信するプロバイダを CSI ドライバに伝えます。Cassandra ユーザーの認証情報は、このオブジェクトを介して構成する必要があります。次の表に、Apigee Cassandra で想定されているファイル名(objectName)を示します。

Cassandra ユーザー 想定される Secret ファイル名
管理者 adminUsernameadminPassword
DDL ddlUsernameddlPassword
デフォルト cassandradefaultPassword
DML dmlUsernamedmlPassword
JMX jmxUsernamejmxPassword
Jolokia jolokiaUsernamejolokiaPassword
  1. SecretProviderClass の YAML ファイルを作成します。ファイルには任意の名前を付けることができます(たとえば、spc.yaml)。次の SecretProviderClass テンプレートを使用して、このリソースを構成します。
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: apigee-cassandra-auth-spc
    spec:
      provider: vault
      parameters:
        roleName: apigee-cassandra-auth  # the roleName should match the vault role you created earlier in this procedure
    
        # vaultAddress is the endpoint your Vault server is running at.
        # If Vault is running in the same cluster as Apigee, the format will generally be:
        # http://vault.<namespace>.svc.cluster.local:<vaultServicePort>
        vaultAddress: VAULT_ADDRESS
    
        # "objectName" is an alias used within the SecretProviderClass to reference
        # that specific secret. This will also be the filename containing the secret.
        # Apigee Cassandra expects these exact values so they must not be changed.
        # "secretPath" is the path in Vault where the secret should be retrieved.
        # "secretKey" is the key within the Vault secret response to extract a value from.
        # For example, if the Vault secret is located at `secret/data/apigee/cassandra`
        # and you want to specify the admin password, you would use the following:
        # - objectName: "adminPassword"
        #   secretPath: "secret/data/apigee/cassandra"
        #   secretKey: "key within Vault secret specifying the admin password"
        objects: |
          - objectName: "adminUsername"
            secretPath: ""
            secretKey: ""
          - objectName: "adminPassword"
            secretPath: ""
            secretKey: ""
          - objectName: "defaultUsername"
            secretPath: ""
            secretKey: ""
          - objectName: "defaultPassword"
            secretPath: ""
            secretKey: ""
          - objectName: "ddlUsername"
            secretPath: ""
            secretKey: ""
          - objectName: "ddlPassword"
            secretPath: ""
            secretKey: ""
          - objectName: "dmlUsername"
            secretPath: ""
            secretKey: ""
          - objectName: "dmlPassword"
            secretPath: ""
            secretKey: ""
          - objectName: "jolokiaUsername"
            secretPath: ""
            secretKey: ""
          - objectName: "jolokiaPassword"
            secretPath: ""
            secretKey: ""
          - objectName: "jmxUsername"
            secretPath: ""
            secretKey: ""
          - objectName: "jmxPassword"
            secretPath: ""
            secretKey: ""
  2. SecretProviderClassapigeeapigee-system の両方の名前空間に適用します。次のコマンドでは、名前空間は apigeeapigee-system です。異なる名前空間を使用する場合は、その値を置き換えます。
    kubectl -n apigee apply -f spc.yaml
    kubectl -n apigee-system apply -f spc.yaml

Cassandra の外部 Secret を有効にする

  1. overrides.yaml 内で、次の構成を追加して Cassandra の外部 Secret の使用を有効にします。
    cassandra:
      auth:
        secretProviderClass: apigee-cassandra-auth-spc  # The name of the SecretProviderClass created in spc.yaml.

    詳細については、cassandra.auth.secretProviderClass をご覧ください。

  2. helm upgrade を使用して、apigee-operator コンポーネントと apigee-datastore コンポーネントに変更を適用します。
    • apigee-operator のデータストア コントローラは、Cassandra の廃止とリージョン拡張時のデータ レプリケーションに参加します。これらのタスクには JMX と Jolokia の認証情報が必要です。
      helm upgrade operator apigee-operator/ \
        --namespace apigee-system \
        --atomic \
        -f overrides.yaml
    • apigee-datastore は、Cassandra への接続時に apigee-runtime、Synchronizer、MART などのダウンストリーム コンポーネントが使用する認証情報を提供します。
      helm upgrade datastore apigee-datastore/ \
        --namespace apigee \
        --atomic \
        -f overrides.yaml
  3. 外部 Secret が使用されていることを確認します。外部 Secret を有効にすると、Secret を参照する新しい VolumeVolume MountEnvironment Variable が追加されます。
    • apigee-controller-manager Deployment を確認します。

      apigee-external-secrets という名前の Volume が存在し、上記で作成した SecretProviderClass を参照していることを確認します。

      kubectl -n apigee-system get deployment apigee-controller-manager -o jsonpath='{.spec.template.spec.volumes[?(@.name=="apigee-external-secrets")]}'
      {
        "csi": {
          "driver": "secrets-store.csi.k8s.io",
          "readOnly": true,
          "volumeAttributes": {
            "secretProviderClass": "apigee-cassandra-auth-spc"
          }
        },
        "name": "apigee-external-secrets"
      }

      apigee-external-secrets という名前の VolumeMount が存在することを確認します。

      kubectl -n apigee-system get deployment apigee-controller-manager -o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].volumeMounts[?(@.name=="apigee-external-secrets")]}'
      {
        "mountPath": "/opt/apigee/externalsecrets",
        "name": "apigee-external-secrets",
        "readOnly": true
      }

      外部 Secret を参照する Environment Variable が存在することを確認します。

      kubectl -n apigee-system get deployment apigee-controller-manager -o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].env}'
      [
        ...
        {
          "name": "CASSANDRA_JOLOKIA_USERNAME_PATH",
          "value": "/opt/apigee/externalsecrets/jolokiaUsername"
        },
        {
          "name": "CASSANDRA_JOLOKIA_PASSWORD_PATH",
          "value": "/opt/apigee/externalsecrets/jolokiaPassword"
        }
      ]

K8s Secret にロールバックする

  1. 非外部 Secret に戻すには、overrides.yamlsecretProviderClass 構成を削除し、以前の構成を使用します。
    cassandra:
          auth:
            secretProviderClass: apigee-cassandra-auth-spc # remove this line
  2. helm upgrade を使用して、apigee-operator コンポーネントと apigee-datastore コンポーネントに変更を適用します。
    helm upgrade operator apigee-operator/ \
      --namespace apigee-system \
      --atomic \
      -f overrides.yaml
    helm upgrade datastore apigee-datastore/ \
      --namespace apigee \
      --atomic \
      -f overrides.yaml

トラブルシューティング: デバッグ用のクライアント コンテナを作成する

Vault を使用している場合は、このセクションは、トラブルシューティングのセクションのデバッグ用のクライアント コンテナを作成するの手順を置き換えます。

このセクションでは、cqlsh などの Cassandra デバッグ ユーティリティにアクセスできるクライアント コンテナを作成する方法について説明します。これらのユーティリティを使用すると、Cassandra テーブルに対してクエリを実行できるので、デバッグに役立ちます。

クライアント コンテナを作成する

クライアント コンテナを作成する手順は次のとおりです。

  1. コンテナは、apigee-cassandra-user-setup Pod からの TLS 証明書を使用します。最初に、この証明書名を取得します。
    kubectl get secrets -n apigee --field-selector type=kubernetes.io/tls | grep apigee-cassandra-user-setup | awk '{print $1}'

    このコマンドは、証明書名を返します。例: apigee-cassandra-user-setup-rg-hybrid-b7d3b9c-tls

  2. 新しいファイルを開き、次の Pod 仕様を貼り付けます。
    apiVersion: v1
      kind: Pod
      metadata:
        labels:
        name: CASSANDRA_CLIENT_NAME   # For example: my-cassandra-client
        namespace: apigee
      spec:
        containers:
        - name: CASSANDRA_CLIENT_NAME
          image: "gcr.io/apigee-release/hybrid/apigee-hybrid-cassandra-client:1.11.1"
          imagePullPolicy: Always
          command:
          - sleep
          - "3600"
          env:
          - name: CASSANDRA_SEEDS
            value: apigee-cassandra-default.apigee.svc.cluster.local
          - name: APIGEE_DML_USERNAME_PATH
            value: /opt/apigee/externalsecrets/dmlUsername
          - name: APIGEE_DML_PASSWORD_PATH
            value: /opt/apigee/externalsecrets/dmlPassword
          volumeMounts:
          - mountPath: /opt/apigee/ssl
            name: tls-volume
            readOnly: true
          - name: apigee-external-secrets
            mountPath: /opt/apigee/externalsecrets
            readOnly: true
        volumes:
        - name: tls-volume
          secret:
            defaultMode: 420
            secretName: apigee-cassandra-user-setup-vaibhavhybridor-8b3e61d-tls
        - name: apigee-external-secrets
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: apigee-cass-password
        serviceAccount: apigee-cassandra-default
        serviceAccountName: apigee-cassandra-default
        restartPolicy: Never
  3. .yaml という拡張子を付けてファイルを保存します。例: my-spec.yaml
  4. クラスタに仕様を適用します。
    kubectl apply -f my-spec.yaml -n apigee
  5. コンテナにログインします。
    kubectl exec -n CASSANDRA_CLIENT_NAME -it -- bash
  6. 次のコマンドを使用して、Cassandra cqlsh インターフェースに接続します。次に示すようにコマンドを正確に入力します。
    APIGEE_DML_USER=$(cat "$APIGEE_DML_USERNAME_PATH")
    export APIGEE_DML_USER
    APIGEE_DML_PASSWORD=$(cat "$APIGEE_DML_PASSNAME_PATH")
    export APIGEE_DML_PASSWORD
    cqlsh ${CASSANDRA_SEEDS} -u ${APIGEE_DML_USER} -p ${APIGEE_DML_PASSWORD} --ssl

クライアント Pod の削除

次のコマンドを使用して、Cassandra クライアント Pod を削除します。

kubectl delete pods -n apigee cassandra-client