Armazenar segredos do Cassandra no Hashicorp Vault

Armazenar segredos do Cassandra no Hashicorp Vault

Esta funcionalidade permite-lhe armazenar credenciais da base de dados Cassandra para o Apigee Hybrid no Hashicorp Vault, um gestor de segredos externo. Os gestores de segredos externos permitem-lhe gerir a forma como os segredos são armazenados no Kubernetes, incluindo a gestão da residência de dados e os controlos de acesso detalhados.

Antes da versão 1.10 do Apigee Hybrid, a única forma de fornecer palavras-passe para utilizadores do Cassandra era especificar a palavra-passe em overrides.yaml. Estas palavras-passe são armazenadas em segredos do Kubernetes. Por exemplo:

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

Com o Hashicorp Vault, pode fornecer estas palavras-passe através da API Kubernetes Secrets Store CSI Driver (SecretProviderClass). Isto permite que o Kubernetes monte vários segredos, chaves e certificados armazenados num Vault externo.

Palavras-passe e utilizadores do Cassandra

Tem de criar segredos para os seguintes utilizadores do Cassandra. Altere os valores predefinidos para cumprir as políticas de segurança da sua organização.

Utilizador do Cassandra Nome de utilizador predefinido Palavra-passe predefinida
Administrador admin_user "********"
LDD ddl_user "********"
Predefinição cassandra Nota: o nome de utilizador predefinido tem de ser sempre "cassandra" "********"
DML dml_user "********"
JMX "jmxuser" "********"
Jolokia "apigee" "********"

Consulte a propriedade de configuração do Cassandra para mais informações.

Configure a integração de segredos externos

A configuração da integração do Vault para o Apigee Hybrid consiste nos seguintes procedimentos.

  • Nos dois primeiros procedimentos, interage diretamente com o Vault.
  • Nos procedimentos terceiro e quarto, aplica as configurações ao seu cluster do Kubernetes.

Use os procedimentos seguintes para criar os segredos no Vault e permitir que a sua instalação híbrida tenha acesso aos mesmos.

Crie segredos, políticas e funções do Vault

  1. Verifique se o contexto atual do Kubernetes está definido para o seu cluster:
    kubectl config current-context
  2. Use a API, a CLI ou a IU do Vault para criar os segredos do Cassandra. Os valores secretos que criar têm de corresponder aos nomes de utilizador e às palavras-passe do Cassandra atualmente usados no seu cluster.
    • Chave secreta: pode usar qualquer chave secreta (ou combinação de várias chaves). Por exemplo:
      secret/data/apigee/cassandra
    • Dados secretos: o Apigee Hybrid espera pares de nome de utilizador e palavra-passe para os seguintes utilizadores do Cassandra:
      Utilizadores do Cassandra
      Administrador
      LDD
      Predefinição
      DML
      JMX
      Jolokia
      Estes valores de nome de utilizador e palavra-passe podem ser distribuídos por qualquer número de chaves secretas.
    • CLI do Vault: o comando seguinte mostra como criar um único segredo que contenha todos os nomes de utilizador e palavras-passe necessários:
      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"
      Os nomes de utilizador predefinidos para cada utilizador são os seguintes:
      Utilizador do Cassandra Valor predefinido
      Administrador admin_user
      LDD ddl_user
      Predefinição cassandra
      DML dml_user
      JMX jmxuser
      Jolokia apigee
  3. No Vault, crie uma política para conceder acesso ao segredo que acabou de criar.
    1. Crie um ficheiro de política (nome sugerido: apigee-cassandra-auth.txt) com o seguinte conteúdo:
      path "secret/data/apigee/cassandra" {
        capabilities = ["read"]
      }
      Se criou vários segredos, cada segredo tem de ser adicionado ao ficheiro de política:
      path "secret/data/apigee/cassandra/admin" {
        capabilities = ["read"]
      }
      
      path "secret/data/apigee/cassandra/ddl" {
        capabilities = ["read"]
      }
    2. Aplique a política ao Vault:
      vault policy write apigee-cassandra-auth apigee-cassandra-auth.txt

      É possível criar a política através da entrada padrão em vez de ler a partir de um ficheiro:

      echo 'path "secret/data/apigee/cassandra" { capabilities = ["read"] }' | vault policy write apigee-cassandra-auth -
  4. Associe a política às contas de serviço do Kubernetes do Apigee Cassandra.
    1. Defina as seguintes variáveis de ambiente:
      export ORG_NAME=APIGEE_ORG_NAME
      export ENVS_LIST=LIST_OF_APIGEE-ENVS
      export APIGEE_NAMESPACE=YOUR_APIGEE_NAMESPACE

      Onde:

      • ORG_NAME é o nome da sua organização do Apigee.
      • ENVS_LIST É uma lista separada por vírgulas dos seus ambientes do Apigee, por exemplo dev,prod.
      • APIGEE_NAMESPACE é o seu espaço de nomes do Apigee. A predefinição é apigee.
    2. Crie um script com o seguinte conteúdo. O script pode ter qualquer nome. No exemplo seguinte, o nome do script é 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. Execute o script e atribua o resultado à variável SERVICE_ACCOUNT_NAMES. Isto cria uma lista de nomes de contas de serviço do Kubernetes separados por vírgulas.
      export SERVICE_ACCOUNT_NAMES=$(./create-vault-cassandra-role)

      Verifique se a variável foi preenchida com a lista:

      echo $SERVICE_ACCOUNT_NAMES
    4. Use a CLI do Vault para criar uma função que associe a política a contas de serviço do Kubernetes:
      vault write auth/kubernetes/role/cassandra \
          bound_service_account_names=${SERVICE_ACCOUNT_NAMES} \
          bound_service_account_namespaces=${APIGEE_NAMESPACE} \
          policies=apigee-cassandra-auth \
          ttl=1m

Instale o controlador CSI e o fornecedor do Vault

O Apigee hybrid v1.13.4 suporta as seguintes versões do gráfico Helm:

Software Versão
Controlador CSI da Secrets Store v1.4.4
Vault 1.17.2
  1. Siga as instruções de instalação do controlador CSI da Secrets Store para instalar o controlador CSI no seu cluster. O controlador CSI tem um gráfico Helm para instalação.
  2. Siga as instruções em Instalar o fornecedor CSI do Vault para instalar o fornecedor CSI do Vault, se ainda não o tiver instalado.

Crie um objeto SecretProviderClass

O recurso SecretProviderClass indica ao controlador CSI com que fornecedor deve comunicar quando pede segredos. As credenciais dos utilizadores do Cassandra têm de ser configuradas através deste objeto. A tabela seguinte mostra os nomes dos ficheiros (objectNames) esperados pelo Apigee Cassandra:

Utilizador do Cassandra Nomes de ficheiros secretos esperados
Administrador adminUsername, adminPassword
LDD ddlUsername, ddlPassword
Predefinição cassandra, defaultPassword
DML dmlUsername, dmlPassword
JMX jmxUsername, jmxPassword
Jolokia jolokiaUsername, jolokiaPassword
  1. Crie um ficheiro YAML para o seu SecretProviderClass. O nome do ficheiro pode ser qualquer coisa, por exemplo: spc.yaml. Use o seguinte modelo 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. Aplique o SecretProviderClass ao espaço de nomes apigee:
    kubectl -n $APIGEE_NAMESPACE apply -f spc.yaml

Ative o token secreto externo para o Cassandra

  1. No overrides.yaml, adicione a seguinte configuração para ativar a utilização de segredos externos para o Cassandra:
    cassandra:
      auth:
        secretProviderClass: apigee-cassandra-auth-spc  # The name of the SecretProviderClass created in spc.yaml.

    Consulte cassandra.auth.secretProviderClass.

  2. Use helm upgrade para aplicar a alteração aos componentes apigee-operator e apigee-datastore:
    • O controlador de armazenamento de dados no apigee-operator participa na desativação do Cassandra e na replicação de dados durante a expansão da região. Estas tarefas requerem as credenciais JMX e Jolokia.
      helm upgrade operator apigee-operator/ \
        --namespace $APIGEE_NAMESPACE \
        --atomic \
        -f overrides.yaml
    • apigee-datastore fornece credenciais que os componentes a jusante, como o apigee-runtime, o sincronizador e o MART, usam quando se ligam ao Cassandra.
      helm upgrade datastore apigee-datastore/ \
        --namespace $APIGEE_NAMESPACE \
        --atomic \
        -f overrides.yaml
  3. Verifique se estão a ser usados segredos externos. Quando os segredos externos estão ativados, são adicionados novos Volumes, Volume Mounts e Environment Variables, que fazem referência aos segredos.
    • Valide a implementação do apigee-controller-manager.

      Verifique se existe um Volume com o nome apigee-external-secrets e se faz referência ao SecretProviderClass criado acima:

      kubectl -n $APIGEE_NAMESPACE get deployment apigee-controller-manager -o jsonpath='{.spec.template.spec.volumes[?(@.name=="apigee-external-secrets")]}'

      Exemplo de resultado:

      {
        "csi": {
          "driver": "secrets-store.csi.k8s.io",
          "readOnly": true,
          "volumeAttributes": {
            "secretProviderClass": "apigee-cassandra-auth-spc"
          }
        },
        "name": "apigee-external-secrets"
      }

      Verifique se existe um VolumeMount com o nome apigee-external-secrets:

      kubectl -n $APIGEE_NAMESPACE get deployment apigee-controller-manager -o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].volumeMounts[?(@.name=="apigee-external-secrets")]}'

      Exemplo de resultado:

      {
        "mountPath": "/opt/apigee/externalsecrets",
        "name": "apigee-external-secrets",
        "readOnly": true
      }

      Verifique se existem Environment Variables que referenciam segredos externos:

      kubectl -n $APIGEE_NAMESPACE get deployment apigee-controller-manager -o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].env}'

      Exemplo de resultado:

      [
        ...
        {
          "name": "CASSANDRA_JOLOKIA_USERNAME_PATH",
          "value": "/opt/apigee/externalsecrets/jolokiaUsername"
        },
        {
          "name": "CASSANDRA_JOLOKIA_PASSWORD_PATH",
          "value": "/opt/apigee/externalsecrets/jolokiaPassword"
        }
      ]

Reverter para o segredo do K8s

  1. Para reverter para segredos não externos, remova a configuração secretProviderClass em overrides.yaml e use a configuração anterior:
    cassandra:
          auth:
            secretProviderClass: apigee-cassandra-auth-spc # remove this line
  2. Use helm upgrade para aplicar a alteração aos componentes apigee-operator e apigee-datastore:
    helm upgrade operator apigee-operator/ \
      --namespace $APIGEE_NAMESPACE \
      --atomic \
      -f overrides.yaml
    helm upgrade datastore apigee-datastore/ \
      --namespace $APIGEE_NAMESPACE \
      --atomic \
      -f overrides.yaml

Resolução de problemas: crie um contentor de cliente para depuração

Se estiver a usar o Vault, esta secção substitui as instruções na secção de resolução de problemas, Crie um contentor de cliente para depuração.

Esta secção explica como criar um contentor de cliente a partir do qual pode aceder às utilidades de depuração do Cassandra como cqlsh. Estas utilidades permitem-lhe consultar tabelas do Cassandra e podem ser úteis para fins de depuração.

Crie o contentor de cliente

Para criar o contentor de cliente, siga estes passos:

  1. O contentor usa o certificado TLS do pod apigee-cassandra-user-setup. O primeiro passo é obter o nome deste certificado:
    kubectl get secrets -n APIGEE_NAMESPACE --field-selector type=kubernetes.io/tls | grep apigee-cassandra-user-setup | awk '{print $1}'

    Este comando devolve o nome do certificado. Por exemplo: apigee-cassandra-user-setup-rg-hybrid-b7d3b9c-tls.

  2. Abra um novo ficheiro e cole a seguinte especificação do pod no mesmo:
    apiVersion: v1
      kind: Pod
      metadata:
        labels:
        name: CASSANDRA_CLIENT_NAME   # For example: my-cassandra-client
        namespace: $APIGEE_NAMESPACE
      spec:
        containers:
        - name: CASSANDRA_CLIENT_NAME
          image: "gcr.io/apigee-release/hybrid/apigee-hybrid-cassandra-client:1.13.4"
          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. Guarde o ficheiro com a extensão .yaml. Por exemplo: my-spec.yaml.
  4. Aplique a especificação ao seu cluster:
    kubectl apply -f my-spec.yaml -n $APIGEE_NAMESPACE
  5. Inicie sessão no contentor:
    kubectl exec -n CASSANDRA_CLIENT_NAME -it -- bash
  6. Estabeleça ligação à interface do Cassandra cqlsh com os seguintes comandos. Introduza os comandos exatamente como são apresentados:
    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

Eliminar o pod do cliente

Use este comando para eliminar o pod do cliente Cassandra:

kubectl delete pods -n $APIGEE_NAMESPACE cassandra-client