【微服务安全】使用 Spring Boot、Kafka、Vault 和 Kubernetes 保护微服务间通信——第 3 部分:设置 Vault

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 【微服务安全】使用 Spring Boot、Kafka、Vault 和 Kubernetes 保护微服务间通信——第 3 部分:设置 Vault
  • 第 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

网络异常,图片无法展示
|

保险库 Kubernetes 服务

 

  • 运行以下命令以获取服务列表

> kubectl get svc

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

网络异常,图片无法展示
|

 

初始化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)。您可能会看到一个对话框,您需要在其中接受自签名证书。单击确定。

网络异常,图片无法展示
|

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

网络异常,图片无法展示
|

  • 然后,点击启用新引擎

网络异常,图片无法展示
|

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

网络异常,图片无法展示
|

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

网络异常,图片无法展示
|

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

网络异常,图片无法展示
|

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

网络异常,图片无法展示
|

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

网络异常,图片无法展示
|

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

网络异常,图片无法展示
|

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

管理访问权限和策略

 

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

网络异常,图片无法展示
|

  • 在名称中,输入 my-encrypt-policy。在策略中放入下面的代码。这将允许此策略仅加密以下数据。完成后,单击“创建策略”:

path "transit/decrypt/my-encryption-key" {

 capabilities = [ "update" ]

}

网络异常,图片无法展示
|

  • 再次单击策略 > 创建 ACL 策略。在 Name 中输入“my-encrypy-policy”,在 Policy 中输入下面的代码。然后点击“创建策略”

path "transit/encrypt/my-encryption-key" {

 capabilities = [ "update" ]

}

网络异常,图片无法展示
|

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

网络异常,图片无法展示
|

  • 然后启动你的命令行控制台并运行下面的 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,我们看到正面和负面的测试用例都通过了。最后,我们创建了一个用于加密和解密功能的令牌。


Tags

本文:https://architect.pub/secure-inter-micro-service-communication-spring-boot-kafka-vault-and-kubernetes-part-3-setting

相关文章
|
21天前
|
Kubernetes 开发者 Docker
构建高效微服务架构:Docker与Kubernetes的协同
在当今快速迭代和部署应用程序的背景下,微服务架构已成为企业开发的首选模式。此文章通过深入分析Docker容器化技术和Kubernetes集群管理工具,探讨了如何利用这两者协同工作以构建和维护一个高效的微服务系统。我们将剖析Docker和Kubernetes的核心原理,并展示它们如何简化部署流程、提高系统的可伸缩性和可靠性。本文旨在为开发者提供一套实践指南,帮助其在云原生时代下,构建出既灵活又强大的后端服务。
|
21天前
|
消息中间件 监控 API
在Python中如何实现微服务架构,及相关的服务间通信方案?
Python微服务架构涉及服务划分、注册发现、通信协议选择(如HTTP、gRPC、消息队列)及服务间通信实现。每个服务应自治,有独立数据库和部署流程,并需考虑容错(如分布式事务、重试、熔断)和监控日志。API网关用于请求管理和路由。实际操作需根据需求和技术栈调整,并关注服务拆分和数据一致性。
43 5
|
6天前
|
Kubernetes 开发者 Docker
构建高效微服务架构:Docker与Kubernetes的协同应用
【5月更文挑战第30天】 在当今软件开发领域,微服务架构已成为实现系统模块化、提升可维护性及扩展性的关键策略。本文深入探讨了如何通过Docker容器化技术和Kubernetes集群管理,共同构建一个既高效又可靠的后端微服务环境。我们将剖析Docker和Kubernetes的核心功能,以及它们如何相辅相成,支撑起现代化的云原生应用程序部署和管理。文章还将提供具体实践案例,帮助开发者理解将理论应用于实际开发过程中的步骤和考虑因素。
|
5天前
|
Kubernetes Cloud Native 开发者
构建高效云原生应用:Kubernetes与微服务架构的融合
【5月更文挑战第31天】 在数字化转型和技术迭代的大潮中,企业对于敏捷、可扩展的IT基础设施需求日益增长。云原生技术以其独特的优势成为推动这一进程的关键力量。本文深入探讨了如何通过结合Kubernetes容器编排和微服务架构来构建和维护高效、可靠的云原生应用。我们将剖析这种技术整合的必要性,揭示其背后的原理,并讨论在实际部署过程中可能遇到的挑战及解决方案。通过案例分析和最佳实践的分享,旨在为开发者和架构师提供一套行之有效的云原生应用构建指南。
|
8天前
|
Kubernetes Cloud Native PHP
构建高效云原生应用:基于Kubernetes的微服务治理实践深入理解PHP中的命名空间
【5月更文挑战第28天】 在当今数字化转型的浪潮中,云原生技术以其独特的弹性、可扩展性和敏捷性成为了企业IT架构的重要选择。本文深入探讨了如何在云平台之上,利用Kubernetes这一容器编排工具,实现微服务架构的有效治理。通过分析微服务设计原则与Kubernetes特性的融合,提出了一套系统的微服务部署、监控和管理策略。文章不仅阐述了关键技术点,还提供了具体实施步骤和最佳实践,以期帮助企业构建出既高效又稳定的云原生应用。 【5月更文挑战第28天】在PHP的编程世界中,命名空间是管理代码和避免名称冲突的强大工具。本文将探讨PHP命名空间的核心概念、实现方式及其在现代PHP开发中的应用。通过深
|
8天前
|
Kubernetes 持续交付 Docker
构建高效微服务架构:Docker与Kubernetes的完美结合
【5月更文挑战第28天】在现代软件开发中,微服务架构已成为提高系统可维护性和扩展性的关键。本文深入探讨了如何利用Docker容器化技术和Kubernetes集群管理工具共同打造一个高效、可靠的微服务环境。通过分析两者的核心优势及互补特性,我们展示了一种优化的部署策略,旨在帮助开发者和系统管理员理解和实践在复杂分布式系统中实现服务的有效管理和自动化部署。
|
19天前
|
Kubernetes 持续交付 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【5月更文挑战第17天】在当今云计算和微服务架构的大潮中,Docker容器化技术和Kubernetes容器编排系统成为了后端开发领域的热门技术栈。本文将探讨如何通过Docker和Kubernetes的结合使用来构建一个高效、可扩展且易于管理的微服务环境。我们将从基础概念出发,深入到实际操作层面,最后讨论这种组合对持续集成和持续部署(CI/CD)流程的影响,旨在为开发者和企业提供一种可靠的后端服务解决方案。
|
21天前
|
Kubernetes Cloud Native 持续交付
构建高效云原生应用:Kubernetes与微服务架构的融合
【5月更文挑战第6天】 在数字化转型的浪潮中,企业正迅速采纳云原生技术以实现敏捷性、可扩展性和弹性。本文深入探讨了如何利用Kubernetes这一领先的容器编排平台,结合微服务架构,构建和维护高效、可伸缩的云原生应用。通过分析现代软件设计原则和最佳实践,我们提出了一个综合指南,旨在帮助开发者和系统架构师优化云资源配置,提高部署流程的自动化水平,并确保系统的高可用性。
37 1
|
21天前
|
Kubernetes 监控 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【5月更文挑战第4天】在现代软件开发中,微服务架构已成为实现可扩展、灵活且独立部署服务的流行解决方案。本文将探讨如何利用Docker容器化技术和Kubernetes容器编排平台来构建一个高效的微服务系统。我们将分析Docker和Kubernetes的核心优势,并指导读者如何通过这些工具优化微服务部署、管理和扩展过程。文章还将涉及监控和日志管理策略,以确保系统的健壮性和可靠性。
|
21天前
|
Kubernetes 监控 Docker