LoginSignup
13
13

More than 5 years have passed since last update.

Consul ACLの使い方

Last updated at Posted at 2014-11-06

Consul ACL (Consul 0.4.X)の使い方。
詳細まで正しいかは不明だが、解ったことから書いていく。

概要

  • トークン単位で値に対する操作を制限する機能。
  • 各トークンはID、名前、どこの値にどのようにアクセスできるかのルールセットを持つ。
  • 値へのアクセス時にトークンIDを指定し(指定しなければデフォルトトークン)、認可を行う。

公式ドキュメントはこちら

対象API

ドキュメントに、

As of Consul 0.4, it is only possible to specify policies for the KV store.

とあるとおり、0.4時点ではKVSだけアクセス制限できる。
※ACLのAPIにはmaster tokenでないとアクセスできない。

Configで書けること

ACLはHTTP APIで登録する。Configファイルにルールを書いておいて、起動したらそれが有効になる、という使い方ではない模様。

Configファイルに書く値

  • acl_datacenter

これで指定したdatacenterがACLでアクセス制限する対象になる。この指定があるとACLが有効になるが、指定せずにACLのAPIにアクセスするとエラーが発生する。

$ curl http://localhost:8500/v1/acl/list?token=master_token_test
ACL support disabled
  • acl_default_policy

allowかdenyを設定する。ACLの持っているruleに対して適用されるもので、allowの場合はblacklist、denyの場合はwhitelist方式での制限を行う。
デフォルトはallow。

  • acl_master_token

Typeがmanagementのトークン。これを指定すると、全ての値にwriteレベルでアクセスでき、ACLの操作ができる。
※対してTypeがclientの場合、ACLの操作はできない。

  • acl_token

HTTP APIで値にアクセスする際、?token=を指定しない場合はこのトークンが利用される。
デフォルトはanonymous。
※トークンを指定すれば、このデフォルトをリクエスト単位で上書きできる、ということ。

設定ファイルの例

/etc/consul.d/default.json

{
  "datacenter": "testdc",
  "data_dir": "/var/lib/consul",
  "server": true,
  "bootstrap": true,
  "acl_datacenter": "testdc",
  "acl_default_policy": "deny",
  "acl_master_token": "master_token_test",
  "acl_token": "anonymous"
}

上記の設定で起動した場合にデフォルトで存在するACLを取得してみると、以下のようになる。

$ curl http://localhost:8500/v1/acl/list
Permission denied

$ curl http://localhost:8500/v1/acl/list?token=anonymous
Permission denied

$ curl http://localhost:8500/v1/acl/list?token=master_token_error
ACL not found

$ curl http://localhost:8500/v1/acl/list?token=master_token_test | jq .
[
  {
    "Rules": "",
    "Type": "client",
    "Name": "Anonymous Token",
    "ID": "anonymous",
    "ModifyIndex": 2,
    "CreateIndex": 2
  },
  {
    "Rules": "",
    "Type": "management",
    "Name": "Master Token",
    "ID": "master_token_test",
    "ModifyIndex": 3,
    "CreateIndex": 3
  }
]

ACLの登録

ACLはHTTP APIで登録する。
Rulesは HashiCorp Configuration Language (HCL) を文字列で記述する。 jsonで書くとエラーが発生する。 jsonで書いても大丈夫。
policyにはdeny、read、writeを書くことができ、writeはreadの権限も包含する(readwriteは存在せず、書き込めるが読み込めない、ということは無い)。

例:

$ cat /tmp/acl.txt
{
  "Name": "test_token",
  "Type": "client",
  "Rules": "
    key \"testread/\" {
      policy = \"read\"
    }
    key \"testwrite/\" {
      policy = \"write\"
    }
  "
}

$ curl -X PUT http://localhost:8500/v1/acl/create?token=master_token_test -d @/tmp/acl.txt
{"ID":"53b6df4c-7f77-c816-750d-b5eabf5ca582"}

$ curl http://localhost:8500/v1/acl/list?token=master_token_test | jq .
[
  {
    "Rules": "    key \"testread/\" {      policy = \"read\"    }    key \"testwrite/\" {      policy = \"write\"    }  ",
    "Type": "client",
    "Name": "test_token",
    "ID": "53b6df4c-7f77-c816-750d-b5eabf5ca582",
    "ModifyIndex": 26,
    "CreateIndex": 26
  },
  {
    "Rules": "",
    "Type": "client",
    "Name": "Anonymous Token",
    "ID": "anonymous",
    "ModifyIndex": 2,
    "CreateIndex": 2
  },
  {
    "Rules": "",
    "Type": "management",
    "Name": "Master Token",
    "ID": "master_token_test",
    "ModifyIndex": 3,
    "CreateIndex": 3
  }
]

createすると、作成されたACLのIDが戻ってくるので、それを使う形になる。

ACLを使ってアクセス

readableに対するアクセス

  • readableに対してGETを行い、値が無い場合
$ # no value
$ curl -i http://localhost:8500/v1/kv/testread/value?token=master_token_test
HTTP/1.1 404 Not Found
X-Consul-Index: 44
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 06:46:22 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

$ curl -i http://localhost:8500/v1/kv/testread/value?token=anonymous
HTTP/1.1 404 Not Found
X-Consul-Index: 44
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 06:46:30 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

$ curl -i http://localhost:8500/v1/kv/testread/value
HTTP/1.1 404 Not Found
X-Consul-Index: 44
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 06:46:40 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

$ curl -i http://localhost:8500/v1/kv/testread/value?token=53b6df4c-7f77-c816-750d-b5eabf5ca582
HTTP/1.1 404 Not Found
X-Consul-Index: 44
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 06:46:54 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8
  • readableに対してPUTを行う場合
$ curl -i -X PUT http://localhost:8500/v1/kv/testread/value -d 200
HTTP/1.1 403 Forbidden
Date: Thu, 06 Nov 2014 06:47:41 GMT
Content-Length: 17
Content-Type: text/plain; charset=utf-8

Permission denied

$ curl -i -X PUT http://localhost:8500/v1/kv/testread/value?token=anonymous -d 200
HTTP/1.1 403 Forbidden
Date: Thu, 06 Nov 2014 06:47:48 GMT
Content-Length: 17
Content-Type: text/plain; charset=utf-8

Permission denied

$ curl -i -X PUT http://localhost:8500/v1/kv/testread/value?token=53b6df4c-7f77-c816-750d-b5eabf5ca582 -d 200
HTTP/1.1 403 Forbidden
Date: Thu, 06 Nov 2014 06:47:59 GMT
Content-Length: 17
Content-Type: text/plain; charset=utf-8

Permission denied

$ curl -i -X PUT http://localhost:8500/v1/kv/testread/value?token=master_token_test -d 200
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 06 Nov 2014 06:48:31 GMT
Content-Length: 4

true
  • readableに対してGETを行い、値がある場合
$ curl -i http://localhost:8500/v1/kv/testread/value?token=master_token_test
HTTP/1.1 200 OK
Content-Type: application/json
X-Consul-Index: 48
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 06:48:58 GMT
Content-Length: 99

[{"CreateIndex":48,"ModifyIndex":48,"LockIndex":0,"Key":"testread/value","Flags":0,"Value":"MjAw"}]

$ curl -i http://localhost:8500/v1/kv/testread/value?token=anonymous
HTTP/1.1 404 Not Found
X-Consul-Index: 48
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 06:49:26 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

$ curl -i http://localhost:8500/v1/kv/testread/value
HTTP/1.1 404 Not Found
X-Consul-Index: 48
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 06:49:34 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

$ curl -i http://localhost:8500/v1/kv/testread/value?token=53b6df4c-7f77-c816-750d-b5eabf5ca582
HTTP/1.1 200 OK
Content-Type: application/json
X-Consul-Index: 48
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 06:49:42 GMT
Content-Length: 99

[{"CreateIndex":48,"ModifyIndex":48,"LockIndex":0,"Key":"testread/value","Flags":0,"Value":"MjAw"}]

master_tokenは何でもできる。
また、readが許可されていないトークンでGETを行った場合、403ではなく404になるらしいので、エラーハンドリングは注意が必要かもしれない。

writableに対するアクセス

master_tokenは上でも似たような実験を行ったため、省略。

  • writableに対して書き込み
$ curl -i -X PUT http://localhost:8500/v1/kv/testwrite/value -d 300
HTTP/1.1 403 Forbidden
Date: Thu, 06 Nov 2014 07:00:47 GMT
Content-Length: 17
Content-Type: text/plain; charset=utf-8

Permission denied

$ curl -i -X PUT http://localhost:8500/v1/kv/testwrite/value?token=anonymous -d 300
HTTP/1.1 403 Forbidden
Date: Thu, 06 Nov 2014 07:00:54 GMT
Content-Length: 17
Content-Type: text/plain; charset=utf-8

Permission denied

$ curl -i -X PUT http://localhost:8500/v1/kv/testwrite/value?token=53b6df4c-7f77-c816-750d-b5eabf5ca582 -d 300
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 06 Nov 2014 07:01:03 GMT
Content-Length: 4

true
  • writableに対して読み込み
$ curl -i http://localhost:8500/v1/kv/testwrite/value
HTTP/1.1 404 Not Found
X-Consul-Index: 62
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 07:03:09 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

$ curl -i http://localhost:8500/v1/kv/testwrite/value?token=anonymous
HTTP/1.1 404 Not Found
X-Consul-Index: 62
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 07:03:17 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

$ curl -i http://localhost:8500/v1/kv/testwrite/value?token=53b6df4c-7f77-c816-750d-b5eabf5ca582
HTTP/1.1 200 OK
Content-Type: application/json
X-Consul-Index: 62
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 07:03:23 GMT
Content-Length: 100

[{"CreateIndex":62,"ModifyIndex":62,"LockIndex":0,"Key":"testwrite/value","Flags":0,"Value":"MzAw"}]

KVS以外のAPIへのアクセス

先頭で記載したとおり、0.4時点ではKVS以外へのアクセスは制限されない。

$ curl -i -X GET http://localhost:8500/v1/catalog/services?token=53b6df4c-7f77-c816-750d-b5eabf5ca582
HTTP/1.1 200 OK
Content-Type: application/json
X-Consul-Index: 6
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 07:19:51 GMT
Content-Length: 13

{"consul":[]}

$ curl -i -X PUT http://localhost:8500/v1/event/fire/testevent?token=53b6df4c-7f77-c816-750d-b5eabf5ca582
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 06 Nov 2014 07:20:16 GMT
Content-Length: 151

{"ID":"1aa92970-7d1a-d4ae-2334-d8fca7002a26","Name":"testevent","Payload":null,"NodeFilter":"","ServiceFilter":"","TagFilter":"","Versi
on":1,"LTime":0}

$ curl -i -X GET http://localhost:8500/v1/event/list?token=53b6df4c-7f77-c816-750d-b5eabf5ca582
HTTP/1.1 200 OK
Content-Type: application/json
X-Consul-Index: 4151740018762382984
Date: Thu, 06 Nov 2014 07:20:24 GMT
Content-Length: 153

[{"ID":"1aa92970-7d1a-d4ae-2334-d8fca7002a26","Name":"testevent","Payload":null,"NodeFilter":"","ServiceFilter":"","TagFilter":"","Vers
ion":1,"LTime":2}]

ただし、ACLのAPIだけは、masterのみアクセス可能。

$ curl -i -X GET http://localhost:8500/v1/acl/list
HTTP/1.1 403 Forbidden
X-Consul-Index: 0
X-Consul-Knownleader: false
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 07:12:18 GMT
Content-Length: 17
Content-Type: text/plain; charset=utf-8

Permission denied

$ curl -i -X GET http://localhost:8500/v1/acl/list?token=53b6df4c-7f77-c816-750d-b5eabf5ca582
HTTP/1.1 403 Forbidden
X-Consul-Index: 0
X-Consul-Knownleader: false
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 07:12:22 GMT
Content-Length: 17
Content-Type: text/plain; charset=utf-8

Permission denied

$ curl -i -X GET http://localhost:8500/v1/acl/list?token=master_token_test
HTTP/1.1 200 OK
Content-Type: application/json
X-Consul-Index: 26
X-Consul-Knownleader: true
X-Consul-Lastcontact: 0
Date: Thu, 06 Nov 2014 07:12:26 GMT
Content-Length: 449

[{"CreateIndex":26,"ModifyIndex":26,"ID":"53b6df4c-7f77-c816-750d-b5eabf5ca582","Name":"test_token","Type":"client","Rules":"    key \"testread/\" {      policy = \"read\"    }    key \"testwrite/\" {      policy = \"write\"    }  "},{"CreateIndex":2,"ModifyIndex":2,"ID":"anonymous","Name":"Anonymous Token","Type":"client","Rules":""},{"CreateIndex":3,"ModifyIndex":3,"ID":"master_token_test","Name":"Master Token","Type":"management","Rules":""}]

細かい動き

クラスタに参加するノードの設定に書かれたacl_master_tokenがすべて異なる場合、どれが有効になるのか?

acl_master_tokenは、Leaderのものが有効になる。
厳密には、Leaderのacl_master_tokenをIDとしたACLがクラスタに追加される。

Leaderがダウンしたらどうなるのか?

  • 新しく選出されたLeaderの設定に書かれていたacl_master_tokenがダウンした元Leaderのacl_master_tokenと異なる場合

新しく選出されたLeaderの設定に書かれていたacl_master_tokenをIDとしたACLが追加される。
ダウンした元Leaderのacl_master_tokenのACLはそのまま残るので、master tokenが複数ある状態になる。
(ダウン時も、ダウンした元Leaderの復旧時も、特に削除しにいったりはしない)

  • 新しく選出されたLeaderの設定に書かれていたacl_master_tokenがダウンした元Leaderのacl_master_tokenと同一の場合

ACLは増えもせず減りもせず。引き続き同じacl_master_tokenのACLを利用できる。

今のところ、ここまで。

13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13