consul配置ACL
第0步,几点说明
- Consul和其他系统ACL的区别
- 通常的ACL授权例如etcd使用用户名:密码对的方式来认证用户,用户名是可能是公开的,密码是保密的用户自己知道;但是consul没有使用用户名:密码对的方式,就使用一个token值;那么既然只有一个值,就必须注意保密,不能使用约定的名字字符串,例如root, tom, jerry等,因为别人很容易猜出来,现在consul使用的字符串时UUID,既唯一又随机,不能被猜出来。
- consul的三类权限类型
- read: 读
- write: 读和写
- deny: 不能访问,既不能读也不能写了。
第一步,激活ACL
consul的ACL激活需要在所有的consul节点上,办法是,创建一个json格式的配置文件:
$ cat consul-acl.json
{
"acl" : {
"enabled" : true,
"default_policy" : "deny",
"down_policy" : "extend-cache",
"tokens" :{
"master": "245d0a09-7139-bbea-aadc-ff170a0562b1"
}
}
}
放置到consul agent通过参数-config-dir指定的目录下面,缺省目录是:/consul/config/
注意几点:
- 这个相同的文件需要部署到所有的consul节点上。
- 关于tokens.master值,这个就是Bootstrap Token
2.1 Bootstrap Token相当于Unix系统中的root,具有所有的权限。
2.2. 其名字可以是任意字符串,不一定是一个UUID值。(原因如前面说,使用UUID为了安全用户无法猜测。)
2.3. tokens.master可以不需要配置,然后在clustor启动之后通过命令产生,如下:
$ consul acl bootstrap
AccessorID: 0274a9e3-1349-78d7-fc53-3dd6f7886626
SecretID: 245d0a09-7139-bbea-aadc-ff170a0562b1
Description: Bootstrap Token (Global Management)
Local: false
Create Time: 2019-01-15 06:21:17.335464249 +0000 UTC
Policies:
00000000-0000-0000-0000-000000000001 - global-management
此时产生的bookstrap就是字符串SecretID: 245d0a09-7139-bbea-aadc-ff170a0562b1。
注意这个bootstrap token的安全不能外泄,不能丢失,后面的创建其他token都需要用到它。
第二步:token的三种类型
- management token: 具有root权限的token,前面介绍的master token就属于这类。也可以增加新的management token。
- client token: 针对客户端的token,ACL的权限管理主要是针对这类token;当创建client token时需要一个management toke。
- anonymous token : 这是系统内置的token。
第三步:创建一个management token
$ curl \
-H "X-Consul-Token: secret" \
-X PUT \
-d '{"Name": "dc1", "Type": "management"}' \
http://localhost:8500/v1/acl/create?token=245d0a09-7139-bbea-aadc-ff170a0562b1
{"ID":"7fa04e1d-1b75-81b0-52d3-e311ad3c28f7"}
参数token就是另一个management token,在这个例子中就是bootstrap token。这样7fa04e1d-1b75-81b0-52d3-e311ad3c28f7就是另外一个management token了,具有"root"的权限。
第四步:创建client token
client token才是真正需要对其授权的token。
创建一个client token需要两步,先创建client policy,然后才能创建client token。
4.1 创建client policy
$ cat client-policy.json
{
"Name": "client-read-policy",
"Description": "Grants read access to all node information",
"Rules": "node_prefix \"\" { policy = \"read\"}",
"Datacenters": ["dc1"]
}
$ curl --request PUT --data @client-policy.json http://127.0.0.1:8500/v1/acl/policy?token=753cc134-36c5-e4ea-6abd-56f8b8b8aa7f
{
"ID":"778192cf-5459-a6e0-99d6-74919ea61dfc",
"Name":"client-read-policy",
"Description":"Grants read access to all node information",
"Rules":"key_prefix \"\" { policy = \"read\"}",
"Datacenters":["dc1"],
"Hash":"0lcW+0xrcZ6OxTwb3ND+7oA+FF8XhXj60J8KGFpEZI0=",
"CreateIndex":105,
"ModifyIndex":105
}
$ curl -X GET http://127.0.0.1:8500/v1/acl/policies?token=753cc134-36c5-e4ea-6abd-56f8b8b8aa7f
[
{
"CreateIndex": 4,
"Datacenters": null,
"Description": "Builtin Policy that grants unlimited access",
"Hash": "swIQt6up+s0cV4kePfJ2aRdKCLaQyykF4Hl1Nfdeumk=",
"ID": "00000000-0000-0000-0000-000000000001",
"ModifyIndex": 4,
"Name": "global-management"
},
{
"CreateIndex": 105,
"Datacenters": ["dc1" ],
"Description": "Grants read access to all node information",
"Hash": "0lcW+0xrcZ6OxTwb3ND+7oA+FF8XhXj60J8KGFpEZI0=",
"ID": "778192cf-5459-a6e0-99d6-74919ea61dfc",
"ModifyIndex": 105,
"Name": "client-read-policy"
}
]
注意这里client-policy.json里面Rules可以为node_prefix, service_prefix,和key_prefix;在我这个例子中只使用了key_prefix因为我们只需要KV访问,没有service discover功能。
4.2 创建client token
$ cat client-token.json
{
"Description": "client read token",
"Policies": [
{
"Name": "client-read-policy"
}
],
"Local": false
}
$ curl --request PUT --data @client-token.json http://127.0.0.1:8500/v1/acl/token?token=753cc134-36c5-e4ea-6abd-56f8b8b8aa7f
{
"AccessorID": "25be308f-43c0-11c8-e620-117e6b91629d",
"CreateIndex": 115,
"CreateTime": "2019-01-15T08:00:04.241925426Z",
"Description": "client read token",
"Hash": "AZ2/M3PRNDcTULjWcpC8eb6EPVoGUHnCKa0nQghKN0I=",
"Local": false,
"ModifyIndex": 115,
"Policies": [
{
"ID": "778192cf-5459-a6e0-99d6-74919ea61dfc",
"Name": "client-read-policy"
}
],
"SecretID": "23fe12e4-ac0e-00af-db43-887589f87823"
}
$ curl -X GET http://127.0.0.1:8500/v1/acl/tokens?token=753cc134-36c5-e4ea-6abd-56f8b8b8aa7f
[
{
"AccessorID": "25be308f-43c0-11c8-e620-117e6b91629d",
"CreateIndex": 115,
"CreateTime": "2019-01-15T08:00:04.241925426Z",
"Description": "client read token",
"Hash": "AZ2/M3PRNDcTULjWcpC8eb6EPVoGUHnCKa0nQghKN0I=",
"Local": false,
"ModifyIndex": 115,
"Policies": [
{
"ID": "778192cf-5459-a6e0-99d6-74919ea61dfc",
"Name": "client-read-policy"
}
]
},
...
]
4.3 上述两步可以合并成一步执行
不过这个API已经被consul标记位Legacy Tokens了。
$ cat client-write-policy.json
{
"Name": "client-write-policy",
"Description": "Grants write access to foo key information",
"Type": "client",
"Rules": "key \"foo/test\" { policy = \"write\" }"
}
$ curl --request PUT --data @client-write-policy.json \
http://127.0.0.1:8500/v1/acl/create?token=753cc134-36c5-e4ea-6abd-56f8b8b8aa7f
{"ID":"1c7c1ca0-d5ee-9d02-f7f4-89dc8759f0c6"}
$ curl -H "X-Consul-Token: 1c7c1ca0-d5ee-9d02-f7f4-89dc8759f0c6" http://127.0.0.1:8500/v1/acl/token/self
{
"AccessorID": "808d69bf-c4fe-0c9f-9a57-aecd85e7f24e",
"CreateIndex": 36,
"CreateTime": "0001-01-01T00:00:00Z",
"Description": "client-write-policy",
"Hash": "mpZmxlI5Zi6HeMFQR0A7U77ZD9IKPDr9Nc9Hrqxz/b8=",
"Local": false,
"ModifyIndex": 37,
"Policies": null,
"Rules": "key \"foo/test\" { policy = \"write\" }",
"SecretID": "1c7c1ca0-d5ee-9d02-f7f4-89dc8759f0c6"
}
第五步, 客户端访问测试
验证,创建一个KV,然后使用client token访问KV:
$ curl --request PUT --data 'hello consul' http://127.0.0.1:8500/v1/kv/foo?token=753cc134-36c5-e4ea-6abd-56f8b8b8aa7f
$ curl --request GET http://127.0.0.1:8500/v1/kv/foo?token=23fe12e4-ac0e-00af-db43-887589f87823
[{"LockIndex":0,"Key":"foo","Flags":0,"Value":"aGVsbG8gY29uc3Vs","CreateIndex":14,"ModifyIndex":14}]
# suppose another token does not have priviledge
$ curl --request GET http://127.0.0.1:8500/v1/kv/foo?token=477ef15e-79b3-8481-b7db-ed7c750b3bea
rpc error making call: rpc error making call: Permission denied