rate limit quota 만들기

rate limit quota 만들기

Vault의 rate limit quota를 사용하면 Vault 관리자가 대상 namespace, mount, path 또는 role에 한도를 설정해 트래픽이 Vault 클러스터로 들어오는 방식을 제어할 수 있습니다. 이는 Community 및 Enterprise 에디션 모두에서 사용할 수 있는 Vault 핵심 기능 세트의 일부입니다.

출처: 문서

본문

Community vs. Enterprise rate limit quota의 기본 동작은 rate limit을 적용하기 위해 수신 요청을 소스 IP 주소를 기준으로 그룹화하는 것입니다. 이는 Vault Community Edition의 유일한 사용 가능한 모드입니다. Vault Enterprise는 추가 모드를 제공합니다. 추가 기능에 대해 알아보려면 Rate limit quotas - collective, by IP, by entity 페이지를 읽어보세요.

시작하기 전에

  • Vault 인스턴스의 root 또는 관리 namespace에 접근 권한이 있는지 확인하세요. rate limit quota를 수정하는 것은 제한된 활동입니다.

1단계: 적절한 세분성(granularity) 결정

rate limit의 세분성은 Vault 클러스터의 성능에 영향을 줄 수 있습니다. 특히 rate limit으로 인해 거부되는 요청 수가 급격히 늘어나면 audit 로깅 증가가 Vault 성능에 영향을 줄 수 있습니다.

2단계: audit 로그 활성화

기본적으로 rate limit quota 위반으로 거부된 요청은 audit 로그에 기록되지 않습니다. 따라서 추적 가능성을 위해 거부된 요청을 로깅하려면 sys/quotas/config 엔드포인트에 대해 enable_rate_limit_audit_loggingtrue로 설정해야 합니다. lease count quota에 도달해 거부된 요청은 항상 로깅되므로 파라미터를 설정할 필요가 없습니다.

성능 고려 사항 rate limit audit 로깅을 활성화하면 거부된 요청의 양이 많을 때 Vault 성능에 영향을 줄 수 있습니다.

  • /var/log/vault-audit.log(또는 원하는 파일 위치)로 출력하는 파일 audit 디바이스를 활성화합니다.
$ vault audit enable file file_path="/var/log/vault-audit.log"
  • rate limit quota에 대한 audit 로깅을 활성화하려면 다음 명령을 실행합니다.
$ vault write sys/quotas/config enable_rate_limit_audit_logging=true
  • quota 구성을 읽어 확인합니다.
$ vault read sys/quotas/config

Key                                   Value
---                                   -----
absolute_rate_limit_exempt_paths      []
enable_rate_limit_audit_logging       true
enable_rate_limit_response_headers    false
rate_limit_exempt_paths               []
  • 파일 audit 디바이스를 활성화합니다.

먼저 audit 로그 경로가 /var/log/vault-audit.log(또는 원하는 파일 위치)로 지정된 HTTP 요청 페이로드를 만듭니다.

$ tee audit-payload.json <<EOF
{
  "type": "file",
  "options": {
      "file_path": "/var/log/vault-audit.log"
  }
}
EOF

sys/audit 엔드포인트를 사용해 파일 audit 로그를 활성화합니다.

$ curl --header "X-Vault-Token: $VAULT_TOKEN" \
    --request POST \
    --data @audit-payload.json \
    $VAULT_ADDR/v1/sys/audit/file

대상 file_path를 원하는 위치로 설정하세요.

  • rate limit quota audit 로깅을 활성화하는 HTTP 요청 페이로드를 만듭니다.
$ tee payload.json <<EOF
{
   "enable_rate_limit_audit_logging": true
}
EOF
  • sys/quotas/config 엔드포인트를 호출합니다.
$ curl --header "X-Vault-Token: $VAULT_TOKEN" \
    --request POST \
    --data @payload.json \
    $VAULT_ADDR/v1/sys/quotas/config
  • quota 구성을 읽어 확인합니다.
$ curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
    $VAULT_ADDR/v1/sys/quotas/config | jq -r ".data"

예시 출력:

{
   "absolute_rate_limit_exempt_paths": [],
   "enable_rate_limit_audit_logging": true,
   "enable_rate_limit_response_headers": false,
   "rate_limit_exempt_paths": []
}

3단계: rate limit quota 만들기

다음 파라미터를 사용해 rate limit quota를 만듭니다:

  • name (string: "") - quota 규칙의 이름

  • path (string: "") - quota 규칙을 적용할 대상 namespace, mount 또는 path입니다. *로 끝날 수 있습니다(예: auth/token/create*). 빈 path는 전역 rate limit quota를 구성합니다.

  • rate float - 허용되는 초당 요청 수(RPS)의 속도

  • role (string: "") - 이 quota를 적용할 로그인 role입니다. 이 파라미터를 설정할 때는 role 개념이 있는 유효한 auth method로 path를 구성해야 합니다.

  • interval (int: 0) - rate limiting을 적용할 기간(기본값은 1초)

  • block_interval (string: "") - 설정하면 클라이언트가 rate limit 임계값에 도달했을 때 block_interval이 경과할 때까지 Vault가 클라이언트의 추가 요청을 금지합니다.

  • inheritable (boolean: false) -

    Enterprise quota 규칙을 하위 namespace에 적용할지 여부를 결정합니다.

  • group_by (string: "") -

    Enterprise 수신 요청을 그룹화하는 방법을 정의합니다. 자세한 내용은 identity-based rate limit quotas를 참고하세요.

  • secondary_rate (float: 0.0)

    Enterprise group_by 모드 entity_then_ip 또는 entity_then_none에만 설정할 수 있습니다. "ip" 또는 "none" 그룹에 속하는 요청에 적용되는 rate limit이며, 엔티티 ID를 포함한 인증된 요청은 대신 rate 필드의 적용을 받습니다. 기본값은 rate와 같은 값입니다.

vault writesys/quotas/rate-limit/{quota-name} 경로를 사용해 새 rate limit quota를 만듭니다.

$ vault write sys/quotas/rate-limit/<QUOTA_NAME> \
    name="<QUOTA_RULE_NAME>" \
    path="<TARGET_PATH>" \
    rate=<ALLOWED_REQUEST_RATE> \
    role="<ROLE_NAME>" \
    interval=<DURATION_OF_RATE_LIMIT> \
    block_interval=<DURATION_TO_BLOCK_REQUESTS> \
    inheritable=<BOOLEAN> \

예시: Vault 클러스터에 적용되는 rate limit quota를 만듭니다.

  • 인바운드 워크로드를 초당 100개 요청으로 제한하는 "global-rate"라는 rate limit quota를 만듭니다.
$ vault write sys/quotas/rate-limit/global-rate rate=100
Success! Data written to: sys/quotas/rate-limit/global-rate
  • global-rate 규칙을 읽어 구성이 올바른지 확인합니다.
$ vault read sys/quotas/rate-limit/global-rate

Key               Value
---               -----
block_interval    0
group_by          ip
inheritable       true
interval          1
name              global-rate
path              n/a
rate              100
role              n/a
type              rate-limit

참고 path가 없으면 이 quota 규칙은 특정 mount나 namespace 대신 전역 수준에 적용됩니다.

예시: Transit secrets engine에 대한 접근을 분당(60초) 1,000개 요청으로 제한하는 "transit-limit"라는 rate limit quota를 만듭니다. 요청을 소스 IP 주소별로 그룹화합니다.

  • transit에 Transit secrets engine을 활성화합니다.
$ vault secrets enable transit
Success! Enabled the transit secrets engine at: transit/
  • rate limit quota를 만듭니다.
$ vault write sys/quotas/rate-limit/transit-limit \
   path="transit" \
   rate=1000 \
   interval=60

출력:

Success! Data written to: sys/quotas/rate-limit/transit-limit
  • transit-limit 규칙을 읽어 구성이 올바른지 확인합니다.
$ vault read sys/quotas/rate-limit/transit-limit

출력:

Key               Value
---               -----
block_interval    0
group_by          ip
inheritable       true
interval          60
name              transit-limit
path              transit/
rate              1000
role              n/a
type              rate-limit

경로 세분성(Path granularity)

path를 마운트 지점(이 예시에서는 transit/)보다 더 깊게 설정할 수 있습니다.

예시: orders 키를 사용하는 데이터 암호화 요청을 초당 500개로 제한하는 "transit-order"라는 rate limit quota를 만듭니다.

  • "orders"라는 암호화 키를 만듭니다.
$ vault write -f transit/keys/orders

Key                       Value
---                       -----
allow_plaintext_backup    false
auto_rotate_period        0s
deletion_allowed          false
derived                   false
exportable                false
imported_key              false
keys                      map[1:1695147293]
latest_version            1
min_available_version     0
min_decryption_version    1
min_encryption_version    0
name                      orders
supports_decryption       true
supports_derivation       true
supports_encryption       true
supports_signing          false
type                      aes256-gcm96
  • "transit-order" rate limit quota를 만듭니다.
$ vault write sys/quotas/rate-limit/transit-order \
   path="transit/encrypt/orders" \
   rate=500

출력:

Success! Data written to: sys/quotas/rate-limit/transit-order
  • rate limit quota 구성을 확인합니다.
$ vault read sys/quotas/rate-limit/transit-order

출력:

Key               Value
---               -----
block_interval    0
group_by          ip
inheritable       true
interval          1
name              transit-order
path              transit/encrypt/orders
rate              500
role              n/a
type              rate-limit

Vault Enterprise namespaces

Vault Enterprise 클러스터의 경우 inheritable 파라미터를 사용해 namespace에 설정된 리소스 quota를 그 하위 namespace에 적용할 수 있습니다.

다음 namespace 계층 구조를 생각해 보세요:

root
   └── parent
      └── child
         └── grand-child

root namespace 아래에 parent namespace가 있고, 그 다음 parent/childparent/child/grand-child namespaces가 있습니다.

inheritable 파라미터를 true로 설정하면 parent namespace에 리소스 quota를 설정해 하위 namespaces에 상속되게 적용할 수 있습니다. 기본값은 false입니다.

  • 하위 namespaces가 상속할 us-west namespace에 quota 규칙을 만듭니다. rate limit은 분당 500개 요청입니다.
$ vault write sys/quotas/rate-limit/us-west \
   path="us-west" \
   rate=500 \
   interval=1m \
   inheritable=true

출력:

Success! Data written to: sys/quotas/rate-limit/us-west
  • quota 규칙을 확인합니다.
$ vault read sys/quotas/rate-limit/us-west

Key               Value
---               -----
block_interval    0
group_by          ip
inheritable       true
interval          60
name              us-west
path              us-west/
rate              500
role              n/a
type              rate-limit

quota 설정이 포함된 페이로드 파일을 만들고 sys/quotas/rate-limit/{quota-name} 엔드포인트를 호출합니다.

{
  "name": "<QUOTA_RULE_NAME>",
  "path": "<TARGET_PATH>",
  "rate": <ALLOWED_REQUEST_RATE>,
  "role": "<ROLE_NAME>",
  "interval": <DURATION_OF_RATE_LIMIT>,
  "block_interval": <DURATION_TO_BLOCK_REQUESTS>,
  "inheritable": <BOOLEAN>
}

예시: 인바운드 워크로드를 초당 100개 요청으로 제한하는 "global-rate"라는 rate limit quota를 만듭니다.

  • sys/quotas/rate-limit 엔드포인트를 호출합니다.
$ curl --header "X-Vault-Token: $VAULT_TOKEN" \
    --request POST \
    --data '{ "rate": 100 }' \
    $VAULT_ADDR/v1/sys/quotas/rate-limit/global-rate
  • 새로 만든 global-rate quota 규칙을 읽습니다.
$ curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
    $VAULT_ADDR/v1/sys/quotas/rate-limit/global-rate | jq -r ".data"

출력:

{
   "block_interval": 0,
   "group_by": "ip",
   "inheritable": true,
   "interval": 1,
   "name": "global-rate",
   "path": "",
   "rate": 100,
   "role": "",
   "type": "rate-limit"
}

참고 path가 없으면 이 quota 규칙은 특정 mount나 namespace 대신 root namespace에 적용됩니다.

예시: Transit secrets engine에 대한 접근을 분당(60초) 1000개 요청으로 제한하는 "transit-limit"라는 rate limit quota를 만듭니다.

  • transit에 Transit secrets engine을 활성화합니다.
$ curl --header "X-Vault-Token: $VAULT_TOKEN" \
    --request POST \
    --data '{"type":"transit"}' \
    $VAULT_ADDR/v1/sys/mounts/transit
  • "transit-limit" rate limit quota를 만듭니다.
$ curl --header "X-Vault-Token: $VAULT_TOKEN" \
   --request POST \
   --data '{"path": "transit", "rate": 1000, "interval": 60 }' \
   $VAULT_ADDR/v1/sys/quotas/rate-limit/transit-limit
  • transit-limit 규칙을 읽어 구성이 올바른지 확인합니다.
$ curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
   $VAULT_ADDR/v1/sys/quotas/rate-limit/transit-limit | jq -r ".data"

출력:

{
   "block_interval": 0,
   "group_by": "ip",
   "inheritable": true,
   "interval": 60,
   "name": "transit-limit",
   "path": "transit/",
   "rate": 1000,
   "role": "",
   "type": "rate-limit"
}

경로 세분성

path를 마운트 지점(이 예시에서는 transit/)보다 더 깊게 설정할 수 있습니다.

예시: orders 키를 사용하는 데이터 암호화 요청을 초당 500개로 제한하는 "transit-order"라는 rate limit quota를 만듭니다.

  • "orders"라는 암호화 키를 만듭니다.
$ curl --header "X-Vault-Token: $VAULT_TOKEN" \
    --request POST \
    $VAULT_ADDR/v1/transit/keys/orders
  • "transit-order" rate limit quota를 만듭니다.
$ curl --header "X-Vault-Token: $VAULT_TOKEN" \
   --request POST \
   --data '{ "path": "transit/encrypt/orders", "rate": 500 }' \
   $VAULT_ADDR/v1/sys/quotas/rate-limit/transit-order
  • rate limit quota 구성을 확인합니다.
$ curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
   $VAULT_ADDR/v1/sys/quotas/rate-limit/transit-order | jq -r ".data"

출력:

{
   "block_interval": 0,
   "group_by": "ip",
   "inheritable": true,
   "interval": 1,
   "name": "transit-order",
   "path": "transit/encrypt/orders",
   "rate": 500,
   "role": "",
   "type": "rate-limit"
}

Vault Enterprise namespaces

Vault Enterprise 클러스터의 경우 inheritable 파라미터를 사용해 namespace에 설정된 리소스 quota를 그 하위 namespace에 적용할 수 있습니다.

다음 namespace 계층 구조를 생각해 보세요:

root
   └── parent
      └── child
         └── grand-child

root namespace 아래에 parent namespace가 있고, 그 다음 parent/childparent/child/grand-child namespaces가 있습니다.

inheritable 파라미터를 true로 설정하면 parent namespace에 리소스 quota를 설정해 하위 namespaces에 상속되게 적용할 수 있습니다. 기본값은 false입니다.

  • 하위 namespace가 상속할 us-west namespace에 quota 규칙을 만듭니다. rate limit은 분당 500개 요청입니다.
$ curl --header "X-Vault-Token: $VAULT_TOKEN" \
   --request POST \
   --data '{"path": "us-west", "rate": 500, "interval": 60, "inheritable": true }' \
   $VAULT_ADDR/v1/sys/quotas/rate-limit/us-west
  • quota 규칙을 확인합니다.
$ curl -s --header "X-Vault-Token: $VAULT_TOKEN" \
   $VAULT_ADDR/v1/sys/quotas/rate-limit/us-west | jq -r ".data"

출력:

{
   "block_interval": 0,
   "group_by": "ip",
   "inheritable": true,
   "interval": 60,
   "name": "us-west",
   "path": "us-west/",
   "rate": 500,
   "role": "",
   "type": "rate-limit"
}

HashiCorp Terraform을 사용해 rate limit quota를 설정할 수 있습니다.

예시:

  • main.tf라는 파일을 다음 내용으로 만듭니다.
# Use Vault provider
provider vault {}

# Create "global-rate" which limits inbound workload to 100 requests per second
resource "vault_quota_rate_limit" "global" {
   name = "global-rate"
   path = ""
   rate = 100
}

# Create "transit-limit" which limits the access to the Transit secrets engine to be 1000 requests per minute (60 seconds)
resource "vault_quota_rate_limit" "transit-limit" {
   name = "transit-limit"
   path = "transit/"
   rate = 1000
   interval = 60

   depends_on = [ vault_mount.transit ]
}

# Path granularity: Create a rate limit quota, "transit-order" to limit the data encryption requests using orders key to be 500 per second
resource "vault_quota_rate_limit" "transit-order" {
   name = "transit-order"
   path = "transit/encrypt/orders"
   rate = 500

depends_on = [ vault_mount.transit, vault_transit_secret_backend_key.key ]
}

# Enable transit secrets engine & create a test key
resource "vault_mount" "transit" {
   path                      = "transit"
   type                      = "transit"
   description               = "Test resource quota"
}

resource "vault_transit_secret_backend_key" "key" {
   backend = vault_mount.transit.path
   name    = "orders"
}

main.tf는 다음 작업을 수행합니다:

  • 인바운드 워크로드를 초당 100개 요청으로 제한하는 "global-rate"라는 rate limit quota를 만듭니다(5-9줄).

  • Transit secrets engine에 대한 접근을 분당 1000개 요청으로 제한하는 "transit-limit"라는 rate limit quota를 만듭니다(12-19줄).

  • orders 키를 사용하는 데이터 암호화 요청을 초당 500개로 제한하는 "transit-order"라는 rate limit quota를 만듭니다(22-28줄).

  • 테스트를 위해 transit secrets engine을 활성화합니다(31-35줄).

  • 테스트를 위해 orders라는 암호화 키를 만듭니다(37-40줄).

  • Terraform을 초기화합니다.

$ terraform init

Initializing the backend...

Initializing provider plugins...
...snip...

Terraform has been successfully initialized!
  • terraform init 실행 후 terraform plan으로 리소스가 생성될지 확인할 수 있습니다.
$ terraform plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
...snip...

Plan: 5 to add, 0 to change, 0 to destroy.
  • 출력에 리소스가 나열되는지 확인해야 합니다.

  • terraform apply로 리소스를 배포합니다.

$ terraform apply -auto-approve

Terraform used the selected providers to generate the following execution plan.
...snip...
Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

Terraform에 대해 더 알아보려면 Terraform tutorials 사이트를 방문하세요.

Vault Enterprise namespaces

Vault Enterprise 클러스터의 경우 inheritable 파라미터를 사용해 namespace에 설정된 리소스 quota를 그 하위 namespace에 적용할 수 있습니다.

다음 namespace 계층 구조를 생각해 보세요:

root
   └── parent
      └── child
         └── grand-child

root namespace 아래에 parent namespace가 있고, 그 다음 parent/childparent/child/grand-child namespaces가 있습니다.

inheritable 파라미터를 true로 설정하면 parent namespace에 리소스 quota를 설정해 하위 namespaces에 상속되게 적용할 수 있습니다. 기본값은 false입니다.

Terraform을 사용해 하위 namespaces가 상속할 us-west namespace에 quota 규칙을 만들 수 있습니다. 다음 Terraform 구성은 rate limit을 분당 500개 요청으로 설정합니다.

provider vault {}

# Create a "us-west" namespace
resource "vault_namespace" "us-west" {
   path = "us-west"
}

# Create a "us-west" rate limit quota
resource "vault_quota_rate_limit" "us-west" {
  name = "us-west"
  path = "us-west"
  rate = 500
  interval = 60
  inheritable = true
}

다음 단계

사전 예방적 모니터링과 주기적인 사용 분석은 문제가 악화되기 전에 잠재적 문제를 식별하는 데 도움이 됩니다.

  • 일반적인 Vault 리소스 quota에 대해 자세히 알아보세요.
  • Vault Enterprise의 lease count quota에 대해 알아보세요.
  • Vault Enterprise 클러스터를 실행 중이라면 Rate limit quotas - collective, by IP, by entity를 검토하세요.

더 알아보기