记录一下Consul开启 ACL方法和遇到的小坑
一、Consul的ACL是什么
ACL:访问策略控制
Consul的ACL用来控制访问API和Key/Value文档,做到访问控制。
二、达成目标
启动Consul ACL后,可以对服务注册和调用、Key/Value文档的访问控制,进行授权访问。
三、使用方法
一、开启ACL
1、添加consul配置文件,开启ACL。
创建config-dir目录,将以下配置文件放在此目录下,命名为acl.json
{
"acl": {
"enabled": true, //是否开启ACLToken
"default_policy": "deny", //allow和deny两个值。allow模式下,ACL是黑名单,允许任何未明确禁止的操作。deny模式下,ACL是白名单,阻止任何未明确允许的操作。
"enable_token_persistence": true //值为true时,API使用的令牌集合将被保存到磁盘,并且当代理重新启动时会重新加载。
}
}
启动consul
启动命令:
consul.exe agent -server -bootstrap -advertise 127.0.0.1 -data-dir ./data -ui -config-dir ./config-dir/acl.json
2、使用Postman调用API,获取超级管理员token。
localhost:8500/v1/acl/bootstrap
将AccessorID添加到配置文件中,重新启动Consul
{
"acl": {
"enabled": true,
"default_policy": "deny",
"enable_token_persistence": true,
"tokens": {
"master": "d90be899-26c6-7fb7-84c3-68ba051611a8"
}
}
}
具有全局管理的权限,也就是最大的权限。它允许操作员使用令牌密钥ID来引导ACL系统。需要在所有的server agent上设置同一个值,可以设置为一个随机的UUID。这个值权限最大,注意保管好。
3、使用Postman调用API,创建客户端token。
localhost:8500/v1/acl/create
在Headers中填写
key | value |
---|---|
X-Consul-Token | 上一步获取的master token |
Content-Type | application/json |
将获得的token添入到配置文件中,重新启动。
{
"acl": {
"enabled": true,
"default_policy": "deny",
"enable_token_persistence": true,
"tokens": {
"master": "d90be899-26c6-7fb7-84c3-68ba051611a8",
"agent": "a7744c70-9aab-a190-9ff6-e935a87c117f"
}
}
}
如果不配置控制台会报
[WARN] agent: Coordinate update blocked by ACLs
4、复制master的token,输入
5、在bootstrap.yml配置文件中加入如下属性
服务的注册和获取
spring:
cloud:
consul:
discovery:
acl-token: 输入创建的token
配置文件Key/Value获取
spring:
cloud:
consul:
config:
acl-token: 输入创建的token
二、自定义策略
1、首先进行策略设置
2、创建token并且添加策略
查看权限列表选择权限并且保存。
保存完成后可以在token列表看到刚才添加的token。
点击进去后查看token进行使用。
三、配置策略信息
https://learn.hashicorp.com/tutorials/consul/access-control-manage-policies(官方文档)
示例格式:
用于服务注册
service_prefix ""{
policy = "write"
}
用于key/value获取
key_prefix "" {
policy = "read"
}
官方文档给出,调用服务的ACL需要节点可读,服务可读。(只给了单独服务的可读权限会获取不到),策略如下:
# 安全性低, 所有节点和服务名都可以暴露,基本等同于Master Token
node_prefix "" { policy = "read" }
service_prefix "" { policy = "read" }
# 仅开放相关node和service的可读权限
node "xxxxx" { policy = "read" }
service "xxxxx" { policy = "read" }
四、注意
在开启ACL后,要重写心跳检测(在consulACL项目consul包下已重写)
https://my.oschina.net/u/4227761/blog/3114951(心跳检测方法重写资料)
五、开启心跳检测与consul自己的健康检查会发生互斥
源码:
public static NewService.Check createCheck(Integer port,
HeartbeatProperties ttlConfig, ConsulDiscoveryProperties properties) {
NewService.Check check = new NewService.Check();
if (StringUtils.hasText(properties.getHealthCheckCriticalTimeout())) {
check.setDeregisterCriticalServiceAfter(
properties.getHealthCheckCriticalTimeout());
}
//如果开启就会设置为心跳检查。
if (ttlConfig.isEnabled()) {
check.setTtl(ttlConfig.getTtl());
return check;
}
Assert.notNull(port, "createCheck port must not be null");
Assert.isTrue(port > 0, "createCheck port must be greater than 0");
if (properties.getHealthCheckUrl() != null) {
check.setHttp(properties.getHealthCheckUrl());
}
else {
check.setHttp(String.format("%s://%s:%s%s", properties.getScheme(),
properties.getHostname(), port, properties.getHealthCheckPath()));
}
check.setHeader(properties.getHealthCheckHeaders());
check.setInterval(properties.getHealthCheckInterval());
check.setTimeout(properties.getHealthCheckTimeout());
check.setTlsSkipVerify(properties.getHealthCheckTlsSkipVerify());
return check;
}
如果要开启ACL权限访问控制,就需要关闭心跳检测,让consul使用自己的健康检测机制。主要因为:
@Override
public void run() {
TtlScheduler.this.client.agentCheckPass(this.checkId);
if (log.isDebugEnabled()) {
log.debug("Sending consul heartbeat for: " + this.checkId);
}
}
心跳检测调用的方法没有token,所以会一直403过不去权限检测。
六、更改配置文件
spring官方文档配置:
在bootstrap.yml中 更改健康检查路径的地址为 /actuator/health