跳转到主要内容
Chinese, Simplified
  • 第 1 部分:简介和架构
  • 第 2 部分:设置 Kubernetes 和 Kafka
  • 第 3 部分:设置 Vault <--本文
  • 第 4 部分:构建微服务
  • 第 5 部分:部署和测试


设置Vault

 

  • 如果我们回想一下我们的架构,我们说过我们将提供端到端加密。虽然 Vault 将保护我们的信息,但谁在保护 Vault? - 为此,我们将使用经典的 TLS 连接 (HTTPS) 来保护我们与 Vault 的通信。我们将为此创建一个自签名证书。

使用 TLS 安装

 

> openssl version

 

  • 如果你有 openssl,你应该得到下面的响应(或类似的)。如果您没有 OpenSSL,请从此处 [https://www.openssl.org/] 下载并安装
LibreSSL 2.6.5

 

  • 接下来,运行以下命令为我们的设置设置环境变量
> SERVICE=vault
> NAMESPACE=default
> SECRET_NAME=vault-server-tls
> TMPDIR=/tmp


SERVICE:包含 Vault 的服务名称

NAMESPACE:运行 Vault 的 Kubernetes 命名空间

SECRET_NAME:包含 TLS 证书的 Kubernetes 密钥

TMPDIR:临时工作目录

  • 然后,创建一个用于签名的密钥
> openssl genrsa -out ${TMPDIR}/vault.key 2048

 

  • 我们现在将创建一个证书签名请求 (CSR)。首先,让我们创建一个 CSR 配置文件:
> cat <<EOF >${TMPDIR}/csr.conf
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${SERVICE}
DNS.2 = ${SERVICE}.${NAMESPACE}
DNS.3 = ${SERVICE}.${NAMESPACE}.svc
DNS.4 = ${SERVICE}.${NAMESPACE}.svc.cluster.local
IP.1 = 127.0.0.1
EOF

 

  • 然后,我们将创建 CSR 文件本身
> openssl req -new -key ${TMPDIR}/vault.key -subj "/CN=${SERVICE}.${NAMESPACE}.svc" -out ${TMPDIR}/server.csr -config ${TMPDIR}/csr.conf

 

  • 现在,我们将创建实际的证书。从命令行运行
> export CSR_NAME=vault-csr

 

  • 然后我们将创建一个 csr.yaml 文件
> cat <<EOF >${TMPDIR}/csr.yaml
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: ${CSR_NAME}
spec:
  groups:
  - system:authenticated
  request: $(cat ${TMPDIR}/server.csr | base64 | tr -d '\n')
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF

 

  • 然后我们将在 Kubernetes 中创建一个证书签名请求
> kubectl create -f ${TMPDIR}/csr.yaml

 

  • 要验证是否创建了证书签名请求,请运行以下命令。
> kubectl get csr ${CSR_NAME}

 

  • 然后,批准 CSR。通过此命令,您已签署 CSR
> kubectl certificate approve ${CSR_NAME}

 

  • 之后,将证书导出到名为 vault.crt 的文件中
> serverCert=$(kubectl get csr ${CSR_NAME} -o jsonpath='{.status.certificate}')
> echo "${serverCert}" | openssl base64 -d -A -out ${TMPDIR}/vault.crt

 

  • 同时导出 Kubernetes CA
> kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}' | base64 -d > ${TMPDIR}/vault.ca

 

  • 创建一个秘密存储上面创建的所有文件
> kubectl create secret generic ${SECRET_NAME} --namespace ${NAMESPACE} --from-file=vault.key=${TMPDIR}/vault.key --from-file=vault.crt=${TMPDIR}/vault.crt --from-file=vault.ca=${TMPDIR}/vault.ca

 

  • 接下来,我们将在 $PROJECTS/k8s 文件夹中创建一个名为 custom-values.yaml 的文件。该文件的内容应为:
global:
  enabled: true
  tlsDisable: false
server:
  extraEnvironmentVars:
    VAULT_CACERT: /vault/userconfig/vault-server-tls/vault.ca
  extraVolumes:
    - type: secret
      name: vault-server-tls
  standalone:
    enabled: true
    config: |
      listener "tcp" {
        address = "[::]:8200"
        cluster_address = "[::]:8201"
        tls_cert_file = "/vault/userconfig/vault-server-tls/vault.crt"
        tls_key_file  = "/vault/userconfig/vault-server-tls/vault.key"
        tls_client_ca_file = "/vault/userconfig/vault-server-tls/vault.ca"
      }

      storage "file" {
        path = "/vault/data"
      }
  • 然后,我们将使用 Helm 安装通过我们的自签名 SSL 保护的独立 Vault。将命令行控制台指向文件夹 $PROJECTS/k8s 并运行:
> helm repo add hashicorp https://helm.releases.hashicorp.com
> helm install vault -f custom-values.yaml hashicorp/vault

 

  • 要验证 Vault 是否正在运行,请运行以下命令:
> kubectl get pods

 

  • 您应该在 pod 列表中看到 vault

No alt text provided for this image


保险库 Kubernetes 服务

 

  • 运行以下命令以获取服务列表
> kubectl get svc
  • 您应该看到下面的列表。Vault服务的名称是“Vault”。由于 Vault 在默认集群中运行,因此 Vault 服务(在 Kubernetes 内)的完全限定域名应该是 vault.default.svc。

No alt text provided for this image

 

初始化Vault

  • 要初始化 Vault,我们需要运行以下命令:
> kubectl exec -ti vault-0 -- vault operator init -format=json > cluster-keys.json

 

  • 这将创建一个包含 5 个键的 json 文件。 json 文件的内容可能如下所示:
{
  "keys": [
    "dea...94",
    "0c0...10",
    "800...29",
    "88e...1e",
    "5by...8z"
  ],
  "keys_base64": [
    "...",
    "...",
    "...",
    "...",
    "..."
  ],
  "root_token": "s.Tyu...d"
}


开封保险库

 

  • 初始化 Vault 时,它以密封模式运行。我们需要解封它才能使 Vault 有用。
  • 您还需要在每次重新启动时解封 Vault
  • 在上面的步骤(Initialize Vault)中,我们创建了一个包含 5 个密钥的子文件。我们需要提供 3 个密钥来解封 Vault。要解封,请运行以下命令:
> kubectl exec -ti vault-0 -- vault operator unseal 

 

  • 此命令将提示输入密钥。键入其中一个键并按回车键。
  • 您将得到以下结果:
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    5
Threshold       3
Version         1.5.2
Cluster Name    vault-cluster-e4b6a573
Cluster ID      80...b
HA Enabled      false

 

  • 每次使用不同的键重新运行以上命令 2 次
  • 祝贺。你有开封Vault。

暴露 Vault web ui

 

  • 接下来,我们将使用他之前在 Kafka 中使用的 port-forward 命令将 Vault 暴露给 Kubernetes 之外的世界。请注意,使用 Vault,我们通过端口转发而不是 pod 公开服务。
> kubectl port-forward service/vault 8200:8200

 

创建中转(transit )引擎

 

  • Vault Transit 引擎是 Vault 提供的一种加密即服务工具。我们将使用它来加密我们的消息。
  • 将浏览器指向地址 https://localhost:8200(注意它是 https)。您可能会看到一个对话框,您需要在其中接受自签名证书。单击确定。

No alt text provided for this image

  • 然后您将看到下面的页面。在 Token 字段中,键入刚才在初始化期间创建的 cluster-key.json 文件中的 root_token 值。

No alt text provided for this image

  • 然后,点击启用新引擎

No alt text provided for this image

  • 选择过境,然后点击下一步

No alt text provided for this image

  • 然后,在 Path 字段中输入“transit”,然后单击 Enable Engine

No alt text provided for this image

  • 您将获得您的秘密中列出的运输引擎

No alt text provided for this image

  • 在中转页面上,单击“创建加密密钥”

No alt text provided for this image

  • 在“创建加密密钥”页面中,在名称字段中输入 my-encryption-key,然后单击创建加密密钥

No alt text provided for this image

  • 您将看到已创建加密密钥

No alt text provided for this image

  • 祝贺。您创建了一个 Transit 引擎

管理访问权限和策略

 

  • 单击菜单策略。然后单击“创建 ACL 策略”

No alt text provided for this image

  • 在名称中,输入 my-encrypt-policy。在策略中放入下面的代码。这将允许此策略仅加密以下数据。完成后,单击“创建策略”:
path "transit/decrypt/my-encryption-key" {
  capabilities = [ "update" ]
}


No alt text provided for this image

  • 再次单击策略 > 创建 ACL 策略。在 Name 中输入“my-encrypy-policy”,在 Policy 中输入下面的代码。然后点击“创建策略”
path "transit/encrypt/my-encryption-key" {
  capabilities = [ "update" ]
}


No alt text provided for this image

  • 您现在应该设置 2 个策略:

No alt text provided for this image

  • 然后启动你的命令行控制台并运行下面的 curl 命令。请注意,下面的值 s.Tyu…d 是从上面的文件 cluster-keys.json 获得的根令牌的值。我们创建的策略 my-encrypt-policy 的值也在下面指定。 (我们在 curl 命令上使用选项 -k 因为我们使用的证书是自签名的。没有 -k,curl 命令将抱怨我们的证书)
> curl --header "X-Vault-Token: s.Tyu...d" --request POST --data '{"policies": ["my-encrypt-policy"]}' -k https://localhost:8200/v1/auth/token/create

 

  • 你应该得到下面的回应。请注意客户端令牌的 values.O1...k。让我们称之为加密令牌
{
   "request_id":"d5b47829-53f0-a35e-4b7c-0e9d8f4f3cbc",
   "lease_id":"",
   "renewable":false,
   "lease_duration":0,
   "data":null,
   "wrap_info":null,
   "warnings":null,
   "auth":{
      "client_token":"s.O1sI3QhVvSmbG1lyfKSMXXFk",
      "accessor":"T...8",
      "policies":[
         "default",
         "my-encrypt-policy"
      ],
      "token_policies":[
         "default",
         "my-encrypt-policy"
      ],
      "metadata":null,
      "lease_duration":2764800,
      "renewable":true,
      "entity_id":"",
      "token_type":"service",
      "orphan":false
   }
}

 

  • 让我们重复相同的 curl 命令,这一次,我们将使用 my-decrypt-policy 策略
curl --header "X-Vault-Token: s.WuTNTDpBqsspinc6dlDN0cbz" --request POST --data '{"policies": ["my-decrypt-policy"]}' -k https://localhost:8200/v1/auth/token/create

 

  • 我们应该看到下面的结果。注意客户端令牌(s.7x…Xv)。我们将此令牌称为解密器令牌
{
   "request_id":"d5b47829-53f0-a35e-4b7c-0e9d8f4f3cbc",
   "lease_id":"",
   "renewable":false,
   "lease_duration":0,
   "data":null,
   "wrap_info":null,
   "warnings":null,
   "auth":{
      "client_token":"s.7xdIhRPcJXFw2B1s6fKasHXv",
      "accessor":"TSNoAMVNwFEUzlmx8tjRh9w8",
      "policies":[
         "default",
         "my-encrypt-policy"
      ],
      "token_policies":[
         "default",
         "my-encrypt-policy"
      ],
      "metadata":null,
      "lease_duration":2764800,
      "renewable":true,
      "entity_id":"",
      "token_type":"service",
      "orphan":false
   }


测试 Vault 的加密即服务

 

  • 因此,让我们测试一下我们的设置。首先,我们需要一个 base-64 字符串。打开命令行控制台并运行以下命令。这会将字符串编码为 base-64。当然,您可以使用“Hello world”以外的其他语言。
> echo -n 'Hello world'|openssl base64

 

  • 你会得到
SGVsbG8gd29ybGQ=

 

  • 让我们使用加密器令牌加密该字符串。
> curl --header "X-Vault-Token: s.O1sI3QhVvSmbG1lyfKSMXXFk" --request POST --data '{"plaintext": "SGVsbG8gd29ybGQ="}' -k https://127.0.0.1:8200/v1/transit/encrypt/my-encryption-key

 

  • 您将收到以下回复。加密数据在字段密文中。
{
   "request_id":"c345db50-2517-90de-cc8c-f66812b27d6b",
   "lease_id":"",
   "renewable":false,
   "lease_duration":0,
   "data":{
      "ciphertext":"vault:v1:+VZG+5sZA0AQworFh5+o/kTyri6I+ooKWjfwbVOtB+lY/AWRurhO",
      "key_version":1
   },
   "wrap_info":null,
   "warnings":null,
 }

 

  • 现在,让我们尝试使用解密器令牌进行解密。请注意,字段密文包含上面的加密数据
curl --header "X-Vault-Token: s.7xdIhRPcJXFw2B1s6fKasHXv" --request POST --data '{"ciphertext":"vault:v1:+VZG+5sZA0AQworFh5+o/kTyri6I+ooKWjfwbVOtB+lY/AWRurhO"}' -k https://127.0.0.1:8200/v1/transit/decrypt/my-encryption-key

 

  • 然后你会得到下面的回复。请注意,我们取回了我们之前加密的 base 64 字符串。
{
   "request_id":"7d00a316-90ff-9c94-3e6f-d8e60b0560e3",
   "lease_id":"",
   "renewable":false,
   "lease_duration":0,
   "data":{
      "plaintext":"SGVsbG8gd29ybGQ="
   },
   "wrap_info":null,
   "warnings":null,
   "auth":null
}

 

  • 现在,让我们尝试一个否定的测试用例。让我们尝试加密数据,但改用解密器令牌
> curl --header "X-Vault-Token: s.7xdIhRPcJXFw2B1s6fKasHXv" --request POST --data '{"plaintext": "SGVsbG8gd29ybGQ="}' -k https://127.0.0.1:8200/v1/transit/encrypt/my-encryption-key

 

  • 您最终会遇到错误
{"errors":["1 error occurred:\n\t* permission denied\n\n"]}

 

  • 您可以尝试相反,尝试使用加密令牌进行解密
> curl --header "X-Vault-Token: s.O1sI3QhVvSmbG1lyfKSMXXFk" --request POST --data '{"ciphertext":"vault:v1:+VZG+5sZA0AQworFh5+o/kTyri6I+ooKWjfwbVOtB+lY/AWRurhO"}' -k https://127.0.0.1:8200/v1/transit/decrypt/my-encryption-key


您最终将遇到与上述相同的错误

{"errors":["1 error occurred:\n\t* permission denied\n\n"]}


为加密和解密创建令牌

 

  • 回想一下我们的架构,其中 Transaction Services 和 DepositAccount Service 都需要消费和发送消息。这意味着他们需要加密和解密功能。要创建具有这两个功能的令牌,只需指定两个策略:
curl --header "X-Vault-Token: s.WuTNTDpBqsspinc6dlDN0cbz" --request POST --data '{"policies": ["my-decrypt-policy", "my-encrypt-policy"]}' -k https://localhost:8200/v1/auth/token/create

 

  • 您将收到以下回复。您可以使用“client_token”安全地登录到 Vault 以获得加密和解密功能:
{
  "request_id": "a1f0fc87-5c27-94e3-b043-29adc5c87557",
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": null,
  "wrap_info": null,
  "warnings": null,
  "auth": {
    "client_token": "s.WuTNTDpBqsspinc6dlDN0cbz",
    "accessor": "Qc...dU",
    "policies": [
      "default",
      "my-decrypt-policy",
      "my-encrypt-policy"
    ],
    "token_policies": [
      "default",
      "my-decrypt-policy",
      "my-encrypt-policy"
    ],
    "metadata": null,
    "lease_duration": 2764800,
    "renewable": true,
    "entity_id": "",
    "token_type": "service",
    "orphan": false
  }
}


Vault的结论


我们终于在我们的 Kubernetes 集群中安装和设置了 Vault(独立设置)。我们已经激活了加密即服务引擎,并创建了两个具有两种不同功能的不同令牌。加密器令牌用于加密数据,解密器令牌用于解密数据。我们还使用令牌测试了引擎的 API,我们看到正面和负面的测试用例都通过了。最后,我们创建了一个用于加密和解密功能的令牌。

原文地址
https://www.linkedin.com/pulse/secure-inter-micro-service-communication-spring-boot-kafka-madisa-2c/
Article
知识星球
 
微信公众号
 
视频号