워크로드 아이덴티티 페더레이션
워크로드 아이덴티티 페더레이션 (Workload identity federation)
HCP(HashiCorp Cloud Platform)의 워크로드 아이덴티티 페더레이션에 대한 개요를 설명해 드릴게요.
출처: 문서
본문
소개
HCP와 외부 아이덴티티 제공자 사이에 신뢰 관계를 만들려면 워크로드 아이덴티티 제공자(workload identity provider)를 구성해요. 이 신뢰 관계를 페더레이션(federation)이라고 불러요. 외부 워크로드는 아이덴티티 페더레이션을 활용해 외부 아이덴티티 토큰을 HCP 액세스 토큰으로 교환할 수 있어요. 워크로드 아이덴티티 페더레이션을 사용하면 워크로드에 서비스 주체 자격 증명을 저장하지 않고도 워크로드 아이덴티티 토큰을 HCP 서비스 주체 액세스 토큰으로 교환할 수 있어요.
HCP는 HCP CLI와 HCP Terraform Provider를 통해 다음 아이덴티티 제공자에 대한 워크로드 아이덴티티 페더레이션을 지원해요.
- AWS
- Azure
- GCP
- GitHub
- GitLab
- 기타 OIDC 제공자
워크로드 아이덴티티 페더레이션을 사용하는 이유
HCP 아이덴티티 서비스는 워크로드(서비스, 스크립트, 컨테이너 기반 애플리케이션 등)가 다른 HCP 서비스에 접근하기 전에 그 워크로드를 인증해야 해요. HCP에서 워크로드는 일반적으로 서비스 주체 키를 사용해 서비스 주체로 인증해요. 이 자격 증명은 접근 권한이 있는 사람이라면 누구나 HCP로 인증할 수 있으므로 보안 위험이 돼요. 안전하게 저장하고 주기적으로 교체하며 배포를 신중하게 관리해야 해요.
워크로드 아이덴티티 페더레이션을 사용하면 외부 워크로드는 시크릿 키를 전혀 저장하지 않고 HCP에 인증할 수 있어요. 워크로드 아이덴티티를 페더레이션하면 워크로드는 신뢰하는 아이덴티티 토큰을 HCP에 보내고, HCP 서비스와 상호작용해야 할 때 HCP 액세스 토큰을 받아요. 이 과정은 자격 증명을 수동으로 관리할 필요를 없애고 서비스 주체의 시크릿 유출 위험을 낮춰줘요.
워크로드 아이덴티티 페더레이션의 동작 방식
워크로드 아이덴티티 페더레이션은 많은 플랫폼이 워크로드에 외부에서 검증 가능한 아이덴티티를 제공한다는 사실에 의존해요. 워크로드는 이 외부 아이덴티티를 사용해 HCP에 인증하고 그 대가로 서비스 주체 토큰을 받을 수 있어요.
먼저, 토큰을 발행한 아이덴티티 제공자를 신뢰하도록 HCP를 구성해요. HCP에 아이덴티티를 어디에서 기대하고 어떻게 검증해야 하는지 알려줘야 해요. HCP는 조건부 접근 문(conditional access statement)으로 아이덴티티를 검증하는데, 이는 아이덴티티의 예상 속성을 주장하는 불리언 표현식이에요.
- AWS의 경우, 아이덴티티 제공자 구성은 토큰을 발생시키는 AWS Account ID를 지정해야 해요. 조건부 접근 문을 구성해 특정 IAM Role로 교환을 제한하면 AWS 계정에 대한 접근을 제한할 수 있어요. 예를 들어 다음 조건부 접근 문은
"example-role"이라는 IAM Role로 실행되는 워크로드에 대한 접근을 제한해요:aws.arn matches ^arn:aws:sts::123456789012:assumed-role/example-role. - OIDC 제공자의 경우, 아이덴티티 제공자 구성에는 token의 유효성을 검증하는 방법을 HCP에 알려주는 Issuer URI가 필요해요. 토큰의
aud를 구성할 수 있지만, 기본적으로 워크로드 아이덴티티 제공자의 리소스 이름인 HCP가 기대하는 값과 일치해야 해요. HCP는 조건부 접근 문을 사용해 올바른 업스트림 아이덴티티에 대한 접근을 제한해요. 예를 들어 GitHub Actions를 사용할 때 다음 조건부 접근 문은 GitHub 리포지토리my-org/my-repo의deploy워크로드가 GitHub Actions 아이덴티티를 서비스 주체 액세스 토큰으로 교환하도록 허용해요:jwt_claims.repository == "my-org/my-repo" and jwt_claims.workflow == “deploy”.
토큰 교환의 요청 흐름은 다음 순서로 발생해요.
- 외부 워크로드가 외부 워크로드 아이덴티티 제공자에서 토큰을 요청해요.
- 외부 워크로드 아이덴티티 제공자가 외부 워크로드에 토큰을 발행해요.
- 외부 워크로드가 HCP 아이덴티티 서비스에서 HCP 액세스 토큰을 요청하고 인증을 위해 외부 토큰을 보내요.
- HCP 아이덴티티 서비스가 외부 토큰을 검증해요.
- HCP 아이덴티티 서비스가 조건부 접근 문을 검증해요.
- HCP 아이덴티티 서비스가 외부 워크로드에 액세스 토큰을 발행해요.
- 외부 워크로드가 서비스 주체로 인증된 상태로 HCP 서비스에 접근해요.
워크로드 제공자는 프로젝트 수준 서비스 주체로 구성해야 해요. 프로젝트 수준 서비스 주체가 없다면 외부 아이덴티티 제공자를 구성하기 전에 먼저 하나를 만들어야 해요.
자격 증명 파일 (Credential files)
HCP CLI, HCP Terraform Provider, Go SDK 같은 도구는 HCP와 상호작용하기 전에 HCP로 인증해야 해요. 자격 증명 파일은 서비스 주체 키 또는 외부 자격 증명을 사용할 때 HCP로 인증하는 한 가지 방법이에요.
HCP는 다음 순서로 자격 증명 파일을 찾으려고 시도해요.
HCP_CRED_FILE환경 변수. 값은/path/to/cred_file.json형식으로 된 자격 증명 파일 경로여야 해요.- 기본 자격 증명 파일 위치인
~/.config/hcp/cred_file.json.
서비스 주체 키로 자격 증명 파일을 만들려면 --output-cred-file 플래그와 함께 hcp iam service-principals key create 명령을 실행해요.
워크로드 아이덴티티 페더레이션을 사용해 외부 워크로드가 인증할 자격 증명 파일을 만들려면 hcp iam workload-identity-providers create-cred-file 명령을 사용해요.
자격 증명 파일로 인증하기
HCP는 자격 증명 파일을 감지하면 자동으로 사용해요. HCP_CRED_FILE 환경 변수를 설정하고 자격 증명 구성 파일을 가리키게 해요.
export HCP_CRED_FILE=/path/to/credentials.json
또는 지원 도구를 명시적으로 구성할 수 있어요.
HCP CLI / Terraform / HCP Go SDK
hcp auth login 명령을 사용해 자격 증명 파일로 인증해요.
hcp auth login --cred-file=/path/to/credentials.json
HCP Terraform Provider가 자격 증명 파일을 사용하도록 구성해요.
// Pin the version
terraform {
required_providers {
hcp = {
source = "hashicorp/hcp"
// Replace with desired version
version = "~> 0.93.0"
}
}
}
// Configure the provider
provider "hcp" {
credential_file = "/path/to/credentials.json"
}
HCP Go SDK가 자격 증명 파일을 사용하도록 구성해요.
package main
import (
"log"
vs "github.com/hashicorp/hcp-sdk-go/clients/cloud-vault-secrets/stable/2023-06-13/client/secret_service"
"github.com/hashicorp/hcp-sdk-go/config"
"github.com/hashicorp/hcp-sdk-go/httpclient"
)
func main() {
// Construct HCP config
hcpConfig, err := config.NewHCPConfig(
config.WithCredentialFilePath("/path/to/credentials.json"),
)
if err != nil {
log.Fatal(err)
}
// Construct HTTP client config
httpclientConfig := httpclient.Config{
HCPConfig: hcpConfig,
}
// Initialize SDK http client
cl, err := httpclient.New(httpclientConfig)
if err != nil {
log.Fatal(err)
}
// Import versioned client for the desired service.
vsClient := vs.New(cl, nil)
// Use the client
// resp, err := vsClient.OpenAppSecret(...)
}
더 알아보기 (Learn more)
- 조건부 접근 문 (Conditional access statements) — 조건부 접근 문을 작성하고 형식화하는 방법을 알아보세요.
- OIDC 제공자 구성 — OIDC 제공자로 워크로드를 구성하는 방법을 확인해 보세요.
- GitHub 제공자 구성 — GitHub Actions 워크로드를 연결하는 방법을 알아보세요.
- 서비스 주체 (Service principal) — 서비스 주체를 만들고 관리하는 방법을 확인해 보세요.