springcloud系列—Config—第6章-3: Spring Cloud Config 高可用配置、安全与加密解密

资料参考:《Spring Cloud 微服务实战》

目录

安全保护

加密解密

使用前提

相关端点

配置密钥

非对称加密

高可用配置


安全保护

由于配置中心存储的内容比较敏感,做一定的安全处理是必要的。为配置中心实现安全保护的方式有很多,比如物理网络限制,OAuth2授权等。不过,由于我们的微服务应用和配置中心都是构建与springboot基础上的,所以与spring security结合使用会更加方便。

加入spring-boot-starter-security依赖

 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
</dependency>

默认情况下,我们可以随机获得一个名为user的用户,并且在配置中心启动的时候,在日志中打印出随机密码,具体如下:

Using default security password: 8c374401-d37c-43fc-8f1e-cf6b09b75045

大多数情况下,我们并不会使用随机生成的密码的机制,可以在配置文件中指定用户和密码,比如:

security:
  basic:
    enabled: true
  user:
    name: user
    password: root123456

由于我们已经为config-server设置了安全保护,如果这时候连接到配置中心的客户端没有设置对应的安全信息,在获取配置信息时会返回401错误,所以需要通过配置方法在客户端加入安全校验,

security:
  basic:
    enabled: true
  user:
    name: user
    password: root123456

加密解密

在微服务架构中,我们通常会采用DevOps的组织方式来降低因团队间沟通造成的巨大成本,以加速微服务应用的交付能力,这就使得原本运维团队控制的线上信息将交由微服务所属组织的成员自行维护,其中将会包含大量的敏感信息,比如数据库的账户与密码等。显然,明文存储是非常危险的。针对这个问题。 spring cloud config提供了对属性加密解密的功能,以保护配置文件中的信息安全,比如下面的列子:

spring.datasource.username=root
spring.datasource.password={cipher}dsafdsfsdf3r423rewfsdfsdfasdfasdfsadfsadfsadfsa

spring cloud config中通过属性值前使用{cipher}前缀来标注该内容是一个加密值,当微服务客户加载配置时,配置中心会自动为带有{cipher}前缀的值进行解密,通过该机制的实现,运维团队就可以将线上信息的加密资源给微服务团队,而不担心这些敏感信息遭到泄漏了。

使用前提

在使用spring cloud config的加密解密功能时,为了启动该功能,需要在配置中心环境安装jce(Unlimited Strength Jurisdiction Policy)。虽然,jce时jdk自带的,但是默认使用的是有长度限制的版本。在oracle的官方网站下载它,下载地址:jce1.8版本

下载之后是一个压缩包,里面有三个文件:

local_policy.jar
README.txt
US_export_policy.jar

我们需要将local_policy.jarUS_export_policy.jar两个文件复制到$JAVA_HOME/jre/lib/security目录下。覆盖之前的默认内容。到这里准备工作完成了。

相关端点

在完成jce的安装后,可以尝试启动配置中心。在控制台中,将会输出一些配置中心特有的端点,

08-18 14:04:43.238  INFO 53689 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/encrypt],methods=[POST]}" onto public java.lang.String org.springframework.cloud.config.server.encryption.EncryptionController.encrypt(java.lang.String,org.springframework.http.MediaType)
2017-08-18 14:04:43.238  INFO 53689 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/encrypt/{name}/{profiles}],methods=[POST]}" onto public java.lang.String org.springframework.cloud.config.server.encryption.EncryptionController.encrypt(java.lang.String,java.lang.String,java.lang.String,org.springframework.http.MediaType)
2017-08-18 14:04:43.238  INFO 53689 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/decrypt/{name}/{profiles}],methods=[POST]}" onto public java.lang.String org.springframework.cloud.config.server.encryption.EncryptionController.decrypt(java.lang.String,java.lang.String,java.lang.String,org.springframework.http.MediaType)
2017-08-18 14:04:43.238  INFO 53689 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/decrypt],methods=[POST]}" onto public java.lang.String org.springframework.cloud.config.server.encryption.EncryptionController.decrypt(java.lang.String,org.springframework.http.MediaType)
2017-08-18 14:04:43.238  INFO 53689 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/encrypt/status],methods=[GET]}" onto public java.util.Map<java.lang.String, java.lang.Object> org.springframework.cloud.config.server.encryption.E
  • /encrypt/status:查看加密功能状态的端点。
  • /key: 查看密钥的端点。
  • /encrypt: 对请求的body内容进行加密的端点。
  • /decrypt:对请求body内容进行解密的端点

尝试访问/encrypt/status端点,http://localhost:9090/encrypt/status,页面显示:

{
    description: "No key was installed for encryption service",
    status: "NO_KEY"
}

该返回信息说明当前配置中心的加密功能还不能使用,因为还没有配置对应的密钥。

配置密钥

可以通过encrypt.key属性在配置文件中直接指定密钥的信息(对称性密钥),比如:在application.yml中加入配置如下:

encrypt:
  key: zhihao.miao

加入了上述服务配置信息之后,重启配置中心,重新访问http://localhost:9090/encrypt/status端点

{
    status: "OK"
}

此时,我们配置中心的加密解密功能就已经可以使用了,访问/encrypt/decrypt端点来使用加密和解密的功能,二个都是post请求,加密和解密信息都需要通过请求体来发送。

➜ curl  localhost:9090/encrypt -d zhihao.miao
af9b9ea63ce1c027d78c1c3414b425ad6f0093c20c69ad144eacb5a8b4522e7c%
➜ curl localhost:9090/decrypt -d af9b9ea63ce1c027d78c1c3414b425ad6f0093c20c69ad144eacb5a8b4522e7c
zhihao.miao%

百分号是结束符。

我们通过配置encrypt.key参数来指定密钥的实现方式采用了对称性加密。这种方式实现起来比较简单,只需要配置一个参数即可。另外,我们也可以使用环境变量ENCRYPT_KEY来进行配置,让密钥信息外部化存储。

demo
修改order-service服务的git仓库的生产环境的配置(application-pro.yml):

spring:
  datasource:
    username: '{cipher}af9b9ea63ce1c027d78c1c3414b425ad6f0093c20c69ad144eacb5a8b4522e7c'
check:
  uri: pro-1.0

贴一下配置中心config-server-git的配置(application.yml):

spring:
  application:
    name: config-server-git
  cloud:
    config:
      server:
        git:
          uri: http://git.oschina.net/zhihaomiao/{application}-config
          username: zhihao.miao
          password: 13579qwertyu
server:
  port: 9090

encrypt:
  key: zhihao.miao

通过url地址访问:

http://localhost:9090/master/order-service-pro.yml

结果:

check:
  uri: pro-1.0
spring:
  datasource:
    username: zhihao.miao

我们发现config-server-git服务自动解密了。

客户端服务(order-service)进行解密,配置文件(bootstrap.yml):

spring:
  application:
    name: order-service
  cloud:
    config:
      uri: http://localhost:9090
      profile: pro
      label: master
server:
  port: 6060

定义了OrderController:

@RestController
@RequestMapping("/order")
public class OrderController {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${check.uri}")
    private String checkurl;

    @GetMapping("/index")
    public String index(){
        log.info("username="+username+",check.uri=="+username);
        return "username="+username+",check.uri==="+checkurl;
    }
}

url地址访问验证:

http://localhost:6060/order/index

打印结果如下:

username=zhihao.miao,check.uri===pro-1.0

发现显示的也是解密的配置。

非对称加密

spring cloud config的配置中心不仅可以使用对称性加密,也可以使用非对称性加密(比如RSA密钥对)。虽然非对象加密(比如RSA密钥对)。虽然非对称性加密的密钥生成与配置相对复杂一些,但是它具有更高的安全性。

首先,需要通过keytool工具来生成密钥对。keytool是jdk中的一个密钥和证书的管理工具。它使用户能够管理自己的公钥/私钥及相关证书,用于(通过数字签名)自我认证(用户向其他用户,服务认证自己)或数据完整性以及认证服务。在jdk1.4以后的版本中都包含了这一工具,位置在$JAVA_HOME/bin/keytool

echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home

我自己本地在/Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home/bin下。

生成证书文件:

keytool -genkeypair -alias mytestkey -keyalg RSA \
  -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
  -keypass changeme -keystore server.jks -storepass letmein

在当前目录下生成server.jks文件(证书文件)

也可以这样生成:

keytool -genkeypair -alias mytestkey -keyalg RSA \
  -keypass changeme -keystore server.jks -storepass letmein

同样也在当前目录下server.jks文件(证书文件)

demo
将生成的server.jks文件(证书文件)放到当前的config server服务的项目路径下,

配置配置文件(application.yml):

spring:
  application:
    name: config-server-git
  cloud:
    config:
      server:
        git:
          uri: http://git.oschina.net/zhihaomiao/{application}-config
          username: zhihao.miao
          password: 13579qwertyu
server:
  port: 9090

encrypt:
  keyStore:
    location: classpath:/server.jks
    password: letmein
    alias: mytestkey
    secret: changeme

访问加密解密的端点

➜ curl  localhost:9090/encrypt -d zhihao.miao
AQArpt0MuLQ4V5/BC/1YkZlUIL72o4M4VEwreFnBXXLGD7iut6KTqTItA9fkjn+XkrHBOuPp2sR7rL8gCaNROE7kqSbxhqclAM7FQv8wy1x5/TZg+QUY/WMkDas4OZmleEZbt+JpZoV/m7n+V8tJwHfgV6zoWCbMwiMjGCzlmfTqsikb0T1t4V2n3JmnAgUtZi0Ot5Gbu1HpsJ2b/YFEH0mcoM/hgJhZNoemxXWiG+vlKCk6edozv/gPm7cz+mCHOsBPf8wQt/4HDEWJPPBIGsBs/OZVi+tEaWchBzSr2CMEdzNCG9OgD/CZneAOwBl/OCCQk83edL7uviko0E9VNlWkIvSXx6TuMCRN8EIwuK6nWPY1fwZXv+GbM17DYPw4dRA=%                                                                                       
➜ curl localhost:9090/decrypt -d AQArpt0MuLQ4V5/BC/1YkZlUIL72o4M4VEwreFnBXXLGD7iut6KTqTItA9fkjn+XkrHBOuPp2sR7rL8gCaNROE7kqSbxhqclAM7FQv8wy1x5/TZg+QUY/WMkDas4OZmleEZbt+JpZoV/m7n+V8tJwHfgV6zoWCbMwiMjGCzlmfTqsikb0T1t4V2n3JmnAgUtZi0Ot5Gbu1HpsJ2b/YFEH0mcoM/hgJhZNoemxXWiG+vlKCk6edozv/gPm7cz+mCHOsBPf8wQt/4HDEWJPPBIGsBs/OZVi+tEaWchBzSr2CMEdzNCG9OgD/CZneAOwBl/OCCQk83edL7uviko0E9VNlWkIvSXx6TuMCRN8EIwuK6nWPY1fwZXv+GbM17DYPw4dRA=
zhihao.miao%

高可用配置

当要将配置中心部署到生产环境时,与服务注册一样,需要时高可用的应用。spring cloud config实现服务端的高可用。spring cloud config实现服务端的高可用非常简单,主要有以下两种方式:

  • 传统方式:不需要为这些服务端做任何额外的配置,遵循一个规则,将所有的config server都指向同一个git仓库,这样所有的配置内容就通过统一的共享文件系统来维护。而客户端在指定config server位置时,只需要配置config server上层的负载均衡设置地址即可。(此时要借助nginx等服务了)

  • 服务模式: 将config server作为一个普通的微服务应用,纳入到eureka的服务治理体系中。这样我们的微服务应用就可以通过配置中心的服务名来获取配置信息,这种方式比起传统的实现模式来说更加有利于维护,因为对于服务端的负载均衡配置和客户端的配置中心制定都通过服务治理机制一并解决了,即实现了高可用,也实现了自维护。

git地址:https://github.com/servef-toto/SpringCloud-Demo/tree/master/config-server-file/git-config

猜你喜欢

转载自blog.csdn.net/weixin_40663800/article/details/85280837