Vault 프록시 캐싱 개요
Vault 프록시 캐싱 개요
Vault 프록시 캐싱은 새로 생성된 토큰을 담은 응답과, 이 새로 생성된 토큰에서 파생된 임대 시크릿을 담은 응답의 클라이언트 측 캐싱을 지원합니다. 캐시된 토큰과 임대의 갱신도 프록시가 관리합니다. 추가로 cache_static_secrets를 true로 설정하면 Vault 프록시가 KVv1 및 KVv2 시크릿을 캐시하도록 구성할 수 있습니다.
캐싱과 갱신
동적 시크릿에 대한 응답 캐싱과 갱신은 프록시가 아래 특정 상황에서만 관리합니다.
- 토큰 생성 요청이 프록시를 통해 이루어집니다. 즉, 다양한 인증 방법으로 수행된 로그인 작업과, 프록시를 통한 토큰 인증 방법의 토큰 생성 엔드포인트 호출은 그 응답이 프록시에 캐시됩니다. 새 토큰을 담은 응답은 부모 토큰이 이미 프록시에 의해 관리되고 있거나, 새 토큰이 고아(orphan) 토큰인 경우에만 프록시에 캐시됩니다.
- 임대 시크릿 생성 요청이 프록시에 이미 관리되고 있는 토큰을 사용해 프록시를 통해 이루어집니다. 즉, 프록시가 관리하는 토큰으로 발급되는 동적 자격 증명은 캐시되며 그 갱신도 처리됩니다.
정적 시크릿 캐싱
Vault 프록시가 동적 시크릿과 정적(KVv1 및 KVv2) 시크릿을 모두 캐시하도록 구성할 수 있습니다. 정적 시크릿에 대한 캐싱을 켜면, 프록시는 시크릿의 캐시 항목을 유지하되 그 시크릿에 접근할 수 있는 토큰으로 만들어진 요청에만 캐시된 응답을 제공합니다. 그 결과, 같은 KV 시크릿에 대한 여러 Vault 프록시 요청은 단 한 번의 최초 요청만 Vault로 전달되면 됩니다.
정적 시크릿 캐싱은 기본적으로 꺼져 있습니다. 정적 시크릿에 대한 캐싱을 켜려면 자동 인증(auto-auth)을 구성하고, 자동 인증 토큰에 KV 이벤트 업데이트를 구독할 권한이 있는지 확인해야 합니다.
구성이 끝나면 프록시는 자동 인증 토큰을 사용해 KV 이벤트를 구독하고, 구독 피드를 모니터링해 캐시의 시크릿을 언제 갱신할지 파악합니다.
정적 시크릿 캐싱에 대한 자세한 내용은 Vault 프록시 정적 시크릿 캐싱 개요를 참고하세요.
영속 캐시(Persistent cache)
Vault 프록시는 이전 Vault 프록시 프로세스가 만든 영속 캐시 파일에서 토큰, 임대, 정적 시크릿 같은 시크릿을 복원할 수 있습니다.
이 기능에 대한 자세한 내용은 Vault 프록시 영속 캐싱 페이지를 참고하세요.
캐시 퇴거(Cache evictions)
동적 시크릿 관련 캐시 항목의 퇴거는 프록시가 더 이상 그 시크릿을 갱신할 수 없을 때 일어납니다. 이는 시크릿이 최대 TTL에 도달했거나 갱신이 오류를 낼 때 발생할 수 있습니다.
Vault 프록시는 특정 요청 유형과 응답 코드를 관찰해 최선의 노력(best-effort) 방식으로 캐시를 퇴거합니다. 예를 들어 프록시를 통해 토큰 폐기 요청이 이루어지고 Vault 서버로의 전달 요청이 성공하면, 프록시는 폐기된 토큰과 연관된 모든 캐시 항목을 퇴거합니다. 마찬가지로 어떤 임대 폐기 작업도 프록시가 가로채고 해당 캐시 항목이 퇴거됩니다.
프록시는 시크릿 만료 시와 폐기 요청 가로채기 시 캐시 항목을 퇴거하지만, 클라이언트가 Vault 서버와 직접 상호작용해 일어난 폐기를 프록시가 전혀 인지하지 못할 수도 있습니다. 이는 캐시에 오래된 항목이 남을 가능성을 만듭니다. 캐시의 오래된 항목을 관리하기 위해, 캐시 항목을 색인할 때 사용되는 일부 쿼리 기준에 따라 캐시 항목을 수동으로 퇴거할 수 있는 엔드포인트 /proxy/v1/cache-clear(아래 참조)가 제공됩니다.
요청 고유성(Request uniqueness)
반복 요청을 감지하고 캐시된 응답을 반환하기 위해 프록시는 요청을 고유하게 식별할 방법이 필요합니다. 현재 이 계산은 단순한 접근 방식(향후 변경될 수 있음)으로, HTTP 요청을 모든 헤더와 요청 본문과 함께 직렬화해 해싱합니다. 이 해시 값은 응답이 즉시 사용 가능한지 확인하기 위한 캐시 인덱스로 사용됩니다. 이 접근 방식의 결과로, 요청의 어떤 데이터든 수정되면 요청의 해시 값이 달라집니다. 예를 들어 요청 매개변수의 순서가 바뀌면 오탐(false negative)이 발생하는 부작용이 있습니다. 요청이 변경 없이 들어오는 한 캐싱 동작은 일관적이어야 합니다. 값의 순서가 다르게 정렬된 동일한 요청은 중복된 캐시 항목을 만들게 됩니다. 클라이언트가 일관된 메커니즘으로 요청해 요청마다 일관된 해시 값을 만들어 낼 것이라는 휴리스틱 가정이 캐싱 기능의 기반입니다.
갱신 관리(Renewal management)
토큰과 임대는 Vault 서버의 Go API를 통해 제공되는 시크릿 갱신기(renewer)를 사용해 프록시가 갱신합니다. 프록시는 모든 작업을 메모리에서 수행하며 어떤 것도 저장소에 영속화하지 않습니다. 즉, 프록시가 종료되면 모든 갱신 작업이 즉시 중단되고, 나중에 갱신을 재개할 방법이 없습니다. 프록시 종료가 시크릿의 폐기를 의미하는 것은 아니며, 단지 유효하고 폐기되지 않은 모든 시크릿에 대한 갱신 책임을 더 이상 Vault 프록시가 수행하지 않는다는 뜻입니다.
API
캐시 비우기(Cache clear)
이 엔드포인트는 주어진 기준에 따라 캐시를 비웁니다. 이 API를 사용하려면 프록시가 값을 어떻게 캐시하는지에 대한 정보를 미리 알아야 합니다. 프록시에 캐시된 각 응답은 요청 유형에 따라 일부 요소로 색인됩니다. 그 요소에는 캐시된 응답에 속한 token, 캐시된 응답에 속한 토큰의 token_accessor, 캐시된 응답을 만든 request_path, 캐시된 응답에 붙은 lease, 캐시된 응답이 속한 namespace 등이 있습니다. 이 API는 연관된 캐시 항목을 가져와 퇴거할 수 있는 일부 요소를 노출합니다. 캐싱이 활성화되지 않은 리스너의 경우에도 이 API는 사용 가능하지만, 아무것도 하지 않고(비울 캐시가 없으므로) 200 응답을 반환합니다.
| Method | Path | Produces |
|---|---|---|
POST |
/proxy/v1/cache-clear |
200 application/json |
매개변수
type(strings: required)— 퇴거할 캐시 항목의 유형입니다. 유효한 값은request_path,lease,token,token_accessor,all입니다.type이all이면 전체 캐시가 비워집니다.value(string: required)— 선택한type에 대한 정확한 값 또는 값의 접두어입니다.type이all일 때는 이 매개변수가 선택 사항입니다.namespace(string: optional)—type이request_path일 때만 적용됩니다. 주어진 요청 경로에 대해 퇴거할 캐시 항목이 속한 네임스페이스입니다.
예시 페이로드
{
"type": "token",
"value": "hvs.rlNjegSKykWcplOkwsjd8bP9"
}
예시 요청
$ curl \
--request POST \
--data @payload.json \
http://127.0.0.1:1234/proxy/v1/cache-clear
구성 (cache)
최상위 cache 블록이 어떤 형태로든 존재하면(빈 cache 블록 포함) 캐시가 활성화됩니다. cache_static_secrets가 true이거나 disable_caching_dynamic_secrets가 false여야 동작하며, 그렇지 않으면 캐시가 아무것도 하지 않습니다. 최상위 cache 블록에는 다음 구성 항목이 있습니다.
persist(object: optional)— 영속 캐시의 구성입니다.cache_static_secrets(bool: false)—true일 때 정적 시크릿 캐싱을 켭니다.disable_caching_dynamic_secrets(bool: false)—true일 때 동적 시크릿 캐싱을 끕니다.
참고: cache 블록이 정의되면 구성에 리스너도 정의되어야 합니다. 그렇지 않으면 캐시를 활용할 방법이 없습니다.
구성 (Persist)
persist 블록 안에 있는 공통 구성 값입니다.
type(string: required)— 사용할 영속 캐시의 유형입니다. 예:kubernetes. 참고: HCL을 사용할 때는 블록의 키로 사용할 수 있습니다. 예:persist "kubernetes" {...}. 현재는kubernetes만 지원됩니다.path(string: required)— 영속 캐시 파일을 만들거나 복원할 디스크 경로입니다.keep_after_import(bool: optional)—true로 설정하면 복원된 캐시 파일이 삭제되지 않습니다. 기본값은false입니다.exit_on_err(bool: optional)—true로 설정하면 영속 캐시 복원 중 오류가 발생할 때 Vault 프록시가 오류와 함께 종료됩니다. 기본값은true입니다.service_account_token_file(string: optional)—type이kubernetes일 때, Kubernetes 서비스 계정 토큰을 찾을 수 있는 디스크 경로를 구성합니다. 기본값은/var/run/secrets/kubernetes.io/serviceaccount/token입니다.
구성 (listener)
listener(array of objects: required)— 리스너의 구성입니다.
최상위에 하나 이상의 listener 블록이 있을 수 있습니다. 리스너를 추가하면 API 프록시가 켜지고, 구성된 경우 API 프록시가 캐시를 사용할 수 있게 됩니다. 이 구성 값은 tcp 및 unix 리스너 블록 모두에 공통입니다. tcp 유형의 블록은 표준 tcp 리스너 옵션을 지원합니다. 추가로 listener 블록 최상위에서 role 문자열 옵션을 사용할 수 있으며, metrics_only로 설정하면 메트릭만 제공하고, 기본 역할인 default는 모든 것(메트릭 포함)을 제공합니다.
type(string: required)— 사용할 리스너의 유형입니다. 유효한 값은tcp와unix입니다. 참고: HCL을 사용할 때는 블록의 키로 사용할 수 있습니다. 예:listener "tcp" {...}.address(string: required)— 리스너가 수신할 주소입니다.tcp를 사용할 때는 URL 경로,unix를 사용할 때는 파일 경로가 될 수 있습니다. 예:127.0.0.1:8200또는/path/to/socket. 기본값은127.0.0.1:8200입니다.tls_disable(bool: false)— TLS를 비활성화할지 지정합니다.tls_key_file(string: optional)— 인증서의 개인 키 경로를 지정합니다.tls_cert_file(string: optional)— TLS용 인증서 경로를 지정합니다.
예시 구성
다음은 선택적 persist 블록과 함께, 일반 리스너 및 메트릭만 제공하는 리스너가 있는 캐시 구성의 예시입니다.
# 다른 Vault 프록시 구성 블록
# ...
cache {
persist = {
type = "kubernetes"
path = "/vault/proxy-cache/"
keep_after_import = true
exit_on_err = true
service_account_token_file = "/tmp/serviceaccount/token"
}
}
listener "tcp" {
address = "127.0.0.1:8100"
tls_disable = true
}
listener "tcp" {
address = "127.0.0.1:3000"
tls_disable = true
role = "metrics_only"
}
출처: 문서