Carpe Diem

備忘録

ConsulのACLを後から有効化する

概要

christina04.hatenablog.com

ではConsulのACLの基本的な設定方法を説明しました。その時は

"default_policy": "deny"のようにデフォルトで全リソースのアクセス禁止にしてwhitelist形式で扱っていきます。

と言いましたが、そもそもACL未設定なConsulを稼働中で、急にdefault denyにしたらサービスに影響が出てしまうというケースももちろんあります。
今回はACLを後から有効化(ACLマイグレーション?)する方法を説明します。

環境

  • Consul 1.4.0

ハンズオン

こちらのリポジトリで検証できます。

github.com

手順

大まかな手順としては

  1. サーバのdefault_policyallowにし、ACLenable
  2. サーバを再起動
  3. Agent Policy用意してconfigのacl.tokens.agentにtokenをセット
  4. Consulを利用するサービス毎に適切なポリシーを用意してconfigのacl.tokens.defaultにtokenをセット
  5. 全agentを再起動
  6. Anonymous TokenのPolicyを更新
  7. サーバのdefault_policydenyに変更
  8. サーバを再起動

です。
結構手間ですが各ACLを最低限必要なものにする場合はこれを守らないとどこかしらでERRが出てきます。

1. サーバのdefault_policyallowにし、ACLenable

リポジトリのものはすでにallowにしていますが、稼働中のConsulの設定を

{
  "primary_datacenter": "dc1",
  "acl": {
    "enabled": true,
    "default_policy": "allow",
    "down_policy": "extend-cache",
    "tokens": {
      "master": "b1gs33cr3t"
    }
  }
}

の状態にしてください。
今回も簡単のためmaster tokenを明示的に書いてますが、本番では書かずにbootstrapで生成してください。

2. サーバを再起動

再起動順ですが、リーダーの再選出が行われるとその間一時的にConsulが使えないので

  1. リーダー以外を再起動
  2. 最後にリーダーを再起動

の順で行ってください。

リーダーが再起動されるまではACLは有効化されませんし、各client agentも通常通りクエリを叩けますが、再起動後のサーバはリーダーが再起動されるまではどのコマンドも

/ # consul members
Error retrieving members: Unexpected response code: 403 (ACL not found)

とうエラーが発生するので注意してください。
ただログを見る感じだとコマンドにコケるだけで、内部通信等は問題ないようです。

この時

  • サーバ:acl=enabled
  • クライアント:acl未設定(=disabled)

ですが、クライアント側ではコマンドは問題なく通ります。未設定のまま再起動しても通ります。

$ docker restart acl-migration_consul-server-1_1

3. Agent Policy用意してconfigのacl.tokens.agentにtokenをセット

ConsulのACLでアクセス制御 - Carpe Diem

の通りに作って設定します。

Policy

/ # consul acl policy create \
 -name "agent-policy" \
 -description "Agent Token Policy" \
 -rules @/consul/policies/agent.hcl

Token

/ # consul acl token create \
 -description "Agent Token" \
 -policy-name "agent-policy"

生成したらサーバ・クライアント(agent)側の両方のacl.tokens.agentにtokenをセットします。

サーバ側の例

{
  "primary_datacenter": "dc1",
  "acl": {
    "enabled": true,
    "default_policy": "allow",
    "down_policy": "extend-cache",
    "tokens": {
      "master": "b1gs33cr3t",
      "agent": "a2b385df-4355-a37e-d465-b5430ea8b671"
    }
  }
}

後ほどまとめて再起動するので今はconfigの更新のみで大丈夫です。

4. Consulを利用するサービス毎に適切なポリシーを用意してconfigのacl.tokens.defaultにtokenをセット

例えばUI用のポリシーを個別に設定するとして、

ConsulのACLでアクセス制御 - Carpe Diem

のようにtokenを作ります。

Policy

/ # consul acl policy create \
 -name "ui-policy" \
 -description "UI Token Policy" \
 -rules @/consul/policies/ui.hcl

Token

/ # consul acl token create \
 -description "UI Token" \
 -policy-name "ui-policy"

UIの場合はWebからも登録できますが、以下のようにconfigでacl.tokens.defaultにセットすれば登録できます。

{
  "primary_datacenter": "dc1",
  "acl": {
    "enabled": true,
    "down_policy": "extend-cache",
    "tokens": {
      "agent": "a2b385df-4355-a37e-d465-b5430ea8b671",
      "default": "a2b385df-4355-a37e-d465-b5430ea8b671"
    }
  }
}

5. 全agentを再起動

サーバ含め各agentを再起動してください。

$ docker restart acl-migration_consul-agent-1_1

6. Anonymous TokenのPolicyを更新

ConsulのACLでアクセス制御 - Carpe Diem

の通りに更新します。

Policy

/ # consul acl policy create \
 -name "anonymous-policy" \
 -description "Anonymous Token Policy" \
 -rules @/consul/policies/anonymous.hcl

Anonymous Tokenにアタッチ

/ # consul acl token update \
 -id 00000000-0000-0000-0000-000000000002 \
 -policy-name "anonymous-policy" \
 -description "Anonymous Token"

7. サーバのdefault_policydenyに変更

一通り設定できたら最後にdefault_policydenyに変更します。

{
  "primary_datacenter": "dc1",
  "acl": {
    "enabled": true,
    "default_policy": "deny",
    "down_policy": "extend-cache",
    "tokens": {
      "master": "b1gs33cr3t",
      "agent": "a2b385df-4355-a37e-d465-b5430ea8b671"
    }
  }
}

8. サーバを再起動

再起動順は先程と同じく

  1. リーダー以外を再起動
  2. 最後にリーダーを再起動

の順で行ってください。

リーダーが再選出されない限りdefault_policy: denyの設定は反映されません。

$ docker restart acl-migration_consul-server-1_1

まとめ

ConsulのACLを後から有効化する方法を紹介しました。
手っ取り早いのはAnonymous Tokenにゴリゴリ権限を追加する方法ですが、それだとサービス毎に設定できる柔軟性・セキュリティの担保ができなくなるのでドキュメント通りの最低限の権限を付与していくのが良いです。