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

简介: 【微服务安全】使用 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

相关文章
|
6月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
6月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
1086 2
Spring Boot 3.x 微服务架构实战指南
|
7月前
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
416 1
消息中间件 Java Kafka
531 0
|
7月前
|
数据可视化 Java BI
将 Spring 微服务与 BI 工具集成:最佳实践
本文探讨了 Spring 微服务与商业智能(BI)工具集成的潜力与实践。随着微服务架构和数据分析需求的增长,Spring Boot 和 Spring Cloud 提供了构建可扩展、弹性服务的框架,而 BI 工具则增强了数据可视化与实时分析能力。文章介绍了 Spring 微服务的核心概念、BI 工具在企业中的作用,并深入分析了两者集成带来的优势,如实时数据处理、个性化报告、数据聚合与安全保障。同时,文中还总结了集成过程中的最佳实践,包括事件驱动架构、集中配置管理、数据安全控制、模块化设计与持续优化策略,旨在帮助企业构建高效、智能的数据驱动系统。
356 1
将 Spring 微服务与 BI 工具集成:最佳实践
|
7月前
|
存储 安全 Java
管理 Spring 微服务中的分布式会话
在微服务架构中,管理分布式会话是确保用户体验一致性和系统可扩展性的关键挑战。本文探讨了在 Spring 框架下实现分布式会话管理的多种方法,包括集中式会话存储和客户端会话存储(如 Cookie),并分析了它们的优缺点。同时,文章还涵盖了与分布式会话相关的安全考虑,如数据加密、令牌验证、安全 Cookie 政策以及服务间身份验证。此外,文中强调了分布式会话在提升系统可扩展性、增强可用性、实现数据一致性及优化资源利用方面的显著优势。通过合理选择会话管理策略,结合 Spring 提供的强大工具,开发人员可以在保证系统鲁棒性的同时,提供无缝的用户体验。
149 0
|
7月前
|
消息中间件 Java 数据库
Spring 微服务中的数据一致性:最终一致性与强一致性
本文探讨了在Spring微服务中实现数据一致性的策略,重点分析了最终一致性和强一致性的定义、优缺点及适用场景。结合Spring Boot与Spring Cloud框架,介绍了如何根据业务需求选择合适的一致性模型,并提供了实现建议,帮助开发者在分布式系统中确保数据的可靠性与同步性。
457 0
|
消息中间件 存储 缓存
kafka 的数据是放在磁盘上还是内存上,为什么速度会快?
Kafka的数据存储机制通过将数据同时写入磁盘和内存,确保高吞吐量与持久性。其日志文件按主题和分区组织,使用预写日志(WAL)保证数据持久性,并借助操作系统的页缓存加速读取。Kafka采用顺序I/O、零拷贝技术和批量处理优化性能,支持分区分段以实现并行处理。示例代码展示了如何使用KafkaProducer发送消息。
|
消息中间件 存储 运维
为什么说Kafka还不是完美的实时数据通道
【10月更文挑战第19天】Kafka 虽然作为数据通道被广泛应用,但在实时性、数据一致性、性能及管理方面存在局限。数据延迟受消息堆积和分区再平衡影响;数据一致性难以达到恰好一次;性能瓶颈在于网络和磁盘I/O;管理复杂性涉及集群配置与版本升级。
575 1
|
消息中间件 Java Kafka
Flink-04 Flink Java 3分钟上手 FlinkKafkaConsumer消费Kafka数据 进行计算SingleOutputStreamOperatorDataStreamSource
Flink-04 Flink Java 3分钟上手 FlinkKafkaConsumer消费Kafka数据 进行计算SingleOutputStreamOperatorDataStreamSource
459 1