【微服务安全】使用 Spring Boot、Kafka、Vault 和 Kubernetes 保护微服务间通信——第 4 部分:构建微服务
Chinese, Simplified
- 第 1 部分:简介和架构
- 第 2 部分:设置 Kubernetes 和 Kafka
- 第 3 部分:设置保险柜
- Part 4: 构建微服务 <--本文
- 第 5 部分:部署和测试
创建微服务
- 我们将创建 2 个微服务:Transaction 和 DepositAccount。我们将为此使用 JHipster。
- 首先,我们需要安装 JHipster。请按照此处的教程安装 JHipster [https://www.jhipster.tech/installation/]
准备信任库(truststore)
- 如果您从 Java 程序调用自签名受保护端点(例如本教程中的 Vault),则需要首先信任自签名证书
- 通常这是通过将自签名证书注册到 JVM 的信任库中来完成的。
- 我们将面临的问题是:当我们创建 docker 镜像并在其中运行我们的微服务时,我们不会使用我们机器的 JVM。我们将改为使用图像的 JVM。我们如何将我们的证书注册到镜像的 JVM 信任库中?
- 当我们进入本教程的部署部分时,我们将解决这个问题。同时,让我们将 Vault 的根证书注册到信任库中。请记住证书 TMPDIR/vault.crt。我们将使用此证书。
- 我们需要找到 JVM cacerts 在哪里。在 Mac 机器上,它位于文件夹中的某个位置:$(/usr/libexec/java_home)/lib/security.你可以参考这个关于堆栈溢出的讨论:https://stackoverflow.com/questions/11936685/how-to-obtain-the-location…
- 运行以下命令。当提示输入密码时,请指定插入符号密码。默认情况下是 changeit
> sudo keytool -import -file "/tmp/vault.crt" -keystore "$(/usr/libexec/java_home)/lib/security/cacerts" -alias "vault certificate"
- 您可能需要更改生产环境的 cacerts 密码
- 我们现在已经将 Vault 的证书注册为可信证书。
设置 JHipster 注册表
- 将 JHipster Registry https://www.jhipster.tech/jhipster-registry/ 下载为 jar 文件并放入 $PROJECTS/Registry 文件夹
- 创建另一个文件夹:$PROJECTS/Registry/central-config。在 central-config 中,创建一个名为 application.yml 的文件并在下面插入内容。请确保将 my-secret-key-which-should-be-changed-in-production-and-be-base64-encoded 替换为您自己的生产机密:
# =================================================================== # JHipster Sample Spring Cloud Config. # =================================================================== # Property used on app startup to check the config server status configserver: name: JHipster Registry config server status: Connected to the JHipster Registry config server! # Default JWT secret token (to be changed in production!) jhipster: security: authentication: jwt: # It is recommended to encrypt the secret key in Base64, using the `base64-secret` property. # For compabitibily issues with applications generated with older JHipster releases, # we use the non Base64-encoded `secret` property here. secret: my-secret-key-which-should-be-changed-in-production-and-be-base64-encoded # The `base64-secret` property is recommended if you use JHipster v5.3.0+ # (you can type `echo 'secret-key'|base64` on your command line) # base64-secret: bXktc2VjcmV0LWtleS13aGljaC1zaG91bGQtYmUtY2hhbmdlZC1pbi1wcm9kdWN0aW9uLWFuZC1iZS1iYXNlNjQtZW5jb2RlZAo= # Enable /management/logfile endpoint for all apps logging: path: /tmp file: ${spring.application.name}.log
- 您已成功设置 JHipster Registry
设置 API 网关
启动命令行控制台并将其指向 $PROJECTS/GatewayKafka 文件夹。跑:
> jhipster
将提出一系列问题。回答他们如下。请注意,当被问及您还想使用哪些其他技术?不要选择 Kafka。我们将单独处理 Kafka,而不是通过 JHipster:
? Which *type* of application would you like to create? Microservice gateway ? [Beta] Do you want to make it reactive with Spring WebFlux? No ? What is the base name of your application? GatewayKafka ? As you are running in a microservice architecture, on which port would like yo ur server to run? It should be unique to avoid port conflicts. 8080 ? What is your default Java package name? com.azrul.ebanking.gatewaykafka ? Which service discovery server do you want to use? JHipster Registry (uses Eur eka, provides Spring Cloud Config support and monitoring dashboards) ? Which *type* of authentication would you like to use? JWT authentication (stat eless, with a token) ? Which *type* of database would you like to use? SQL (H2, MySQL, MariaDB, Postg reSQL, Oracle, MSSQL) ? Which *production* database would you like to use? PostgreSQL ? Which *development* database would you like to use? H2 with disk-based persist ence ? Do you want to use the Spring cache abstraction? No - Warning, when using an S QL database, this will disable the Hibernate 2nd level cache! ? Do you want to use Hibernate 2nd level cache? No ? Would you like to use Maven or Gradle for building the backend? Maven ? Which other technologies would you like to use? ? Which *Framework* would you like to use for the client? Angular ? Would you like to use a Bootswatch theme (https://bootswatch.com/)? Default JH ipster ? Would you like to enable internationalization support? No ? Besides JUnit and Jest, which testing frameworks would you like to use? ? Would you like to install other generators from the JHipster Marketplace? (y/N ) No
- 您现在已成功设置 API 网关
设置交易微服务
启动命令行控制台并将其指向 $PROJECTS/Transaction 文件夹。跑:
> jhipster
将提出一系列问题。回答他们如下。请注意,当被问及您还想使用哪些其他技术时?不要选择卡夫卡。我们将单独处理 Kafka,而不是通过 JHipster:
? Which *type* of application would you like to create? Microservice application ? [Beta] Do you want to make it reactive with Spring WebFlux? No ? What is the base name of your application? Transaction ? As you are running in a microservice architecture, on which port would like yo ur server to run? It should be unique to avoid port conflicts. 8081 ? What is your default Java package name? com.azrul.ebanking.transaction ? Which service discovery server do you want to use? JHipster Registry (uses Eur eka, provides Spring Cloud Config support and monitoring dashboards) ? Which *type* of authentication would you like to use? JWT authentication (stat eless, with a token) ? Which *type* of database would you like to use? SQL (H2, MySQL, MariaDB, Postg reSQL, Oracle, MSSQL) ? Which *production* database would you like to use? PostgreSQL ? Which *development* database would you like to use? H2 with disk-based persist ence ? Do you want to use the Spring cache abstraction? No - Warning, when using an S QL database, this will disable the Hibernate 2nd level cache! ? Would you like to use Maven or Gradle for building the backend? Maven ? Which other technologies would you like to use? ? Would you like to enable internationalization support? No ? Besides JUnit and Jest, which testing frameworks would you like to use? ? Would you like to install other generators from the JHipster Marketplace? No
指定对 Kafka 和 Vault 的依赖关系
- 首先,让我们处理依赖关系。在文件 $PROJECTS/Transaction/pom.xml 中,在 <dependencies> </dependencies> 标记中添加以下依赖项。
<dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>2.4.8.RELEASE</version> </dependency> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> <version>2.4.1</version> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka_2.13</artifactId> <version>2.4.1</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-vault-config</artifactId> <version>2.2.5.RELEASE</version> </dependency>
- 在同一个 pom.xml 文件下,我们还需要在 <dependencyManagement><dependencies> ... </dependencies></dependencyManagement> 下添加一个条目
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency>
需要 spring-cloud-starter-vault-config 和 spring-cloud-dependencies 以允许 Vault 集成
编写事务微服务
- 让我们创建一种将数据从发布者传输到消费者并再次返回的方法。为此,我们在名为 com.azrul.ebanking.common.dto 的包中创建了一个“数据传输对象”(DTO)。这将是生产者和消费者的通用包。在那里,让我们按照下面的方式创建一个 Transaction 类。请注意,为了使 Transaction 类可序列化,它必须实现 Serializable 接口,必须有一个默认构造函数,toString 和 equals 方法:
- [完整来源:https://raw.githubusercontent.com/azrulhasni/Ebanking-JHipster-Kafka-Va…]
- 在 com.azrul.ebanking.transaction.config 包下创建一个名为 KafkaConfig 的配置类
- [完整来源:https://raw.githubusercontent.com/azrulhasni/Ebanking-JHipster-Kafka-Va…]
- Kafka配置
- Spring 使用 spring-kafka 库对 Kafka 提供了广泛的支持。这包括序列化器和反序列化器 - 这将使消息传递类型安全。另一方面,我们不会使用这些序列化器/反序列化器,因为我们将在消息到达我们自己的 Kafka 之前对其进行加密。我们将选择一个基本的字符串序列化器/反序列化器。
- 这是我们将用来连接到 Kafka 的 KafkaTemplate。请注意,我们使用的是一种特殊的 KafkaTemplate,称为 ReplyingKafkaTemplate。这个类将允许我们发送请求并获得响应,而无需我们自己做太多的管道
- 我们还需要一个配置文件。在 $PROJECTS/Transaction/src/main/resources/config 文件夹下,在 application.yml 文件中添加:
kafka: bootstrap-servers: kafka-headless.default.svc.cluster.local:9092 deposit-debit-request-topic: deposit-debit-request deposit-debit-response-topic: deposit-debit-response consumer: group.id: transaction auto.offset.reset: earliest producer:
- 在 $PROJECTS/Transaction/src/main/resources/config 文件夹下,在文件 bootstrap.yml 中,在 spring.cloud 下添加以下属性。
- 在方案中,确保我们把 https
- 在主机中,确保我们放置自己的 Vault Kubernetes 服务的完全限定域名。回想上面的 Vault Kubernetes Service 段落
- 在连接超时和读取超时中,设置一个合理的超时时间。我们放了一个大的进行测试。放一个小的(比如几秒钟)用于生产
- 在认证中,输入TOKEN,表示我们将通过安全令牌登录
- 在令牌中,确保您在之前的“为加密和解密创建令牌”段落中输入了 client_token 值。
vault: scheme: https host: vault.default.svc port: 8200 connection-timeout: 3600000 read-timeout: 3600000 authentication: TOKEN token: s.WuTNTDpBqsspinc6dlDN0cbz kv: enabled=true:
- 接下来,在 com.azrul.ebanking.transaction.web.rest 包中,创建一个名为 TransactionKafkaResource 的控制器
- [完整来源:https://raw.githubusercontent.com/azrulhasni/Ebanking-JHipster-Kafka-Va…]
- 让我们分解这段代码:
- 首先,我们需要获取请求和响应主题。回想一下我们的架构。另外,我们还在我们的KafkaTemplate中进行了wire,方便我们调用Kafka
- 我们还在 VaultTemplate 中进行接线以方便我们调用 Vault
- 这是我们将收到一个宁静的电话的地方。我们将加密该调用中的数据,创建 ProducerRecord 并将消息发送到 deposit-debit-request 主题。然后,我们将等待来自 deposit-debit-response 主题的回复。回复将包含我们得到的余额。一旦我们有了这些数据,我们就会解密它并返回给调用者。
- 这是我们加密数据的地方。最初,我们的数据是对象(Transaction 类型)的形式。然后我们将其转换为一系列字节。然后将一系列字节转换为 Base64 字符串。接下来,我们使用 Vault Transit 引擎加密 Base64 字符串。
- 这是我们解密数据的地方。最初,我们会得到一个加密的 Base64 字符串。我们需要使用 Vault Transit 引擎解密这个字符串。这将产生一个解密的 Base64 字符串。接下来,我们将 Base64 解密后的字符串解码为一系列字节。最后,我们将一系列字节转换回一个对象。
使用 Transaction 微服务的自签名证书处理 SSL
- 请回想一下我们关于从微服务调用自签名保护端点的困难的讨论(准备信任库段落)。我们将利用 Jib 来帮助我们解决这个问题并部署到 Kubernetes。
- 如果您注意到,JHipster 创建的文件夹之一称为 Jib ($PROJECTS/Transaction/src/main/jib)。此文件夹中的任何内容都将复制到根级别的 Docker 映像。
- 例如。如果我们有 $PROJECTS/Transaction/src/main/jib/myfolder/myfile.txt,当我们创建 Docker 镜像时,Jib 会将 myfolder 和 myfile.txt 复制到 Docker 镜像中。这会在图像中创建 /myfolder/myfile.txt
- 我们将创建一个名为 truststore 的文件夹,并在其中复制我们的主机/本地信任库(cacerts)。这会将 cacerts 复制到 /truststore/cacerts 的映像中。回想一下,我们可以找到信任库作为 JDK 的一部分。请在此处查看堆栈溢出讨论:https://stackoverflow.com/questions/11936685/how-to-obtain-the-location…
- 接下来,我们需要告诉 Java 使用 /truststore/cacerts 中的 cacerts。在我们的 TransactionApp.java 文件的 main 方法中,添加以下行。确保我们使用正确的 cacerts 密码(默认为 changeit):
System.setProperty("javax.net.ssl.trustStore","/truststore/cacerts"); System.setProperty("javax.net.ssl.trustStorePassword","changeit");
设置 DepositAccount 微服务
启动命令行控制台并将其指向 $PROJECTS/DepositAccount 文件夹。跑:
> jhipster
将提出一系列问题。回答他们如下。请注意,当被问及您还想使用哪些其他技术时?不要选择卡夫卡。我们将单独处理 Kafka,而不是通过 JHipster:
? Which *type* of application would you like to create? Microservice application ? [Beta] Do you want to make it reactive with Spring WebFlux? No ? What is the base name of your application? DepositAccount ? As you are running in a microservice architecture, on which port would like yo ur server to run? It should be unique to avoid port conflicts. 8082 ? What is your default Java package name? com.azrul.ebanking.depositaccount ? Which service discovery server do you want to use? JHipster Registry (uses Eur eka, provides Spring Cloud Config support and monitoring dashboards) ? Which *type* of authentication would you like to use? JWT authentication (stat eless, with a token) ? Which *type* of database would you like to use? SQL (H2, MySQL, MariaDB, Postg reSQL, Oracle, MSSQL) ? Which *production* database would you like to use? PostgreSQL ? Which *development* database would you like to use? H2 with disk-based persist ence ? Do you want to use the Spring cache abstraction? No - Warning, when using an S QL database, this will disable the Hibernate 2nd level cache! ? Would you like to use Maven or Gradle for building the backend? Maven ? Which other technologies would you like to use? ? Would you like to enable internationalization support? No ? Besides JUnit and Jest, which testing frameworks would you like to use? ? Would you like to install other generators from the JHipster Marketplace? (y/N ) No
指定对 Kafka 和 Vault 的依赖关系
- DepositAccount 微服务的依赖与 Transaction 微服务相同。无论如何,我们将在这里重复以完成目的
- 首先,让我们处理依赖关系。在文件 $PROJECTS/DepositAccount/pom.xml 中,在 <dependencies> </dependencies> 标记中添加以下依赖项。
<dependency> <groupId>org.springframework.kafka</groupId> <artifactId>spring-kafka</artifactId> <version>2.4.8.RELEASE</version> </dependency> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> <version>2.4.1</version> <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka_2.13</artifactId> <version>2.4.1</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-vault-config</artifactId> <version>2.2.5.RELEASE</version> </dependency>
- 在同一个 pom.xml 文件下,我们还需要在 <dependencyManagement><dependencies> ... </dependencies>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency>
- 需要 spring-cloud-starter-vault-config 和 spring-cloud-dependencies 以允许 Vault 集成
为 DespositAccount 创建数据模型和存储库
- 我们现在将为 DepositAccount 创建一个数据模型。
- 在文件夹 $PROJECTS/DepositAccount/ 中创建一个名为 banking.jh 的文件。在那里,将数据模型放在下面
entity DepositAccount{ accountNumber String, productId String, openingDate ZonedDateTime, status Integer, balance BigDecimal } // Set service options to all except few service all with serviceClass
- // 将服务选项设置为除少数之外的所有选项
使用 serviceClass 服务所有
然后,启动命令行控制台并将其指向文件夹 $PROJECTS/DepositAccount。 运行以下命令:
> jhipster import-jdl ./banking.jh
这将创建诸如 DepositAccountService 等可用于查询和保存存款账户数据的类。
编码 DespositAccount 微服务
- 首先,我们需要与事务微服务相同的 DTO
- 创建名为 com.azrul.ebanking.common.dto 的包,并在其中创建一个名为 Transaction 的类。回想一下,Transaction 类需要实现 Serialisable 接口,需要有一个默认构造函数,并且需要有 equals、hashCode 和 toString 方法:
- [完整源代码:https://raw.githubusercontent.com/azrulhasni/Ebanking-JHipster-Kafka-Va…]
- 然后我们将处理配置。 DepositAccount 微服务的配置与 Transaction 微服务相同。 无论如何,为了完成目的,我们将在这里重复一遍。 下面是 KafkaConfig 类
- 卡夫卡配置
- Spring 使用 spring-kafka 库对 Kafka 提供了广泛的支持。这包括序列化器和反序列化器 - 这将使消息传递类型安全。另一方面,我们不会使用这些序列化器/反序列化器,因为我们将在消息到达我们自己的 Kafka 之前对其进行加密。我们将选择一个基本的字符串序列化器/反序列化器。
- 这是我们将用来连接到 Kafka 的 KafkaTemplate。请注意,我们使用的是一种特殊的 KafkaTemplate,称为 ReplyingKafkaTemplate。这个类将允许我们发送请求并获得响应,而无需我们自己做太多的管道
- 我们还需要一个配置文件。在 $PROJECTS/DepositAccount/src/main/resources/config 文件夹下,在 application.yml 文件中添加:
kafka: bootstrap-servers: kafka-headless.default.svc.cluster.local:9092 deposit-debit-request-topic: deposit-debit-request deposit-debit-response-topic: deposit-debit-response consumer: group.id: transaction auto.offset.reset: earliest producer:
- 在 $PROJECTS/DepositAccount/src/main/resources/config 文件夹下,在文件 bootstrap.yml 中,在 spring.cloud 下添加以下属性。
- 在方案中,确保我们把 https
- 在主机中,确保我们放置自己的 Vault Kubernetes 服务的完全限定域名。回想上面的 Vault Kubernetes Service 段落
- 在连接超时和读取超时中,设置一个合理的超时时间。我们放了一个大的进行测试。放一个小的(比如几秒钟)用于生产
- 在认证中,输入TOKEN,表示我们将通过安全令牌登录
- 在令牌中,确保您在之前的“为加密和解密创建令牌”段落中输入了 client_token 值。
vault: scheme: https host: vault.default.svc port: 8200 connection-timeout: 3600000 read-timeout: 3600000 authentication: TOKEN token: s.WuTNTDpBqsspinc6dlDN0cbz kv: enabled=true:
- 接下来我们将创建一个监听器。在 com.azrul.ebanking.depositaccount.service 包中,创建一个名为 Transfer 的类,如下所示:
- [完整源代码:https://github.com/azrulhasni/Ebanking-JHipster-Kafka-Vault/blob/master…]
- 注入 VaultTemplate 允许我们解密进来的数据并加密返回的数据。
- 注入 DespositAccountService 让我们可以查询和保存存款账户数据
- 这是真正的听众。我们将通过输入参数从请求主题中获取我们的加密数据。我们十继续将这些数据解密到 Transaction 对象中。该对象将告诉我们要借记的源账户、要贷记的目标账户和金额。我们将继续执行该交易并计算借方和贷方账户中的结果余额。然后,我们将借记帐户余额放回消息中,并使用此编辑对象回复发布者。
- 该方法与 Transaction 微服务中的方法相同,用于加密和对象
- 该方法与 Transaction 微服务中的方法相同,用于解密和对象
使用 DepositAccount 微服务的自签名证书处理 SSL
- 就像事务微服务一样,我们需要在这里做同样的事情
- 我们将复制 cacerts(回想一下关于 stackoverflow 上关于 cacerts 在您的系统堆栈溢出中可用位置的讨论:https://stackoverflow.com/questions/11936685/how-to-obtain-the-location…- the-default-java-installation) 到 $PROJECTS/DepositAccounts/src/main/jib/truststore
- 然后,我们需要通过添加以下代码来修改 main 方法(在文件 $PROJECTS/DepositAccounts/src/main/java/com/azrul/ebanking/depositaccount/DepositAccountApp.java 中):
System.setProperty("javax.net.ssl.trustStore","/truststore/cacerts"); System.setProperty("javax.net.ssl.trustStorePassword","changeit");
- [完整源代码:https://raw.githubusercontent.com/azrulhasni/Ebanking-JHipster-Kafka-Va…]
- 在下一部分中,我们将看到如何部署所有这些。
- 37 次浏览
SEO Title
Secure inter-micro-service communication with Spring Boot, Kafka, Vault and Kubernetes -- Part 4 : Building micro-services