Carpe Diem

備忘録

ConsulでService登録をした時のACLでハマった話

概要

Consulではserviceを登録することでService Discovery機能を活用することができます。
例えば

  "service": {
    "name": "payment",
    "port": 9090,
    "tags": ["development"]
  }

のように設定をすると、

$ dig @localhost -p 8600 payment.service.consul

paymentサービスとして登録したノードのIP群を取得できます。
詳細を知りたい方は以下を参考にしてください。

christina04.hatenablog.com

今回はこのサービス登録でACLを設定しているとうまく行かずハマってしまった話です。

環境

  • Consul v1.4.0

原因調査

以前使ったハンズオン用のリポジトリ

  "service": {
    "name": "consul-ui",
    "port": 8500,
    "tags": ["ui"]
  }

を追加して検証してみました。ui用ノードには以下のエラーが表示されました。

[ERR] consul: "Catalog.Register" RPC failed to server 172.26.0.4:8300: rpc error making call: rpc error making call: Permission denied
[WARN] agent: Service "consul-ui" registration blocked by ACLs

この時のPolicyは以下です。

agent policy

node_prefix "" {
   policy = "write"
}

service_prefix "" {
   policy = "read"
}

agent tokenに使用します。

ui policy

key_prefix "" {
   policy = "write"
}

node_prefix "" {
   policy = "read"
}

service_prefix "" {
   policy = "read"
}

default tokenに使用します。

似たエラー

ググってよく見るエラーは以下です。

[ERR] consul: "Coordinate.Update" RPC failed to server 172.26.0.3:8300: rpc error making call: rpc error making call: Permission denied
[WARN] agent: Coordinate update blocked by ACLs

これはagent間通信でNodeの登録が必要なので、agent tokenには以下のnode:writeの権限が必要になります。

node_prefix "" {
   policy = "write"
}

元々これはドキュメントにも明記されているもので、今回も

node_prefix "" {
   policy = "write"
}

service_prefix "" {
   policy = "read"
}

のpolicyでagent tokenを用意していたので別の問題ということになります。

Service registration だから write権限が必要?

次に

[WARN] agent: Service "consul-ui" registration blocked by ACLs

に注目してみると、registrationとあるのでwrite権限が必要なのでは?と推測しました。
ドキュメントのServiceAPIを確認してみると、

Service - Agent - HTTP API - Consul by HashiCorp

にはservice:writeとあるのでやはり権限が違ったようです。
そこでagent-policyを

node_prefix "" {
   policy = "write"
}

service_prefix "" {
   policy = "write"
}

にしてみました。

しかしこれでもエラーは直りませんでした。

Policyの変更はtokenに反映されない?

「前述のpolicy変更がもしかしたらtokenに反映されてないのでは?」と考えて

  • policy_ttlが過ぎるのを待つ
  • policy変更後にtokenもupdate
  • tokenの再生成

と色々試してみましたがエラーは直りませんでした。

※あとで分かりましたがpolicyの変更はちゃんと既存tokenに反映されます

結論

Serviceの登録はagent tokenを使用しない

github.com

のissueを読んでみると、どうやらService登録はagent tokenによって行われるものではない事が分かりました。
つまりdefault token側の権限が足りていなかったのです。

そこでdefault tokenに使っているui policyを以下のようにservice:writeにしてみると

key_prefix "" {
   policy = "write"
}

node_prefix "" {
   policy = "read"
}

service_prefix "" {
   policy = "write"
}

無事Service登録されることがログ&UIで確認できました。

[INFO] agent: Synced node info
[INFO] agent: Synced service "consul-ui"

f:id:quoll00:20190109033400p:plain

まとめ

Consul ACLは柔軟な権限管理ができる一方で

  • ドキュメントに明記されてない使い方
  • ドキュメント自体の誤植

がちょこちょこあるので本番導入時にはしっかり検証を行いましょう。