controller 스탠자

controller 스탠자

controller 스탠자는 Boundary 컨트롤러 특화 파라미터를 구성해요. 데이터베이스 연결, 인증 토큰 수명, API 요청 제한 같은 컨트롤러의 핵심 동작을 여기서 정해요.

출처: HashiCorp Boundary docs

본문

controller 스탠자는 Boundary 컨트롤러 특화 파라미터를 구성해요.

controller {
  name = "example-controller"
  description = "An example controller"
  database {
    url = "postgresql://<username>:***@10.0.0.1:5432/<database_name>"
    max_open_connections = 5
  }
}
  • name — Boundary 클러스터 내에서 이 컨트롤러의 고유한 이름을 지정해요. 이 값은 이름 문자열을 직접 쓸 수도 있고, 이름을 읽어올 디스크의 파일(file://)을 가리킬 수도 있으며, 이름을 읽어올 환경 변수(env://)를 가리킬 수도 있어요.

  • description — 이 컨트롤러에 대한 설명을 지정해요. 이 값은 설명 문자열을 직접 쓸 수도 있고, 설명을 읽어올 디스크의 파일(file://)을 가리킬 수도 있으며, 설명을 읽어올 환경 변수(env://)를 가리킬 수도 있어요.

  • database — Postgres에 연결하기 위한 두 개의 유효한 파라미터를 가진 구성 블록이에요.

    • url — Postgres에 연결하기 위한 URL을 구성해요. Postgres 서버의 TLS가 비활성화되어 있으면 Boundary는 기본적으로 연결하지 못해요. Postgres에 TLS 연결 없이 Boundary를 실행하려면(프로덕션에는 권장하지 않아요) 연결 문자열에 sslmode=disable 파라미터를 추가하세요. 예: url = "postgresql://postgres:***@192.168.1.1:5432/boundary?sslmode=disable". 이 값은 URL을 읽어올 디스크의 파일(file://), URL을 읽어올 환경 변수(env://), 또는 직접 데이터베이스 URL(postgres://)을 가리킬 수 있어요. 0.10.5부터 이 값은 데이터베이스 자격 증명의 순환(rotation)을 지원하기 위해 SIGHUP에서 다시 읽혀요.
    • migration_url — 마이그레이션에 다른 URL을 지정할 때 사용해요. 마이그레이션은 보통 더 높은 권한을 요구하기 때문이에요. 이 값은 URL을 읽어올 디스크의 파일(file://), URL을 읽어올 환경 변수(env://), 또는 직접 데이터베이스 URL(postgres://)을 가리킬 수 있어요.
    • max_open_connections — 컨트롤러가 열 수 있는 최대 연결 수를 제어해요. 필요한 최소 연결 수는 5개예요. 이 값을 0으로 설정하면 컨트롤러가 필요할 만큼 많은 연결을 열 수 있어요. 이 값은 최대 연결 수를 나타내는 문자열 또는 정수일 수 있고, 연결 수를 읽어올 파일(file://)이나 환경 변수(env://)를 가리키는 문자열일 수도 있어요.
    • max_idle_connections — 유휴 연결 풀의 최대 유휴 연결 수를 제어해요. max_open_connections이 0보다 크고 max_idle_connections보다 작으면 max_idle_connections이 max_open_connections 한도에 맞춰 줄어들어요. 이 값을 0으로 설정하면 유휴 연결을 유지하지 않아요. 설정하지 않거나 0보다 작게 설정하면 기본 sql.DB 설정을 사용해요. 이 값은 최대 연결 수를 나타내는 문자열 또는 정수일 수 있고, 파일(file://)이나 환경 변수(env://)를 가리키는 문자열일 수도 있어요.
    • max_idle_time — 연결이 유휴 상태로 있을 수 있는 최대 시간을 제어해요. 이 값을 0으로 설정하면 유휴 시간 때문에 연결이 닫히지 않아요. 설정하지 않거나 0보다 작게 설정하면 기본 sql.DB 설정을 사용해요. 이 값은 기간을 나타내는 문자열일 수 있고, 파일(file://)이나 환경 변수(env://)를 가리키는 문자열일 수도 있어요. 유효한 시간 단위는 Golang의 ParseDuration() 메서드가 명시하는 것들이에요.
  • public_cluster_addr — 워커가 이 컨트롤러에 도달할 수 있는 공개 호스트 또는 IP 주소, 그리고 선택적으로 포트를 지정해요. 각 컨트롤러는 자신만의 값을 설정해요. 클러스터의 공유 주소가 아니고, API 주소도 아니에요. 워커는 워커의 initial_upstreams 블록을 통한 초기 연결 이후에 이 파라미터를 사용해요. 그 첫 연결에서 컨트롤러는 현재 컨트롤러 주소 집합을 반환하는데, Boundary는 각 컨트롤러의 public_cluster_addr에서 또는 public_cluster_addr이 설정되지 않았을 때는 그 컨트롤러의 cluster 리스너 주소에서 이를 가져와요. 그러면 워커가 컨트롤러에 직접 연결하고 이들을 균형 있게(balance) 사용해요. 이 파라미터는 기본적으로 cluster 용도로 표시된 리스너의 주소로 설정돼요. 포트를 생략하면 Boundary는 기본 클러스터 포트 9201을 붙여요. 워커가 클러스터 리스너 주소로 컨트롤러에 도달할 수 없을 때 이 파라미터를 설정하세요. Amazon EIP처럼 호스트의 NIC에 직접 공개적으로 접근 가능한 IP를 바인딩하지 않는 클라우드 환경이나, 개별 컨트롤러 앞에 TCP 프록시가 있는 경우에 흔해요. 모든 컨트롤러를 같은 주소(예: 로드 밸런서 주소)로 설정하지 마세요. 그러면 워커가 개별 컨트롤러에 도달하지 못하고 클라이언트 측 로드 밸런싱이 무력화돼요. 이 파라미터를 initial_upstreams 및 로드 밸런서와 어떻게 조합하는지는 Load balancing Boundary controllers를 참고하세요. 이 값은 주소 문자열을 직접 쓸 수도 있고, 주소를 읽어올 디스크의 파일(file://), 주소를 읽어올 환경 변수(env://), 또는 go-sockaddr 템플릿일 수도 있어요. 주소에는 http://나 https:// 같은 프로토콜 접두어가 포함되지 않아야 해요.

  • license — Boundary Enterprise를 활성화하기 위한 라이선스 키 값이에요. HashiCorp 계정 팀이 엔터프라이즈 기능을 활성화하기 위한 라이선스를 보내줘요. 라이선스 키 원본을 넣거나, 라이선스 키를 담고 있는 파일의 디렉터리 경로를 넣을 수 있어요. 또는 라이선스를 환경 변수로 구성할 수도 있어요. 자세한 내용은 Boundary Enterprise licensing을 참고하세요.

  • auth_token_time_to_live — 모든 인증 토큰의 전역 최대 수명(TTL)이에요(모든 인증 방법의 모든 토큰에 적용돼요). 유효한 시간 단위는 Golang의 ParseDuration() 메서드가 명시하는 것들이에요. 기본값은 7일이에요.

  • auth_token_time_to_stale — 모든 인증 토큰의 전역 최대 비활성 시간이에요(모든 인증 방법의 모든 토큰에 적용돼요). 유효한 시간 단위는 Golang의 ParseDuration() 메서드가 명시하는 것들이에요. 기본값은 1일이에요.

  • scheduler — 컨트롤러에서 작업 스케줄러 동작을 지정하는 구성 블록이에요.

    • job_run_interval — 스케줄러가 실행해야 할 작업이 있는지 데이터베이스를 호출하는 간격이에요. 기본값은 1분이에요.
    • monitor_interval — 스케줄러가 다른 스케줄러에서 실행 중이던 종료된(defuncted) 작업을 확인하고 중단하는 간격이에요. 5분 동안 데이터베이스에 상태를 보고하지 않은 작업은 종료된 것으로 간주돼요. 작업이 중단되면 사용 가능한 첫 번째 컨트롤러에서 즉시 실행돼요. 기본값은 30초예요.
  • graceful_shutdown_wait_duration — 종료 신호를 받은 후 Boundary가 종료 절차를 시작하기 전에 기다리는 시간이에요. 이 상태에서 Boundary는 요청을 평소처럼 계속 처리하지만, 건강 상태(health) 요청에는 503 Service Unavailable로 응답해요. 이는 운영자가 로드 밸런서를 구성해 곧 사라질 Boundary 인스턴스로 새 트래픽을 사전에 보내지 않게 하려는 설계예요. 유효한 시간 단위는 Go의 ParseDuration() 메서드가 명시하는 것들이에요. ops 리스너가 설정되고 Controller가 존재할 때만 사용돼요. 기본값은 0초예요.

  • api_rate_limit — 컨트롤러 API 엔드포인트의 요청 비율에 제한을 설정해요. 이 설정은 한 번에 너무 많은 요청으로 리소스가 압도당하는 것을 막는 데 도움이 돼요. api_rate_limit 구성 스탠자는 다음 필드를 포함해요.

    • resources — 요청 비율을 제한하려는 Boundary 리소스를 지정해요. 예를 들어 리소스는 target이나 credential-library일 수 있어요. 와일드카드 "*"를 사용해 모든 리소스를 포함할 수 있어요.
    • actions — 리소스에서 제한하려는 동작을 지정해요. 예를 들어 동작은 create, list, authorize-session일 수 있어요. 와일드카드 "*"를 사용해 모든 동작을 포함할 수 있어요.
    • per — 제한이 어떻게 할당되는지 지정해요. 다음 값 중에서 선택할 수 있어요. total — 인증 토큰이나 IP 주소와 관계없이 모든 요청을 셈해요. ip-address — IP 주소별로 요청을 셈해요. 이 값으로 IP 주소별 요청을 제한할 수 있어요. auth-token — 사용자의 인증 토큰별로 요청을 셈해요. 이 값으로 인증 토큰별 요청을 제한할 수 있어요. unlimited도 함께 구성된 경우에만 와일드카드 "*"를 사용해 모든 값을 포함할 수도 있어요.
    • limit — period 안에 허용되는 요청 수를 지정해요.
    • period — limit에 대한 시간 창을 지정해요. 이 기간이 지나면 제한이 재설정돼요.
    • unlimited — 해당 리소스와 동작에 요청 비율을 제한하지 않음을 나타내요. 이 값을 true로 설정하면 limit과 period 값을 지정해서는 안 돼요. 지정하면 오류를 받게 돼요. API 비율 제한이 어떻게 동작하는지에 대한 자세한 내용은 API rate limiting 문서를 참고하세요.
  • api_rate_limit_disable — true로 설정하면 API 비율 제한을 비활성화해요. api_rate_limit_disable을 true로 설정하면서 api_rate_limit 스탠자를 제공하면 오류를 받아요.

  • api_rate_limit_max_quotas — Boundary가 허용하는 최대 API 비율 제한 할당량(quota) 수를 지정해요.

  • max_page_size — 페이지네이션할 때 허용되는 최대 페이지 크기예요. 사용자가 이 수보다 큰 페이지 크기를 지정하면 이 수로 잘려요(truncate). 페이지 크기를 명시적으로 지정하지 않는 요청의 기본 페이지 크기로도 사용돼요. 기본값은 1000이에요.

시그널

SIGHUP 시그널은 컨트롤러가 구성 파일을 다시 로드해 database url 값에 대한 갱신을 반영하게 해요. 그 외 갱신된 값은 무시돼요.

SIGTERM과 SIGINT 시그널은 컨트롤러에서 정상 종료(graceful shutdown)를 시작해요. 정상 종료는 컨트롤러를 종료하기 전에 리스너와 서버를 닫아요.

KMS 구성

컨트롤러는 root와 worker-auth purpose를 위한 두 개의 KMS 스탠자가 필요해요.

# Root KMS configuration block: this is the root key for Boundary
# Use a production KMS such as AWS KMS in production installs
kms "aead" {
  purpose = "root"
  aead_type = "aes-gcm"
  key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung="
  key_id = "global_root"
}

# Worker authorization KMS
# Use a production KMS such as AWS KMS for production installs
# This key is the same key used in the worker configuration
kms "aead" {
  purpose = "worker-auth"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
  key_id = "global_worker-auth"
}

그리고 선택적으로 recovery purpose를 위한 KMS 스탠자도 필요해요.

# Recovery KMS block: configures the recovery key for Boundary
# Use a production KMS such as AWS KMS for production installs
kms "aead" {
  purpose = "recovery"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
  key_id = "global_recovery"
}

그리고 선택적으로 구성 암호화(configuration encryption) purpose를 위한 KMS 스탠자도 있어요.

# Configuration encryption block: decrypts sensitive values in the
# configuration file. See `boundary config [encrypt|decrypt] -h`.
kms "aead" {
  purpose = "config"
  aead_type = "aes-gcm"
  key = "7xtkEoS5EXPbgynwd+dDLHopaCqK8cq0Rpep4eooaTs="
}

그리고 선택적으로 세션 녹화(session recording) 기능을 활성화하기 위한 KMS 스탠자도 있어요.

# BSR encryption block: encrypts data and checks the integrity
# of session recordings. If you do not add a BSR key to your
# controller configuration, you cannot enable session recording.
kms "aead" {
  purpose = "bsr"
  aead_type = "aes-gcm"
  key = "[email protected]#4iyHAd:TpgjuwC/;J;"
  key_id = "session_recording"
}

Boundary는 다양한 종류의 KMS 통합을 지원해요. 사용 가능한 모든 KMS 유형에 대한 완전한 가이드는 KMS documentation을 참고하세요.

완전한 구성 예시

# Disable memory lock: https://www.man7.org/linux/man-pages/man2/mlock.2.html
disable_mlock = true

# Controller configuration block
controller {
  # This name attr must be unique across all controller instances if running in HA mode
  name = "demo-controller-1"
  description = "A controller for a demo!"

  # Path to a valid license to enable Boundary Enterprise.
  license = "file:///folder_path/license.hclic"

  # After receiving a shutdown signal, Boundary will wait 10s before initiating the shutdown process.
  graceful_shutdown_wait_duration = "10s"

  # Database URL for postgres. This can be a direct "postgres://"
  # URL, or it can be "file://" to read the contents of a file to
  # supply the url, or "env://" to name an environment variable
  # that contains the URL.
  database {
      url = "postgresql://boundary:***@postgres.yourdomain.com:5432/boundary"
  }

  # Rate limiting examples to conserve controller resources
  # total limit for all resources and actions
  api_rate_limit {
    resources = ["*"]
    actions   = ["*"]
    per     = "total"
    limit   = 500
    period  = "1s"
  }

  # Limit for ip addresses to all resources+actions to prevent a malicious
  # host that is fabricating tokens, or spamming unauthed endpoints
  api_rate_limit {
    resources = ["*"]
    actions   = ["*"]
    per     = "ip-address"
    limit   = 100
    period  = "1s"
  }

  # Limit of all authed requests, to prevent one user consuming all of the total limit
  api_rate_limit {
    resources = ["*"]
    actions   = ["*"]
    per     = "auth-token"
    limit   = 100
    period  = "1s"
  }
}

# API listener configuration block
listener "tcp" {
  # Should be the address of the NIC that the controller server will be reached on
  address = "10.0.0.1"
  # The purpose of this listener block
  purpose = "api"

  tls_disable = false

  # Uncomment to enable CORS for the Admin UI. Be sure to set the allowed origin(s)
  # to appropriate values.
  #cors_enabled = true
  #cors_allowed_origins = ["https://yourcorp.yourdomain.com", "serve://boundary"]
}

# Data-plane listener configuration block (used for worker coordination)
listener "tcp" {
  # Should be the IP of the NIC that the worker will connect on
  address = "10.0.0.1"
  # The purpose of this listener
  purpose = "cluster"
}

listener "tcp" {
  # Should be the address of the NIC where your external systems'
  # (eg: Load-Balancer) will connect on.
  address = "10.0.0.1"
  # The purpose of this listener block
  purpose = "ops"

  tls_disable = false
}

# Root KMS configuration block: this is the root key for Boundary
# Use a production KMS such as AWS KMS in production installs
kms "aead" {
  purpose = "root"
  aead_type = "aes-gcm"
  key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung="
  key_id = "global_root"
}

# Worker authorization KMS
# Use a production KMS such as AWS KMS for production installs
# This key is the same key used in the worker configuration
kms "aead" {
  purpose = "worker-auth"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
  key_id = "global_worker-auth"
}

# Recovery KMS block: configures the recovery key for Boundary
# Use a production KMS such as AWS KMS for production installs
kms "aead" {
  purpose = "recovery"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
  key_id = "global_recovery"
}

# BSR encryption block: encrypts data and checks the integrity
# of session recordings. If you do not add a BSR key to your
# controller configuration, you cannot enable session recording.
kms "aead" {
  purpose = "bsr"
  aead_type = "aes-gcm"
  key = "[email protected]#4iyHAd:TpgjuwC/;J;"
  key_id = "session_recording"
}