Vault Lambda 확장
Vault Lambda 확장 (Lambda Extension)
AWS Lambda는 서버를 프로비저닝·관리하지 않고 코드를 실행할 수 있게 해줍니다. Vault Lambda 확장은 AWS Lambda Extensions API를 활용해 Lambda 함수가 Vault 배포에서 시크릿을 읽을 수 있게 도와줍니다. 확장을 처음부터 사용해보고 싶다면 종단간 예시가 있는 quick-start 디렉토리를 사용할 수 있습니다.
참고: 처음부터 만들기로 결정했다면 AWS 요금에 따라 관련 비용이 드는 실제 인프라가 생성된다는 점을 유의하세요.
출처: 문서
본문
사용법 (Usage)
확장을 사용하려면 원하는 아키텍처에 따라 다음 ARN 중 하나를 Lambda 함수의 레이어(layer)로 포함하세요.
amd64 (x86_64):
arn:aws:lambda:<your-region>:634166935893:layer:vault-lambda-extension:18
arm64:
arn:aws:lambda:<your-region>:634166935893:layer:vault-lambda-extension-arm64:6
여기서 region은 af-south-1, ap-east-1, ap-northeast-1, ap-northeast-2, ap-northeast-3, ap-south-1, ap-south-2, ap-southeast-1, ap-southeast-2, ca-central-1, eu-central-1, eu-north-1, eu-south-1, eu-west-1, eu-west-2, eu-west-3, me-south-1, sa-east-1, us-east-1, us-east-2, us-west-1, us-west-2 중 하나일 수 있습니다.
확장은 AWS IAM 인증으로 Vault에 인증하며, 모든 구성은 환경 변수로 제공됩니다. 시크릿을 읽는 방법은 두 가지이며, 둘을 나란히 사용할 수 있습니다.
- 권장:
http://127.0.0.1:8200의 확장 로컬 프록시 서버에 인증되지 않은 요청을 보냅니다. 프록시가 인증 헤더를 추가하고 구성된VAULT_ADDR로 프록시합니다. Vault의 응답은 수정 없이 반환됩니다. - 확장이 시크릿을 읽고 디스크에 쓰도록
VAULT_SECRET_PATH같은 환경 변수를 구성합니다.
기존 lambda 및 Vault 인프라에 확장 추가하기
요구사항
- Lambda가 실행되는 역할의 ARN
- AWS Lambda에서 접근 가능한 Vault 인스턴스
- 인증된 vault 클라이언트
- Lambda가 접근할 Vault의 시크릿과 그에 대한 읽기 접근을 주는 정책
- Lambda 함수는 확장에 지원되는 런타임 중 하나를 사용해야 함
1단계: Vault 구성하기
aws 인증 메서드를 활성화합니다.
$ vault auth enable aws
AWS 클라이언트가 기본 옵션을 사용하도록 구성합니다.
$ vault write -force auth/aws/config/client
AWS 환경 이름이 접두사로 붙은 역할을 만듭니다.
$ vault write auth/aws/role/vault-lambda-role \
auth_type=iam \
bound_iam_principal_arn="${YOUR_ARN}" \
policies="${YOUR_POLICY}" \
ttl=1h
2단계 - 옵션 a) zip 아카이브로 패키징된 Lambda 함수용 확장 설치
Lambda 함수를 zip 파일로 배포한다면 콘솔이나 CLI를 사용해 확장을 Lambda 레이어에 추가할 수 있습니다.
arn:aws:lambda:<your-region>:634166935893:layer:vault-lambda-extension:11
2단계 - 옵션 b) 컨테이너 이미지로 패키징된 Lambda 함수용 확장 설치
또는 Lambda 함수를 컨테이너 이미지로 배포한다면, 이미지의 /opt/extensions 디렉토리에 빌드된 바이너리를 넣기만 하면 됩니다.
releases.hashicorp.com에서 바이너리를 가져옵니다. 다음 명령에는 cURL이 필요합니다.
$ curl --silent https://releases.hashicorp.com/vault-lambda-extension/0.5.0/vault-lambda-extension_0.5.0_linux_amd64.zip \
--output vault-lambda-extension.zip
다운로드한 바이너리의 압축을 풉니다.
$ unzip vault-lambda-extension.zip
선택적으로, 릴리스 아카이브 체크섬 검증 지침을 사용해 다운로드한 zip의 무결성을 검증할 수 있습니다.
또는 소스에서 바이너리를 빌드합니다. Golang 설치가 필요합니다. 이 저장소의 루트에서 실행하세요.
$ GOOS=linux GOARCH=amd64 go build -o vault-lambda-extension main.go
3단계: vault-lambda-extension 구성하기
Lambda 환경 변수를 사용해 확장을 구성합니다.
Vault API 주소를 설정합니다.
$ VAULT_ADDR=http://vault.example.com:8200
AWS IAM 인증 마운트 지점을 설정합니다(위의 auth/ 뒤의 경로 세그먼트).
$ VAULT_AUTH_PROVIDER=aws
인증할 Vault 역할을 설정합니다. Lambda 역할의 ARN에 대해 구성되어야 합니다.
$ VAULT_AUTH_ROLE=vault-lambda-role
Vault의 시크릿 경로. 정적 또는 동적일 수 있습니다. VAULT_SECRET_FILE을 지정하지 않으면 JSON 응답이 /tmp/vault/secret.json에 기록됩니다.
$ VAULT_SECRET_PATH=secret/lambda-app/token
모든 것이 올바르게 설정되면 Lambda 함수는 /tmp/vault/secret.json에서 시크릿 자료를 읽을 수 있습니다. JSON 개체의 정확한 내용은 읽은 시크릿에 따라 다르지만, 스키마는 Vault API 모듈의 Secret 구조체입니다.
또는 http://127.0.0.1:8200의 로컬 프록시로 일반 Vault API 요청을 HTTP로 보낼 수 있으며, 확장이 요청을 전달하기 전에 인증을 추가합니다. Vault 응답은 수정 없이 반환됩니다. 로컬 통신은 일반 HTTP지만, 아래에 설명된 대로 구성된 경우 프록시 서버는 Vault와 통신할 때 TLS를 사용합니다.
구성 (Configuration)
확장은 Lambda 환경 변수로 구성됩니다. 대부분의 Vault CLI 클라이언트 환경 변수를 사용할 수 있으며, 인증, 읽을 시크릿, 시크릿 기록 위치를 구성하는 몇 가지 추가 변수도 있습니다.
| 환경 변수 | 설명 | 필수 | 예시 값 |
|---|---|---|---|
| VLE_VAULT_ADDR | 연결할 Vault 주소. VAULT_ADDR보다 우선하므로 프록시 서버의 클라이언트를 표준 VAULT_ADDR로 구성할 수 있음 |
아니요 | https://x.x.x.x:8200 |
| VAULT_ADDR | VLE_VAULT_ADDR이 설정되지 않은 경우 연결할 Vault 주소. VLE_VAULT_ADDR이 설정되지 않으면 필수 |
아니요 | https://x.x.x.x:8200 |
| VAULT_AUTH_PROVIDER | Vault에 구성된 AWS IAM 인증 경로 이름 | 예 | aws |
| VAULT_AUTH_ROLE | 인증할 Vault 역할 | 예 | lambda-app |
| VAULT_IAM_SERVER_ID | AWS 인증용 X-Vault-AWS-IAM-Server-ID HTTP 헤더로 Vault 서버에 전달할 값 |
아니요 | vault.example.com |
| VAULT_SECRET_PATH | 읽을 시크릿 경로. VAULT_SECRET_FILE이 지정되지 않으면 /tmp/vault/secret.json에 기록 |
아니요 | database/creds/lambda-app |
| VAULT_SECRET_FILE | VAULT_SECRET_PATH의 JSON 응답을 쓸 경로 |
아니요 | /tmp/db.json |
| VAULT_SECRET_PATH_FOO | 읽을 추가 시크릿 경로. FOO는 어떤 이름이든 가능, 일치하는 VAULT_SECRET_FILE_FOO가 지정되는 한 사용 |
아니요 | secret/lambda-app/token |
| VAULT_SECRET_FILE_FOO | 해당 이름의 VAULT_SECRET_PATH_FOO에 대해 존재해야 함. 이름은 올바른 경로 변수와 일치하는 것 외에는 추가 효과 없음 |
아니요 | /tmp/token |
| VAULT_RUN_MODE | 사용 가능 옵션은 default, proxy, file. proxy 모드는 확장의 로컬 프록시 서버로 요청. file 모드는 확장이 시크릿을 읽고 디스크에 쓰도록 구성. default 모드는 file과 proxy 모드를 모두 사용. 기본값은 default | 아니요 | default |
| VAULT_TOKEN_EXPIRY_GRACE_PERIOD | 프록시 서버의 인증 토큰 TTL 끝에서 토큰이 만료된 것으로 간주하고 Vault에 다시 인증하려 시도하는 기간. 단위가 있어야 하며 time.Duration으로 파싱 가능해야 함. 기본 10s | 아니요 | 1m |
| VAULT_STS_ENDPOINT_REGION | 인증할 STS 리전 엔드포인트의 리전. 지정된 AWS IAM 인증 마운트가 리전 STS 엔드포인트를 사용하면 이 엔드포인트의 리전과 일치해야 함. 기본값은 전역 엔드포인트 또는 AWS_STS_REGIONAL_ENDPOINTS가 regional로 설정된 경우 Lambda가 있는 리전 |
아니요 | eu-west-1 |
나머지 환경 변수는 필수가 아니며 Vault Commands(CLI) 문서에 설명된 대로 정확히 작동합니다. 단, VAULT_CLIENT_TIMEOUT은 파일을 디스크에 쓸 때 Extensions API가 부과하는 10초 초기화 시간제한을 넘어갈 수 없다는 점을 유의하세요.
| 환경 변수 | 설명 | 필수 | 예시 값 |
|---|---|---|---|
| VAULT_CACERT | 로컬 디스크의 PEM 인코딩 CA 인증서 파일 경로 | 아니요 | /tmp/ca.crt |
| VAULT_CAPATH | 로컬 디스크의 PEM 인코딩 CA 인증서 파일 디렉토리 경로 | 아니요 | /tmp/certs |
| VAULT_CLIENT_CERT | 로컬 디스크의 PEM 인코딩 클라이언트 인증서 경로 | 아니요 | /tmp/client.crt |
| VAULT_CLIENT_KEY | 일치하는 클라이언트 인증서에 해당하는 디스크의 암호화되지 않은 PEM 인코딩 개인 키 경로 | 아니요 | /tmp/client.key |
| VAULT_CLIENT_TIMEOUT | Vault 요청 시간제한. 기본값 60s. 프록시 서버에서 무시됨. 10s를 넘는 값은 Extensions API 시간제한을 초과하므로 효과 없음 | 아니요 | 5s |
| VAULT_MAX_RETRIES | 5xx 오류 코드의 최대 재시도 횟수. 기본 2. 프록시 서버에서 무시됨 | 아니요 | 2 |
| VAULT_SKIP_VERIFY | 통신 전에 Vault가 제시한 인증서를 검증하지 않음. 이 변수 설정은 권장하지 않으며 Vault의 보안 모델을 무효화함 | 아니요 | true |
| VAULT_TLS_SERVER_NAME | TLS로 연결할 때 SNI 호스트로 사용할 이름 | 아니요 | vault.example.com |
| VAULT_RATE_LIMIT | 확장의 단일 호출에만 적용. 자세한 내용은 Vault Commands(CLI) 문서 참조. 프록시 서버에서 무시됨 | 아니요 | 10 |
| VAULT_NAMESPACE | 사전 구성된 시크릿에 사용할 네임스페이스. 프록시 서버에서 무시됨 | 아니요 | education |
| VAULT_DEFAULT_CACHE_TTL | 프록시 서버가 사용하는 캐시의 TTL(time to live) 구성. 단위가 있어야 하며 time.Duration으로 파싱 가능해야 함. 캐싱 활성화에 필요 | 아니요 | 15m |
| VAULT_DEFAULT_CACHE_ENABLED | 각 요청에 X-Vault-Cache-Control 헤더를 설정할 필요 없이 모든 요청에 캐싱 활성화. 부울 값으로 설정해야 함 |
아니요 | true |
| VAULT_ASSUMED_ROLE_ARN | Lambda 함수에 할당된 실행 역할이 수임할 수 있는 유효한 IAM 역할 ARN | 아니요 | arn:aws:iam::123456789012:role/xaccounts3access |
| VAULT_LOG_LEVEL | 로그 상세 수준. TRACE, DEBUG, INFO, WARN, ERROR, OFF 중 하나. 기본 INFO | 아니요 | DEBUG |
AWS STS 클라이언트 구성
Vault 구성 외에도 일반적인 AWS 환경 변수를 통해 확장이 사용하는 STS 클라이언트의 특정 측면을 구성할 수 있습니다. 예를 들어 Vault 인스턴스의 IAM 인증이 리전 STS 엔드포인트를 사용하도록 구성된 경우:
$ vault write auth/aws/config/client \
sts_endpoint="https://sts.eu-west-1.amazonaws.com" \
sts_region="eu-west-1"
그러면 AWS_STS_REGIONAL_ENDPOINTS=regional을 설정해 확장의 STS 클라이언트도 리전 STS 엔드포인트를 사용하도록 구성해야 할 수 있습니다. AWS Golang SDK와 Vault IAM 인증 메서드 모두 많은 리전에서 전역 엔드포인트를 기본으로 사용하기 때문입니다. sts_regional_endpoints 문서를 참고하세요.
캐싱 (Caching)
확장의 로컬 프록시 서버에 대한 캐싱을 구성해 모든 HTTP 요청을 Vault로 전달하지 않을 수 있습니다. 캐싱 설계의 주요 고려사항은 캐싱을 요청 수준의 명시적 옵트인(opt-in) 으로 만들어, 다른 곳에 부정적 영향 없이 캐싱이 의미가 있는 시나리오에서만 활성화되도록 하는 것입니다. 캐싱을 켜려면 VAULT_DEFAULT_CACHE_TTL 환경 변수를 Go에서 time.Duration으로 파싱 가능한 유효한 값(예: "15m", "1h", "2m3s", "1h2m3s")으로 설정합니다. 잘못되거나 음수인 값은 값이 없는 것과 동일하게 취급되며, 이 경우 캐싱이 설정·활성화되지 않습니다.
그런 다음 HTTP 메서드가 "GET"이고 HTTP 헤더가 X-Vault-Cache-Control: cache인 요청은 캐시 히트 시 캐시에서 직접 반환됩니다. 캐시 미스 시 요청은 Vault로 전달되고 응답이 반환·캐시됩니다. 헤더가 X-Vault-Cache-Control: recache로 설정되면 캐시 조회를 건너뛰고 요청이 Vault로 전달되며 응답이 반환·캐시됩니다. 현재 캐시 키는 요청 URL 경로, 헤더, 본문, 토큰의 해시입니다.
비표준 분산 추적 헤더는 캐시를 무효화할 수 있습니다. Vault Lambda 확장 캐시 키는 프록시 요청의 헤더를 포함하지만 표준 분산 추적 헤더
traceparent와tracestate는 제외합니다. 추적 ID가 요청마다 고유해 반복 요청에 고유 해시가 생기기 때문입니다. 일부 분산 추적 도구는 비표준 추적 헤더를 추가할 수 있으며, 이것도 반복 요청을 고유하게 만드는 개별 해시를 만들어 캐시 미스를 유발할 수 있습니다.
또한 VAULT_DEFAULT_CACHE_ENABLED 환경 변수를 true로 설정해 모든 요청에 캐싱을 활성화할 수 있습니다. 그러면 X-Vault-Cache-Control: cache 헤더가 있었던 것처럼 모든 요청을 가져오고/캐시합니다. 이 구성에서 요청에 nocache 헤더를 설정하면 캐싱을 완전히 옵트아웃합니다. recache 헤더를 설정하면 앞서 설명한 대로 캐시 조회를 건너뛰고 Vault의 응답을 반환·캐시합니다.
경고! Vault Lambda 확장의 캐시는 메모리 전용이며 Lambda 실행 환경이 종료될 때 지속되지 않습니다. 즉 캐시 TTL은 Lambda 실행 환경의 지속 시간으로 제한됩니다.
제한 사항 (Limitations)
디스크에 기록되거나 프록시 서버에서 반환된 시크릿은 만료될 때 자동으로 새로고침되지 않습니다. 특히 확장을 구성해 시크릿을 디스크에 쓰는 경우 중요합니다. 확장은 함수 호출마다가 아니라 실행 환경당 한 번만 디스크에 쓰기 때문입니다. 프로비저닝된 동시성(provisioned concurrency)을 사용하거나 Lambda가 시크릿 수명을 넘어 실행 컨텍스트가 유지될 만큼 자주 호출된다면, 디스크의 시크릿은 무효화될 가능성이 높습니다.
Lambda 모범 사례에 따라 가능하면 시크릿을 디스크에 쓰는 것을 피하고 프록시 서버를 통해서만 시크릿을 소비할 것을 권장합니다. 그러나 프록시 서버는 반환된 시크릿에 대해 자동 임대 갱신 같은 추가 처리를 수행하지 않습니다. 프록시 서버의 자체 Vault 인증 토큰만 자동으로 새로고침됩니다. 토큰이 만료되면(유예 창 포함) 요청을 프록시하기 전에 자체 토큰을 동기적으로 새로고침하고, 토큰이 거의 만료되지만 갱신 가능하면 갱신을 시도합니다. 또한 들어오는 요청 헤더 X-Vault-Token-Options: revoke가 있으면 프록시는 즉시 토큰을 새로고침합니다.
SnapStart 비호환: Vault Lambda 확장은 현재 AWS SnapStart와 작동하지 않습니다.
성능 영향 (Performance impact)
AWS Lambda 요금은 호출 수, 실행 시간, 사용 메모리를 기준으로 합니다. 다음 표는 이 확장의 비용 영향을 평가하는 데 도움이 되는 몇 가지 대략적인 성능 관련 통계를 설명합니다. AWS Lambda는 메모리에 비례해 CPU 성능을 할당하므로 결과가 크게 달라질 수 있습니다. 이 벤치마크는 최소 128MB 메모리로 실행되어 대략적인 기준선을 제공하기 위한 것입니다.
| 메트릭 | 값 | 설명 | 산출 |
|---|---|---|---|
| 레이어 크기 | 8.5MB | 압축 해제된 확장 바이너리 크기 | ls -la |
| 초기화 지연시간 | 8.5ms(표준편차 2.4ms) + Vault 인증 네트워크 왕복 1회 | 새 실행 환경에서의 확장 초기화 시간. 인증 왕복 시간은 배포에 크게 의존 | 코드에서 계측 |
| 호출 지연시간 | <1ms | 프록시 서버 호출이 없다고 가정할 때 각 함수 호출의 기본 처리 시간 | 코드에서 계측 |
| 메모리 영향 | 12MB | 확장 실행 시 "Max Memory Used"에 대한 주변 영향 | 확장 유무로 Hello World 함수 실행 시 Lambda가 보고 |
자신의 AWS 계정·리전에 업로드하기
확장을 자신의 AWS 계정·리전에 Lambda 레이어로 업로드하려면 다음을 할 수 있습니다.
$ curl --silent https://releases.hashicorp.com/vault-lambda-extension/0.5.0/vault-lambda-extension_0.5.0_linux_amd64.zip \
--output vault-lambda-extension.zip
대상 AWS 리전을 설정합니다.
$ export REGION="YOUR REGION HERE"
확장을 Lambda 레이어로 업로드합니다.
$ aws lambda publish-layer-version \
--layer-name vault-lambda-extension \
--zip-file "fileb://vault-lambda-extension.zip" \
--region "${REGION}"
튜토리얼
단계별 지침은 AWS Lambda 함수를 만들고 Vault Lambda 확장을 사용해 Vault에 인증하는 방법에 대한 Retrieve secrets with Vault AWS Lambda extension 튜토리얼을 참고하세요.