Posted in

Vault auto-unseal Using Transit Secret on Kubernetes

Introduction

Sebelumnya kita sudah melakukan instalasi vault HA, hanya saja pods restart, maka harus melakukan unseal secara manual dan itu merupakan cara yang tidak efisien. Untuk autounseal sendiri ada beberapa macam cara untuk autounseal, yaitu dengan Clud KMS, vault transit, dan lain-lain.

Untuk pembahasan ini kita akan menggunakan Vault-transit untuk melakukan autounseal ketika vault utama kita ke-seal.

Concept

Vault transit akan menyimpan key dari production, kemudian vault production akan mengguakan vault-transit ketika ingin unseal

Configuration Vault-Transit

Pertama yang harus di deploy itu ada Vault transit, kita akan menggunakan 3 replicas (1 fault torelance) dan kita tidak akan menggunakan tls untuk transit (karena masih 1 cluster).

kita akan menggunakan values seperti dibawah ini

global:
  enabled: true
  tlsDisable: true

server:
  dataStorage:
    enabled: true
    size: 1Gi
    storageClass: default

  auditStorage:
    enabled: false

  standalone:
    enabled: false

  ha:
    enabled: true
    replicas: 3
    raft:
      enabled: true
      setNodeId: true
      config: |
        cluster_name = "vault-transit"
        ui = true

        listener "tcp" {
          address = "[::]:8200"
          cluster_address = "[::]:8201"
          tls_disable = 1
        }

        storage "raft" {
          path = "/vault/data"
        }

        disable_mlock = true
        service_registration "kubernetes" {}

apply values tersebut

helm install vault-transit -n vault -f values.yaml --version 0.32.0 hashicorp/vault

Setelah kita install, kita harus init vault-transit terlebih dahulu. Untuk init transit pada tutorial ini kita akan menggunakan 1 key saja, untuk mempermudah saja (rekomendasi lebih dari 1)

kubectl exec -n vault vault-transit-0 -- vault operator init -key-shares=1 -key-threshold=1

Kita akan mendapatkan 1 unseal key dan 1 root token, dan kita akan unseal vault-transit-0 terlebih dahulu

kubectl exec -n vault vault-transit-0 -- vault operator unseal <SEALTOKEN>

Sekarang untuk vault-transit-1, kita akan join cluster

kubectl exec -n vault vault-transit-1 -- vault operator raft join http://vault-transit.vault:8200

Sekarang kita unseal vault-transit-1

kubectl exec -n vault vault-transit-1 -- vault operator unseal <UNSEALTOKEN>

Sekarang kita join cluster untuk vault-transit-2

kubectl exec -n vault vault-transit-2 -- vault operator raft join http://vault-transit.vault:8200

Sekarang kita unseal vault-transit-2

kubectl exec -n vault vault-transit-2 -- vault operator unseal <UNSEALTOKEN>

Sekarang semua pod vault-transit sudah keunseal dan ketika kita check podsnya, running semua

kubectl get all -n vault

Kita akan membuat transit secret engine, pertama kita exec ke stateful vault-transit

kubectl exec -n vault -it sts/vault-transit -- sh

Kita login menggunakan root token yang sudah diinisiasi

vault login

Membuat transit secret

vault secrets enable transit
vault write -f transit/keys/autounseal

Membuat vault policy

echo '
path "transit/encrypt/autounseal" {
  capabilities = ["update"]
}

path "transit/decrypt/autounseal" {
  capabilities = ["update"]
}
' | vault policy write autounseal -

Membuat token untuk autounseal

vault token create -orphan -policy=autounseal -period=24h

Kita sudah mendapatkan token, kita save token tersebut nanti kita akan gunakan pada seal di vault production

Configuration Vault-Production

Jika kita sebelumnya sudah membuat vault tanpa unseal, maka kira harus re-init, untuk tutorial ini saya akan menggunakan fresh deployment.

Untuk vault-production, saya menggunakan TLS dan tahap instalasinya saya akan menggunakan instalasi pada tutorial sebelumnya https://cygnenoir.net/hashicorp-vault-ha-cluster-installation-on-kubernetes/

Sekarang perbedaannya menambahkan seal transit

        seal "transit" {
          address = "http://vault-transit.vault:8200"
          token = "PUTTOKENHERE" # INPUT TOKEN YANG SUDAH DIBUAT
          disable_renewal = "false"
          key_name = "autounseal"
          mount_path = "transit/"
          tls_skip_verify = "true"
        }

Untuk lengkap valuesnya dibawah ini

global:
  enabled: true
  tlsDisable: false
  resources:
    requests:
      memory: 256Mi
      cpu: 250m
    limits:
      memory: 256Mi
      cpu: 250m

server:
  resources:
    requests:
      memory: 2Gi
      cpu: 2000m
    limits:
      memory: 4Gi
      cpu: 4000m

  extraEnvironmentVars:
    VAULT_CACERT: /vault/userconfig/vault-ha-tls/vault.ca
    VAULT_TLSCERT: /vault/userconfig/vault-ha-tls/vault.crt
    VAULT_TLSKEY: /vault/userconfig/vault-ha-tls/vault.key

  volumes:
    - name: userconfig-vault-ha-tls
      secret:
        defaultMode: 420
        secretName: vault-ha-tls
  volumeMounts:
    - mountPath: /vault/userconfig/vault-ha-tls
      name: userconfig-vault-ha-tls
      readOnly: true

  dataStorage:
    enabled: true
    size: 10Gi
    storageClass: nfs-csi

  auditStorage:
    enabled: false

  standalone:
    enabled: false
    
  # Run Vault in "HA" mode.
  ha:
    enabled: true
    replicas: 3
    raft:
      enabled: true
      setNodeId: true
      config: |
        cluster_name = "vault-integrated-storage"
        ui = true
        listener "tcp" {
           tls_disable = 0
           address = "[::]:8200"
           cluster_address = "[::]:8201"
           tls_cert_file = "/vault/userconfig/vault-ha-tls/vault.crt"
           tls_key_file  = "/vault/userconfig/vault-ha-tls/vault.key"
           tls_client_ca_file = "/vault/userconfig/vault-ha-tls/vault.ca"
        }
        storage "raft" {
          path = "/vault/data"
        }
        disable_mlock = true
        service_registration "kubernetes" {}


        seal "transit" {
          address = "http://vault-transit.vault:8200"
          token = "PUTTOKENHERE"
          disable_renewal = "false"
          key_name = "autounseal"
          mount_path = "transit/"
          tls_skip_verify = "true"
        }

# Vault UI 
ui:
  enabled: true
  serviceType: "LoadBalancer"
  loadBalancerIP: "10.100.19.93"
  serviceNodePort: null
  externalPort: 8200

install vault production menggunakan values diatas

helm install vault -n vault -f values.yaml --version 0.32.0 hashicorp/vault

Setelah install, kita init vault production. Sebenarnya untuk init sama join cluster sama pada postingan sebelumnya https://cygnenoir.net/hashicorp-vault-ha-cluster-installation-on-kubernetes/

Jika sudah join semua, kita check status dari vault

kubectl exec -it -n vault vault-0 -- vault status

Diatas kita menggunakan seal type transit dan menggunakan Recovery Share untuk keynya, pada tahap ini sudah selesai kita membuat Vault-Transit dan Vault-Production. Sekarang kita check semua pods yang digunakan untuk vault

kubectl get all -n vault

Conclusion

Setelah saya testing vault autoseal menggunakan transit secret engine, berikut beberapa testing yang saya lakukan

  • Ketika vault-prod restart, maka vault tersbut akan autounseal
  • Ketika vault-transit ( 1 pods restart), maka vault tersebut harus unseal manual, untuk vault-prod dan vault-transit masih berjalan normal (karna pake 3 replicas)
  • Ketika vault-transit (2 pods restart), maka vault tersebut unseal manual, untuk vault-prod masih normal tetapi untuk vault-transit tidak normal karena fault tolerance hanya 1
  • Ketika vault-prod (1 pods restart) tetapi cluster vault-transit down, maka pods yang kerestart akan crashloopback karena dia akan mencari vault-transit, tetapi cluster vault-prod masih jalan karena menggunakan 3 pods
  • Ketika vault-prod (2 pods restart) tetapi cluster vault-transit down, maka pods yang kerestart akan crashloopback karena dia akan mencari vault-transit, dan juga cluster vault-prod down yang menjadikan vault tidak bisa digunakan

Vault cocok digunakan jika menggunakan HA dan mempunyai banyak fault tolerance, memang kita tetap masih menggunakan seal untuk melakukan unseal pada vault-transit. Jika cluster vault-transit down, vault-production tidak akan bisa up jika terjadi restart, tetapi tetap bejalan jika tidak ada restart sama sekali (karna menyimpan KEY di RAM)

Leave a Reply

Your email address will not be published. Required fields are marked *