Almacena secrets de Cassandra en Hashicorp Vault

Almacena secrets de Cassandra en Hashicorp Vault

Esta función te permite almacenar credenciales de la base de datos de Cassandra para Apigee Hybrid en Hashicorp Vault, un Secret Manager externo. Los Secret Manager externos te permiten administrar cómo se almacenan los objetos Secret en Kubernetes, incluida la administración de la residencia de datos y los controles de acceso detallados.

Antes de la versión 1.10 de Apigee Hybrid, la única forma de proporcionar contraseñas para los usuarios de Cassandra era especificar la contraseña en overrides.yaml. Estas contraseñas se almacenan en secrets de Kubernetes. Por ejemplo:

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

Con Hashicorp Vault, puedes proporcionar estas contraseñas a través de la API de Kubernetes Secrets Store CSI Driver (SecretProviderClass). Esto permite que Kubernetes active varios secrets, claves y certificados almacenados en un Vault externo.

Usuarios y contraseñas de Cassandra

Deberás crear secrets para los siguientes usuarios de Cassandra. Cambia los valores predeterminados para cumplir con las políticas de seguridad de tu organización.

Usuario de Cassandra Nombre de usuario predeterminado Contraseña predeterminada
Administrador admin_user "********"
DDL ddl_user "********"
Predeterminado cassandra Nota: El nombre de usuario predeterminado siempre debe ser “Cassandra”. "********"
DML dml_user "********"
JMX "jmxuser" "********"
Jolokia "apigee" "********"

Consulta la propiedad de configuración de Cassandra para obtener más información.

Configura la integración de un secret externo

La configuración de la integración de Vault para Apigee Hybrid consta de los siguientes procedimientos.

  • En los dos primeros procedimientos, interactúas de forma directa con Vault.
  • En el tercer y cuarto procedimiento, aplicas la configuración a tu clúster de Kubernetes.

Usa los siguientes procedimientos para crear los secrets en Vault y permitir que tu instalación híbrida tenga acceso a ellos.

Crea políticas, secrets y roles de Vault

  1. Verifica que el contexto actual de Kubernetes esté configurado en tu clúster:
    kubectl config current-context
  2. Usa la API, la CLI o la IU de Vault para crear los secrets de Cassandra. Los valores secrets que crees deben coincidir con los nombres de usuario y las contraseñas de Cassandra que se usan en la actualidad en tu clúster.
    • Clave secreta: Se puede usar cualquier clave secreta (o combinación de varias claves), por ejemplo:
      secret/data/apigee/cassandra
    • Datos secrets: Apigee Hybrid espera pares de nombre de usuario y contraseña para los siguientes usuarios de Cassandra:
      Usuarios de Cassandra
      Administrador
      DDL
      Predeterminado
      DML
      JMX
      Jolokia
      Estos valores de nombre de usuario y contraseña se pueden distribuir en cualquier cantidad de claves secretas.
    • CLI de Vault: El siguiente comando muestra cómo crear un solo secret que contenga todos los nombres de usuario y contraseñas necesarios:
      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"
      Los nombres de usuario predeterminados para cada usuario son los siguientes:
      Usuario de Cassandra Valor predeterminado
      Administrador admin_user
      DDL ddl_user
      Predeterminado cassandra
      DML dml_user
      JMX jmxuser
      Jolokia apigee
  3. En Vault, crea una política para otorgar acceso al secret que acabas de crear.
    1. Crea un archivo de texto apigee-cassandra-auth.txt (nombre sugerido) con el siguiente contenido:
      path "secret/data/apigee/cassandra" {
        capabilities = ["read"]
      }
      Si creaste varios Secrets, cada uno debe agregarse al archivo de políticas:
      path "secret/data/apigee/cassandra/admin" {
        capabilities = ["read"]
      }
      
      path "secret/data/apigee/cassandra/ddl" {
        capabilities = ["read"]
      }
    2. Aplica la política a Vault:
      vault policy write apigee-cassandra-auth apigee-cassandra-auth.txt

      Es posible crear la política con una entrada estándar en lugar de leer desde un archivo:

      echo 'path "secret/data/apigee/cassandra" { capabilities = ["read"] }' | vault policy write apigee-cassandra-auth -
  4. Vincula la política a las cuentas de servicio de Kubernetes de Apigee Cassandra.
    1. Define las siguientes variables de entorno:
      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}

      Donde:

      • ORG_NAME es el nombre de tu organización de Apigee.
      • ENVS_LIST es una lista separada por comas de tus entornos de Apigee, por ejemplo, dev,prod.
      • APIGEE_NAMESPACE es el espacio de nombres de Apigee. El valor predeterminado es apigee.
      • NAMESPACES es una lista de espacios de nombres separados por comas para Apigee, apigee-system y tu espacio de nombres de Apigee.
    2. Crea una secuencia de comandos con el siguiente contenido: La secuencia de comandos puede tener cualquier nombre. En el siguiente ejemplo, el nombre de la secuencia de comandos es 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. Ejecuta la secuencia de comandos y asigna el resultado a la variable SERVICE_ACCOUNT_NAMES. Esto creará una lista separada por comas de los nombres de cuentas de servicio de Kubernetes.
      export SERVICE_ACCOUNT_NAMES=$(./create-vault-cassandra-role)

      Verifica que la variable se haya propagado con la lista:

      echo $SERVICE_ACCOUNT_NAMES
    4. Usa la CLI de Vault para crear una función que vincule la política a las cuentas de servicio de 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

Instala el controlador CSI y el proveedor de Vault

Apigee Hybrid v1.12.3 admite las siguientes versiones de gráficos de Helm:

Software Versión
Controlador de CSI del almacén de secrets v1.3.4
Vault v0.25.0
  1. Sigue las instrucciones de instalación del controlador de CSI del almacén de secrets para instalar el controlador de CSI en tu clúster. El controlador de CSI tiene un gráfico de Helm para la instalación.
  2. Sigue las instrucciones en Instala el proveedor de CSI de Vault para instalar el proveedor de CSI de Vault si aún no lo instalaste.

Crea un objeto SecretProviderClass

El recurso SecretProviderClass le indica al controlador de CSI con qué proveedor se debe comunicar cuando solicita secrets. Las credenciales de los usuarios de Cassandra deben configurarse a través de este objeto. En la siguiente tabla, se muestran los nombres de archivos (objectName) que espera Apigee Cassandra:

Usuario de Cassandra Nombres de archivos de secrets esperados
Administrador adminUsername, adminPassword
DDL ddlUsername, ddlPassword
Predeterminado cassandra, defaultPassword
DML dmlUsername, dmlPassword
JMX jmxUsername, jmxPassword
Jolokia jolokiaUsername, jolokiaPassword
  1. Crea un archivo YAML para tu SecretProviderClass. El nombre del archivo puede ser cualquier elemento, por ejemplo: spc.yaml. Usa la siguiente plantilla de SecretProviderClass para configurar este recurso:
    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. Aplica SecretProviderClass a tus espacios de nombres apigee y apigee-system. En los siguientes comandos, los espacios de nombres son apigee y apigee-system. Reemplaza esos valores si usas espacios de nombres diferentes:
    kubectl -n apigee apply -f spc.yaml
    kubectl -n apigee-system apply -f spc.yaml

Habilita el secret externo para Cassandra

  1. En tu overrides.yaml, agrega la siguiente configuración para habilitar el uso de secrets externos para Cassandra:
    cassandra:
      auth:
        secretProviderClass: apigee-cassandra-auth-spc  # The name of the SecretProviderClass created in spc.yaml.

    Consulta cassandra.auth.secretProviderClass.

  2. Usa helm upgrade para aplicar el cambio a los componentes apigee-operator y apigee-datastore:
    • El controlador del almacén de datos en apigee-operator participa en el retiro de servicio de Cassandra y la replicación de datos durante la expansión regional. Estas tareas requieren las credenciales de JMX y Jolokia.
      helm upgrade operator apigee-operator/ \
        --namespace apigee-system \
        --atomic \
        -f overrides.yaml
    • apigee-datastore proporciona credenciales que los componentes descendentes, como apigee-runtime, Synchronizer y MART usan cuando se conectan a Cassandra.
      helm upgrade datastore apigee-datastore/ \
        --namespace apigee \
        --atomic \
        -f overrides.yaml
  3. Verifica que se usen secrets externos. Cuando se habilitan secrets externos, se agregan nuevos Volume, Volume Mount y Environment Variable, que hacen referencia a los secrets.
    • Verifica la implementación de apigee-controller-manager.

      Comprueba que exista un Volume llamado apigee-external-secrets que haga referencia a la SecretProviderClass creada antes:

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

      Comprueba que exista una VolumeMount llamada apigee-external-secrets:

      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
      }

      Verifica que existan Environment Variable que hagan referencia a secrets externos:

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

Revierte al Secret K8s

  1. Para volver a los secrets no externos, quita la configuración secretProviderClass en overrides.yaml y usa la configuración anterior:
    cassandra:
          auth:
            secretProviderClass: apigee-cassandra-auth-spc # remove this line
  2. Usa helm upgrade para aplicar el cambio a los componentes apigee-operator y 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

Solución de problemas: Crea un contenedor del cliente para depurar

Si usas Vault, esta sección reemplaza las instrucciones de la sección de solución de problemas, Crea un contenedor de cliente para la depuración.

En esta sección, se explica cómo crear un contenedor de cliente desde el que puedes acceder a las utilidades de depuración de Cassandra, como cqlsh. Estas utilidades te permiten consultar tablas de Cassandra y pueden ser útiles para fines de depuración.

Crea el contenedor del cliente

Para crear el contenedor del cliente, sigue estos pasos:

  1. El contenedor usa el certificado TLS del Pod apigee-cassandra-user-setup. El primer paso es recuperar este nombre de certificado:
    kubectl get secrets -n apigee --field-selector type=kubernetes.io/tls | grep apigee-cassandra-user-setup | awk '{print $1}'

    Este comando muestra el nombre del certificado. Por ejemplo: apigee-cassandra-user-setup-rg-hybrid-b7d3b9c-tls.

  2. Abre un archivo nuevo y pega en él las siguientes especificaciones del 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.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. Guarda el archivo con una extensión .yaml. Por ejemplo: my-spec.yaml
  4. Aplica las especificaciones a tu clúster:
    kubectl apply -f my-spec.yaml -n apigee
  5. Accede al contenedor:
    kubectl exec -n CASSANDRA_CLIENT_NAME -it -- bash
  6. Conéctate a la interfaz cqlsh de Cassandra con los siguientes comandos. Ingresa los comandos con exactitud como se muestra:
    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

Borra el pod del cliente

Usa este comando para borrar el Pod de cliente de Cassandra:

kubectl delete pods -n apigee cassandra-client