Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Prerequisites

These instructions require the following tools on the local machine:

  • Kubernetes command-line interface (CLI)

  • Helm CLI

The kubectl context should be set to the Kubernetes cluster where the HiveMQ broker will be installed.

\uD83D\uDCD8 Instructions

Install the Vault

...

git clone https://github.com/hashicorp-education/learn-vault-secrets-operator.git

...

cd learn-vault-secrets-operator

...

Helm Chart

  1. Add the HashiCorp Helm repository.

    Code Block
    languagebash
    $ helm repo add hashicorp https://helm.releases.hashicorp.com
  2. helm repo update hashicorp

  3. helm install vault hashicorp/vault -n vault --create-namespace --values vault/vault-values.yaml

  4. Convert the license and copy to the vault:
    
    "hashicorp" has been added to your repositories
  5. Update all the repositories to ensure helm is aware of the latest versions.

    Verify you have “root” token:
    Code Block
    languagebash
    cat hivemq.lic | base64 > hivemq.lic.b64
    kubectl cp hivemq.lic.b64 vault-0:/tmp/hivemq.lic.b64
  6. Attach to the Vault:

  7. kubectl exec --stdin=true --tty=true vault-0 -n vault -- /bin/sh

  8. Run in the vault:

  9. $ helm repo update
    Hang tight while we grab the latest from your chart repositories...
    ...Successfully got an update from the "hashicorp" chart repository
    Update Complete. ⎈Happy Helming!⎈
  10. Install the latest version of the Vault server running in development mode.

    Code Block
    languagebash
    $ helm install vault hashicorp/vault --set "server.dev.enabled=true"
    NAME: vault
    ## ...

    The Vault pod and Vault Agent Injector pod are deployed in the default namespace.

  11. Display all the pods in the default namespace.

    Code Block
    languagebash
    vault$ tokenkubectl lookupget #Key      pods
    NAME           Value #---                 ----- #accessor      READY   STATUS   ma6KC5nhNdTmANzeco0Evtdm #creation_timeRESTARTS   AGE
    vault-0   1707226849 #creation_ttl        0s #display_name        token #entity_id           n1/a1 #expire_time    Running   0  <nil> #explicit_max_ttl    0s #id  80s
    vault-agent-injector-5945fb98b5-tpglz   1/1     Running   0    root #issue_time          2024-02-06T13:40:49.967795042Z
    #meta                <nil>
    #num_uses            0
    #orphan              true
    #path       80s

    The vault-0 pod runs a Vault server in development mode. The vault-agent-injector pod performs the injection based on the annotations present or patched on a deployment.
    Development mode: Running a Vault server in development is automatically initialized and unsealed. This is ideal in a learning environment but NOT recommended for a production environment.

  12. Wait until the vault-0 pod and vault-agent-injector pod are running and ready (1/1).

Set a secret in Vault

  1. Copy the hivemq-license file to the vault-0 pod.

    Code Block
    languagebash
    $ kubectl cp hivemq.lic pod/vault-0:/tmp/
  2. Verify that the file is copied.

    Code Block
    languagebash
    $ kubectl exec -it vault-0 -- ls /tmp
  3. Start an interactive shell session on the vault-0 pod.

    Code Block
    languagebash
    $ kubectl exec -it vault-0 -- /bin/sh
    / $

    Your system prompt is replaced with a new prompt / $. Commands issued at this prompt are executed on the vault-0 container.

  4. Enable kv-v2 secrets at the path hivemq.

    Code Block
    languagebash
    $ vault secrets enable -path=hivemq kv-v2
    Success! Enabled the kv-v2 secrets engine at: hivemq/
  5. Create a secret at path hivemq/myenv/license with a hivemq_license_b64key and base64-encoded /tmp/hivemq.lic file.

    Code Block
    languagebash
    $ cd /tmp
    $ vault kv put hivemq/myenv/license hivemq_license_b64="$(base64 -w 0 hivemq.lic)"
    ====== Secret Path ======
    hivemq/data/myenv/license
    
    ======= Metadata =======
    Key         auth/token/create #policies      Value
    ---     [root] #renewable           false
    #ttl-----
    created_time       2024-02-21T17:34:39.261249639Z
    custom_metadata    <nil>
    deletion_time     0s #typen/a
    destroyed               service

    Enable secrets on the path:

    Code Block
    languagebash
    vault secrets enable -path=hivemq-mqtt/obc-poc/opt/hivemq/license kv-v2
    #Success! Enabled the kv-v2 secrets engine at: hivemq-mqtt/obc-poc/opt/hivemq/license/
    Put the content of the base64 encoded file to the vault secret at the path:
    false
    version            1
  6. Verify that the secret is defined at the path internal/database/config.

    Code Block
    languagebash
    $ vault kv putget hivemq-mqtt/obc-poc/opt/hivemq/license/hivemq.lic.b64 mydata="$(cat /tmp/hivemq.lic.b64)"
    #==========myenv/license
    ============== Secret Path =======================
    #hivemq-mqtt/obc-poc/opt/hivemq/license/data/hivemq.lic.b64
    #
    #hivemq/data/myenv/license
    
    ======= Metadata =======
    #KeyKey                Value
    #---                -----
    #createdcreated_time       2024-02-06T1721T14:2257:4401.720536373Z446984026Z
    #customcustom_metadata    <nil>
    #deletiondeletion_time      n/a
    #destroyeddestroyed          false
    #version
    version            1
    
    ========= Data =========
    Key               Value
    ---               -----
    hivemq_lic_b64 2   SCFNUSRbM10.......
    

    The secret is ready for the application.

  7. Lastly, exit the vault

    kv list hivemq-mqtt/obc-poc/opt/hivemq/license/ #Keys #---- #hivemq.lic.b64

    List vault secrets at the path:-0 pod.

    Code Block
    languagebash
    $ exit

Configure Kubernetes authentication

Vault provides a Kubernetes authentication method that enables clients to authenticate with a Kubernetes Service Account Token. This token is provided to each pod when it is created.

  1. Start an interactive shell session on the vault-0 pod.

    Code Block
    languagebash
    $ kubectl exec -it vault-0 -- /bin/sh
    / $

    Your system prompt is replaced with a new prompt / $. Commands issued at this prompt are executed on the vault-0 container.

  2. Enable the Kubernetes authentication method.

    Code Block
    languagebash
    $ vault auth enable kubernetes
    Success! Enabled kubernetes auth method at: kubernetes/

    Vault accepts a service token from any client in the Kubernetes cluster. During authentication, Vault verifies that the service account token is valid by querying a token review Kubernetes endpoint.

  3. Configure the Kubernetes authentication method to use the location of the Kubernetes API.

    Note: For the best compatibility with recent Kubernetes versions, ensure you are using Vault v1.13.3 or greater.

    Code Block
    languagebash
    $ vault write auth/kubernetes/config \
          kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443"

    Successful output from the command resembles this example:

    Code Block
    languagetext
    Success! Data written to: auth/kubernetes/config

    The environment variable KUBERNETES_PORT_443_TCP_ADDR is defined and references the internal network address of the Kubernetes host.

    For a client to read the secret data defined at hivemq/myenv/license, requires that the read capability be granted for the path hivemq/data/myenv/license. This is an example of a policy. A policy defines a set of capabilities.

  4. Write out the policy named hivemq that enables the read capability for secrets at path internal/data/database/config.

    Code Block
    languagebash
    $ vault kvpolicy listwrite hivemq-mqtt/obc-poc/opt/hivemq/license/
    #Keys
    #----
    #hivemq.lic.b64

    Exit from the vault container exit

  5. Consult-template.hcl file:

    View file
    nameconsul-template.hcl

  6. Edit the hivemq-operator/values.yaml and add the sidecar:

    yaml
    Code Block
    language
     - <<EOF
    path "internal/data/database/config" {
       capabilities = ["read"]
    }
    EOF
  7. Create a Kubernetes authentication role named hivemq.

    Code Block
    languagebash
    $ vault write auth/kubernetes/role/hivemq \
          bound_service_account_names=hivemq-hivemq-operator-hivemq \
          bound_service_account_namespaces=hivemq \
          policies=internal-app \
          ttl=24h

    Successful output from the command resembles this example:

    Code Block
    languagetext
    Success! Data written to: auth/kubernetes/role/hivemq

    The role connects the Kubernetes service account, hivemq-hivemq-operator-hivemq, and namespace, hivemq, with the Vault policy, hivemq. The tokens returned after authentication are valid for 24 hours.

  8. Lastly, exit the vault-0 pod.

    Code Block
    languagebash
    $ exit

Deploy a HiveMQ cluster

  1. If you already have a customized values.yaml, use it. If you do not have values.yaml file yet, get the values.yaml

    Code Block
    languagebash
    helm show values hivemq/hivemq-operator > values-hivemq.yaml
  2. Edit the values-hivemq.yaml file. Add annotations to the hivemq pods.

    Code Block
    hivemq:
      # CustomAnnotations container spec to add to the HiveMQ PodPods
      sidecarspodAnnotations:
        vault.hashicorp.com/agent- name: consul-template-container
    inject: "true"
        vault.hashicorp.com/role: "hivemq"
        vault.hashicorp.com/agent-inject-status: 'update'
         image: hashicorp/consul-template:latest
    vault.hashicorp.com/agent-inject-secret-hivemq-license: "hivemq/data/myenv/license"
        vault.hashicorp.com/agent-inject-template-hivemq-license: |
         command: [ "consul-template",  "-config", "/hivemq-data/conf/consul-template.hcl" ] {{- with secret \"hivemq/data/myenv/license\" -}}
          {{- $hivemq_broker_license #command: [ "consul-template",  "-version" ]
          env:
            - name: TARGET_ENV
              value: hivemq-mqtt/obc-poc
          volumeMounts::= base64Decode .Data.data.hivemq_lic_b64 -}}
          {{- $hivemq_broker_license -}}
          {{- end -}}
  3. (Re)install hivemq

    Code Block
    languagebash
    helm upgrade hivemq --install hivemq/hivemq-operator -n hivemq -f values-hivemq.yaml
  4. Get all the pods in the hivemq namespace.

    Code Block
    $ kubectl get pods -n hivemq
    NAME                                    READY   STATUS     RESTARTS   AGE
    hivemq-599cb74d9c-s8hhm                 0/2     Init:0/1   0         - name:23s
    consulhivemq-template-files69697d9598-l878s                mountPath: /hivemq-data/conf1/1     Running    0 # Custom init container specs to add to the HiveMQ Pod. This is an extension of the initialization field. In comparison, this field does not have any defaults but allows for more granular configuration using the full K8s Container API
      initContainers: []

    Edit the hivemq-operator/values.yaml and add the volume with consul-template.hcl

    Code Block
    languageyaml
    hivemq:
      # Additional volumes to add to the HiveMQ Pod
      additionalVolumes:
        - name: consul-template-files
          configMap:20m
    vault-0                                 1/1     Running    0          78m
    vault-agent-injector-5945fb98b5-tpglz   1/1     Running    0         name: consul-template-files
    Create the configMap with consul-template-files
     78m

    Wait until the re-deployed hivemq pod reports that it is Running and ready (2/2).

    This new pod now launches two containers. The application container, named hivemq, and the Vault Agent container, named vault-agent.

  5. Display the logs of the vault-agent container in the new orgchart pod.

    Code Block
    languagebash
    $ kubectl create configmap consul-template-files -n hivemq --from-file consul-template.hcl
  6. Install hivemq helm upgrade hivemq --install hivemq/hivemq-operator -n hivemq -f hivemq-operator/values.yam

  7. TODO: continue

...

  1. logs \
          $(kubectl get pod -l app=hivemq -o jsonpath="{.items[0].metadata.name}") \
          --container vault-agent

    Vault Agent manages the token lifecycle and the secret retrieval. The secret is rendered in the orgchart container at the path /vault/secrets/hivemq-license.

  2. Display the secret written to the hivemq container.

    Code Block
    languagebash
    $ kubectl exec \
          $(kubectl get pod -l app=hivemq -o jsonpath="{.items[0].metadata.name}") \
          --container hivemq -- cat /vault/secrets/hivemq-license

    The unformatted secret data is present on the container: TODO

...