Consul ACL 토큰

Consul ACL 토큰

Consul에 보안을 적용하면 '누가 이 요청을 보낸 건지'를 검증하는 과정이 필요해요. ACL(접근 제어 목록) 시스템의 토큰이 바로 Consul에서 인증(authentication)의 핵심 역할을 하는 존재예요. 토큰은 사용자·서비스·에이전트를 식별하고, 그들이 접근할 수 있는 자원을 정책으로 연결해요. 이번에는 토큰의 개념부터 생성, 전달, 회전(rotate)까지 하나씩 살펴볼게요.

ACL이 활성화되면 자원에 접근을 요청하는 주체는 반드시 정책(policy)·서비스 아이덴티티·노드 아이덴티티로 권한을 부여받은 토큰을 함께 제시해야 해요.

출처: ACL Tokens - HashiCorp Developer

본문

토큰은 ACL 시스템에서 사용자·서비스·Consul 에이전트를 인증하는 데 사용되는 객체(artifact)예요. ACL 시스템은 토큰을 확인하고, 연결된 권한에 따라 자원에 대한 접근을 허용하거나 거부해요.

토큰 생성

ACL 관리자는 HTTP API나 CLI로 토큰을 만들어 권한을 가진 주체에 연결할 수 있어요.

$ consul acl token create -description "Read nodes and services" -policy-name node-services-read
$ curl --request PUT --data @payload.json http://127.0.0.1:8500/v1/acl/token

토큰은 신뢰할 수 있는 외부 시스템에서 auth method를 사용해 동적으로 만들 수도 있어요.

토큰 전달하기

Consul 작업을 수행하거나 서비스를 네트워크에 배포하는 사용자는 필요한 정책을 가진 ACL 토큰을 요청에 포함해야 해요. ACL 토큰은 토큰의 SecretID 속성 값이에요. 이 토큰은 요청자를 식별하는 불투명한(opaque) 문자열이라서, ACL 시스템이 요청된 자원에 대한 접근을 허용할지 거부할지 결정할 수 있어요.

Consul 작업 수행하기

ACL이 활성화되면 Consul과 상호작용하려면 요청에 ACL 토큰을 전달해야 해요.

Consul CLI를 사용할 때 ACL 토큰을 전달하는 방법은 두 가지예요.

  1. -token 명령줄 플래그로 ACL 토큰을 지정해요. 다음 예시는 사용자가 intention을 만들 수 있도록 ACL 토큰을 전달해요.

    $ consul intention create -file one.hcl -token "<token>"
    
  2. CONSUL_HTTP_TOKEN이라는 환경 변수로 ACL 토큰을 설정해요. 이러면 CLI로 작업을 수행할 때 -token 플래그를 생략할 수 있어요.

    $ export CONSUL_HTTP_TOKEN="<token>"
    

API 요청을 할 때는 HTTP X-Consul-Token 헤더 필드에 토큰을 지정해요. 다음 예시는 agent/members 엔드포인트에 대한 GET 요청에 대한 헤더를 보여줘요.

$ curl --header "X-Consul-Token: <token>" "http://127.0.0.1:8500/v1/agent/members"

서비스를 ACL로 구성하기

서비스를 구성할 때 token 파라미터로 SecretID 속성 값을 지정해요. 다음 예시 서비스 구성은 redis 서비스에 샘플 ACL 토큰을 포함해요. 이 ACL 토큰은 Consul 카탈로그와 상호작용하는 읽기·쓰기 규칙을 가져야 해요.

service = {
  id = "redis"
  name = "redis"
  namespace = "foo"
  token = "<SecretID>"
}
{
  "service": {
    "id": "redis",
    "name": "redis",
    "namespace": "foo",
    "token": "<SecretID>"
  }
}

에이전트를 ACL로 구성하기

Consul 에이전트가 여러 ACL 토큰(acl.tokens)을 보유하도록 구성할 수 있어요. 이는 ACL 시스템 부트스트래핑이나 특정 조건에서 Consul에 접근하는 등 여러 사용 사례를 수용하기 위함이에요. 다음 예시에서 에이전트는 기본 토큰을 사용하도록 구성돼요.

acls {
  tokens = {
    default = "00000000-0000-0000-0000-000000000000"
  }
}
{
  "acls": {
    "tokens": {
      "default": "00000000-0000-0000-0000-000000000000"
    }
  }
}

토큰 회전(Rotate)하기

배포의 보안을 보장하기 위해 토큰을 정기적으로 회전할 것을 권장해요. 토큰을 회전하려면 새 토큰을 만들고, 이전 토큰을 참조하는 모든 구성을 새 토큰으로 갱신한 다음, 이전 토큰을 삭제해야 해요. 서비스·에이전트 등록, DNS 조회, Consul 데이터 접근에 사용되는 토큰을 회전할 수 있어요.

이전 토큰과 같은 권한을 유지하려면 기존 토큰의 AccessorID로 clone 명령을 사용해요.

$ consul acl token clone -description "Clone of <token_you_are_cloning>" -id <accessor_id_you_are_cloning>
Token cloned successfully.
AccessorID:   dcfa52ed-9288-b3ff-056d-255ef69d2d88
SecretID:     0005d17e-5bb2-7e8b-7bfa-15f2eee9ad14
Description:  Clone of Super User
Local:        false
Create Time:  2018-10-22 16:26:02.909096 -0400 EDT
Policies:
   00000000-0000-0000-0000-000000000001 - global-management

필요에 따라 토큰을 에이전트나 서비스에 적용해요. 마지막으로 Consul에서 이전 토큰을 삭제해요. ACL 토큰은 HTTP API의 acl 엔드포인트로도 삭제할 수 있어요.

$ consul acl token delete -id 6a1253d2-1785-24fd-91c2-f8e78c745511

특수 목적 토큰

다음 표는 특수 목적 토큰의 일부를 설명해요. 구성할 수 있는 전체 특수 목적 토큰 집합은 acl.tokens 문서를 참고하세요.

토큰 서버 클라이언트 설명
acl.tokens.agent optional optional 내부 에이전트 작업에 사용돼요.
acl.tokens.agent_recovery optional optional 원격 bearer 토큰 해석이 실패할 때 agent/ HTTP API 엔드포인트에 접근할 수 있게 해줘요. 클러스터 설정과 초기 join 작업에 사용돼요.
acl.tokens.default optional optional 토큰이 제공되지 않을 때 클라이언트 요청에 사용할 기본 토큰을 지정해요. 에이전트에서 DNS 서비스 디스커버리를 사용할 수 있도록 서비스에 대한 읽기 전용 접근으로 흔히 구성돼요.
acl.tokens.initial_management optional n/a ACL 시스템을 부트스트랩하는 데 사용돼요.
acl.tokens.replication optional n/a 보조 데이터센터가 기본 데이터센터의 데이터를 복제하도록 승인해요.

/v1/agent/token 엔드포인트로 initial_management 토큰을 제외한 모든 예약 토큰을 만들거나 갱신할 수 있어요.

스냅샷 토큰

스냅샷은 백업·복구 목적으로 snapshot API로 만들어진 객체예요. 스냅샷에는 ACL 토큰이 포함되며, 스냅샷과 상호작용하려면 acl:write 권한을 가진 토큰이 필요해요.

ACL 에이전트 토큰

ACL 에이전트 토큰(acl.tokens.agent)은 Consul이 내부 에이전트 작업에 사용하는 특수 토큰이에요. 기본 ACL 토큰(acl.tokens.default)처럼 사용자가 시작한 작업에는 직접 사용되지 않아요. 하지만 ACL 에이전트 토큰을 정의하지 않으면 Consul은 내부 에이전트 작업에 기본 ACL 토큰을 사용해요. Consul은 다음과 같은 에이전트 작업에 ACL 에이전트 토큰을 사용해요.

  1. Catalog API로 에이전트의 노드 항목을 갱신해요. 여기에는 노드 메타데이터, 태그된 주소, 네트워크 좌표 갱신이 포함돼요.
  2. anti-entropy 동기화를 수행하는데, 특히 카탈로그에 등록된 노드 메타데이터와 서비스 읽기를 포함해요.
  3. consul exec 명령을 실행할 때 KV 스토어의 특수 _rexec 섹션을 읽고 써요.

다음 예시는 mynode라는 노드의 내부 에이전트 작업을 수행하는 데 필요한 최소 정책이에요. service_prefix 정책은 에이전트에 등록될 수 있는 모든 서비스에 대한 읽기 접근이 필요해요. 원격 실행을 비활성화했다면(기본 동작) key_prefix 정책은 생략할 수 있어요.

node "mynode" {
  policy = "write"
}
service_prefix "" {
  policy = "read"
}
key_prefix "_rexec" {
  policy = "write"
}

내장 토큰

Consul에는 내장 익명(anonymous) 토큰과 초기 관리(initial management) 토큰이 포함돼요. 두 토큰 모두 클러스터를 부트스트랩할 때 주입돼요.

익명 토큰

익명 토큰은 bearer 토큰을 지정하지 않고 요청했을 때 사용돼요. 이 토큰의 속성은 다음과 같아요.

속성
AccessorID 00000000-0000-0000-0000-000000000002
SecretID anonymous

익명 토큰의 설명과 정책은 갱신할 수 있지만, 토큰 자체는 삭제할 수 없어요.

⚠️ 보안 경고: 익명 토큰에 광범위한 정책을 연결하면 토큰 없이도 그 권한에 접근할 수 있게 되므로, 익명 토큰의 정책은 최소한으로 유지하세요.

초기 관리 토큰

초기 관리 토큰을 만드는 방법은 두 가지예요.

  1. consul acl bootstrap으로 ACL 시스템을 부트스트랩해요. Consul이 자동으로 토큰을 생성해 줘요.
  2. Consul 에이전트 구성(acl.token.initial_management)에 초기 관리 토큰을 직접 정의해요. 이 방법으로 ACL 관리자는 알려진 값으로 ACL 시스템을 부트스트랩할 수 있어요.

Consul은 관리 토큰을 내장 global management 정책에 연결해요. 이 토큰은 자원과 API에 대한 무제한 권한을 가져요.

ACL 에이전트 복구 토큰

ACL 에이전트 복구 토큰(acl.tokens.agent_recovery)은 Consul 서버를 사용할 수 없을 때 사용할 수 있어요. 토큰에 연결된 정책은 에이전트에서 로컬로 관리되며, Consul 서버에 토큰을 정의할 필요가 없어요. 설정되면 암묵적으로 다음과 같은 정책이 연결돼요.

agent "<node name of agent>" {
  policy = "write"
}
node_prefix "" {
  policy = "read"
}

더 알아보기