Stocker des secrets Cassandra dans Hashicorp Vault

Stocker des secrets Cassandra dans Hashicorp Vault

Cette fonctionnalité vous permet de stocker les identifiants de base de données Cassandra pour Apigee hybrid dans Hashicorp Vault, un gestionnaire de secrets externe. Les gestionnaires de secrets externes vous permettent de gérer la façon dont les secrets sont stockés dans Kubernetes, y compris la gestion de la résidence des données et des contrôles d'accès précis.

Avant la version 1.10 d'Apigee hybrid, le seul moyen de fournir des mots de passe aux utilisateurs Cassandra était de spécifier le mot de passe dans le fichier overrides.yaml. Ces mots de passe sont stockés dans des secrets Kubernetes. Exemple :

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

Avec Hashicorp Vault, vous pouvez fournir ces mots de passe via l'API du pilote CSI Kubernetes Secrets Store (SecretProviderClass). Cela permet à Kubernetes d'installer plusieurs secrets, clés et certificats stockés dans un Vault externe.

Utilisateurs et mots de passe Cassandra

Vous devrez créer des secrets pour les utilisateurs Cassandra suivants. Modifiez les valeurs par défaut pour qu'elles respectent les règles de sécurité de votre organisation.

Utilisateur Cassandra Nom d'utilisateur par défaut Mot de passe par défaut
Admin admin_user "********"
LDD ddl_user "********"
Par défaut cassandra Remarque : Le nom d'utilisateur par défaut doit toujours être "cassandra". "********"
LMD dml_user "********"
JMX "jmxuser" "********"
Jolokia "apigee" "********"

Pour en savoir plus, consultez la section Propriété de configuration Cassandra.

Configurer l'intégration de secrets externes

La configuration de l'intégration de Vault pour Apigee hybrid comprend les procédures suivantes.

  • Dans les deux premières procédures, vous interagissez directement avec Vault.
  • Dans la troisième et la quatrième procédure, vous appliquez les configurations à votre cluster Kubernetes.

Suivez les procédures ci-dessous pour créer les secrets dans Vault et permettre à votre installation hybride d'y accéder.

Créer des secrets, des règles et des rôles Vault

  1. Vérifiez que le contexte Kubernetes actuel est défini sur votre cluster :
    kubectl config current-context
  2. Utilisez l'API, la CLI ou l'interface utilisateur Vault pour créer les secrets Cassandra. Les valeurs du secret que vous créez doivent correspondre aux noms d'utilisateur et aux mots de passe Cassandra actuellement utilisés dans votre cluster.
    • Clé secrète : toute clé secrète (ou combinaison de plusieurs clés) peut être utilisée, par exemple :
      secret/data/apigee/cassandra
    • Données secrètes : Apigee Hybrid attend des paires nom d'utilisateur et mot de passe pour les utilisateurs Cassandra suivants :
      Utilisateurs Cassandra
      Admin
      LDD
      Par défaut
      LMD
      JMX
      Jolokia
      Ces valeurs de nom d'utilisateur et de mot de passe peuvent être réparties sur un nombre illimité de clés secrètes.
    • CLI Vault : la commande suivante montre comment créer un seul secret contenant tous les noms d'utilisateurs et mots de passe requis :
      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"
      Les noms d'utilisateur par défaut de chaque utilisateur sont les suivants:
      Utilisateur Cassandra Valeur par défaut
      Admin admin_user
      LDD ddl_user
      Par défaut cassandra
      LMD dml_user
      JMX jmxuser
      Jolokia apigee
  3. Dans Vault, créez une règle pour accorder l'accès au secret que vous venez de créer.
    1. Créez un fichier de règles (nom suggéré : apigee-cassandra-auth.txt) avec le contenu suivant :
      path "secret/data/apigee/cassandra" {
        capabilities = ["read"]
      }
      Si vous avez créé plusieurs secrets, chaque secret doit être ajouté au fichier de règles :
      path "secret/data/apigee/cassandra/admin" {
        capabilities = ["read"]
      }
      
      path "secret/data/apigee/cassandra/ddl" {
        capabilities = ["read"]
      }
    2. Appliquez la règle à Vault :
      vault policy write apigee-cassandra-auth apigee-cassandra-auth.txt

      Vous pouvez créer la règle en utilisant l'entrée standard plutôt que de lire à partir d'un fichier :

      echo 'path "secret/data/apigee/cassandra" { capabilities = ["read"] }' | vault policy write apigee-cassandra-auth -
  4. Liez la règle aux comptes de service Kubernetes Apigee Cassandra.
    1. Définissez les variables d'environnement suivantes :
      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}

      Où :

      • ORG_NAME est le nom de votre organisation Apigee.
      • ENVS_LIST est une liste de vos environnements Apigee séparés par une virgule, par exemple dev,prod.
      • APIGEE_NAMESPACE est votre espace de noms Apigee. La valeur par défaut est apigee.
      • NAMESPACES est une liste d'espaces de noms séparés par une virgule pour Apigee, apigee-system et votre espace de noms Apigee.
    2. Créez un fichier avec le contenu suivant : Le script peut porter n'importe quel nom. Dans l'exemple suivant, le nom du script est 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. Exécutez le script et attribuez le résultat à la variable SERVICE_ACCOUNT_NAMES. Vous obtiendrez une liste de noms de comptes de service Kubernetes séparés par une virgule.
      export SERVICE_ACCOUNT_NAMES=$(./create-vault-cassandra-role)

      Vérifiez que la variable a bien été renseignée avec la liste :

      echo $SERVICE_ACCOUNT_NAMES
    4. Utilisez la CLI Vault pour créer un rôle qui lie la règle aux comptes de service 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

Installer le pilote CSI et le fournisseur Vault

Apigee hybrid v1.12.3 est compatible avec les versions de chart Helm suivantes:

Logiciels Version
Pilote CSI Secrets Store v1.3.4
Vault v0.25.0
  1. Suivez les instructions d'installation du pilote CSI Secrets Store pour installer le pilote CSI sur votre cluster. Le pilote CSI dispose d'un chart Helm pour l'installation.
  2. Suivez les instructions de la page Installer le fournisseur CSI Vault pour installer le fournisseur CSI Vault si ce n'est pas déjà fait.

Créer un objet SecretProviderClass

La ressource SecretProviderClass indique au pilote CSI avec quel fournisseur il doit communiquer lorsqu'il demande des secrets. Les identifiants des utilisateurs Cassandra doivent être configurés via cet objet. Le tableau suivant présente les noms de fichiers (objectName) attendus par Apigee Cassandra :

Utilisateur Cassandra Noms de fichiers de secrets attendus
Admin adminUsername, adminPassword
LDD ddlUsername, ddlPassword
Par défaut cassandra, defaultPassword
LMD dmlUsername, dmlPassword
JMX jmxUsername, jmxPassword
Jolokia jolokiaUsername, jolokiaPassword
  1. Créez un fichier YAML pour votre SecretProviderClass. Le nom du fichier peut être n'importe quel élément, par exemple : spc.yaml. Utilisez le modèle SecretProviderClass suivant pour configurer cette ressource :
    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. Appliquez SecretProviderClass à vos espaces de noms apigee et apigee-system. Dans les commandes suivantes, les espaces de noms sont apigee et apigee-system. Remplacez ces valeurs si vous utilisez différents espaces de noms :
    kubectl -n apigee apply -f spc.yaml
    kubectl -n apigee-system apply -f spc.yaml

Activer le secret externe pour Cassandra

  1. Dans votre overrides.yaml, ajoutez la configuration suivante pour activer l'utilisation des secrets externes pour Cassandra :
    cassandra:
      auth:
        secretProviderClass: apigee-cassandra-auth-spc  # The name of the SecretProviderClass created in spc.yaml.

    Consultez cassandra.auth.secretProviderClass.

  2. Utilisez helm upgrade pour appliquer la modification aux composants apigee-operator et apigee-datastore :
    • Le contrôleur de datastore dans apigee-operator participe à la mise hors service et à la réplication des données Cassandra lors de l'expansion de la région. Ces tâches nécessitent les identifiants JMX et Jolokia.
      helm upgrade operator apigee-operator/ \
        --namespace apigee-system \
        --atomic \
        -f overrides.yaml
    • apigee-datastore fournit des identifiants qui sont utilisés par les composants en aval tels que apigee-runtime, le synchronisateur et MART lors de la connexion à Cassandra.
      helm upgrade datastore apigee-datastore/ \
        --namespace apigee \
        --atomic \
        -f overrides.yaml
  3. Vérifiez que les secrets externes sont utilisés. Lorsque les secrets externes sont activés, de nouveaux Volume, Volume Mount et Environment Variable sont ajoutés pour faire référence aux secrets.
    • Vérifiez le déploiement apigee-controller-manager.

      Vérifiez qu'un objet Volume nommé apigee-external-secrets existe et fait référence à la ressource SecretProviderClass créée ci-dessus :

      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"
      }

      Vérifiez qu'un objet VolumeMount nommé apigee-external-secrets existe :

      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
      }

      Vérifiez qu'il existe des Environment Variable qui font référence aux secrets externes :

      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"
        }
      ]

Revenir au secret K8s

  1. Pour revenir aux secrets non externes, supprimez la configuration secretProviderClass dans overrides.yaml et utilisez la configuration précédente :
    cassandra:
          auth:
            secretProviderClass: apigee-cassandra-auth-spc # remove this line
  2. Utilisez helm upgrade pour appliquer la modification aux composants apigee-operator et 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

Dépannage : Créer un conteneur client pour le débogage

Si vous utilisez Vault, cette section remplace les instructions de la section de dépannage Créer un conteneur client pour le débogage.

Cette section explique comment créer un conteneur client à partir duquel vous pouvez accéder aux utilitaires de débogage Cassandra tels que cqlsh. Ces utilitaires vous permettent d'interroger les tables Cassandra et peuvent être utiles à des fins de débogage.

Créer le conteneur client

Pour créer le conteneur client, procédez comme suit :

  1. Le conteneur utilise le certificat TLS du pod apigee-cassandra-user-setup. La première étape consiste à extraire ce nom de certificat :
    kubectl get secrets -n apigee --field-selector type=kubernetes.io/tls | grep apigee-cassandra-user-setup | awk '{print $1}'

    Cette commande renvoie le nom du certificat. Exemple : apigee-cassandra-user-setup-rg-hybrid-b7d3b9c-tls.

  2. Ouvrez un nouveau fichier et collez-y la spécification de pod suivante :
    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.12.3"
          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. Enregistrez le fichier avec l'extension .yaml. Exemple : my-spec.yaml.
  4. Appliquez les spécifications à votre cluster comme suit :
    kubectl apply -f my-spec.yaml -n apigee
  5. Connectez-vous au conteneur :
    kubectl exec -n CASSANDRA_CLIENT_NAME -it -- bash
  6. Connectez-vous à l'interface Cassandra cqlsh à l'aide des commandes suivantes. Saisissez les commandes exactement comme indiqué ci-dessous :
    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

Supprimer le pod client

Utilisez la commande suivante pour supprimer le pod client Cassandra :

kubectl delete pods -n apigee cassandra-client