에이전트 ID가 있는 Google Kubernetes Engine (GKE) 에이전트는 해당 ID를 사용하여 Google Cloud API와 외부 도구 및 서비스에 인증할 수 있습니다. 상담사는 자체 ID를 사용하거나 최종 사용자를 대신하여 행동할 수 있습니다. 이 문서에서는 에이전트 애플리케이션 개발자가 다양한 리소스에 인증하도록 애플리케이션을 구성하는 방법을 보여줍니다. GKE 에이전트의 에이전트 ID를 요청하는 방법을 이미 알고 있어야 합니다.
에이전트가 액세스해야 하는 리소스에 따라 플랫폼 관리자가 추가 워크플로를 실행하도록 인증 관리자 사용자 인증 정보 보관함을 구성해야 할 수 있습니다. 예를 들어 상담사가 최종 사용자를 대신하여 GitHub에 인증하려면 인증 관리자의 3단계 OAuth 인증 제공업체가 사용자 로그인, 승인, 리디렉션을 처리해야 합니다. 개발자는 올바른 인증 제공업체를 호출하고 최종 사용자의 대화 재개를 처리하도록 에이전트를 수정합니다.
제한사항
- 에이전트 ID 제한사항을 참고하세요.
- Google 인증 라이브러리를 사용하여 Python에만 바인드된 액세스 및 ID 토큰을 가져올 수 있습니다. 인증 라이브러리가 다른 언어의 바인드된 토큰을 가져오지 못할 수 있습니다. 다른 언어를 사용하는 경우
GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN환경 변수를false로 설정하여 바인드되지 않은 토큰으로 전환합니다.
시작하기 전에
시작하기 전에 다음 태스크를 수행했는지 확인합니다.
- Google Kubernetes Engine API를 사용 설정합니다. Google Kubernetes Engine API 사용 설정
- 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화합니다. 이전에 gcloud CLI를 설치했으면
gcloud components update명령어를 실행하여 최신 버전을 가져옵니다. 이전 gcloud CLI 버전에서는 이 문서의 명령어를 실행하지 못할 수 있습니다.
- 에이전트 ID를 사용하는 실행 중인 워크로드가 있는 기존 클러스터에 연결합니다. 워크로드의 에이전트 ID를 요청하려면 GKE 에이전트의 에이전트 ID 요청을 참고하세요.
- 인증 관리자를 사용하여 외부 도구 및 서비스를 인증하려면 플랫폼 관리자에게 다음을 요청하세요.
- 인증 워크플로의 인증 제공업체를 설정합니다.
- 에이전트에 인증 제공업체 액세스 권한을 부여합니다.
필요한 역할
GKE 클러스터에서 배포된 에이전트를 구성하는 데 필요한 권한을 얻으려면 관리자에게 프로젝트에 대한 Kubernetes Engine 개발자 (roles/container.developer) IAM 역할을 부여해 달라고 요청하세요.
역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.
커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.
Google Cloud API에 인증
Google Cloud API에 에이전트 자체 ID로 인증하려면 에이전트가 노드의 메타데이터 서버에서 에이전트 ID 액세스 토큰을 사용할 수 있습니다. 코드에 적용해야 할 변경사항은 다음과 같이 Google Cloud API를 호출하는 방식에 따라 달라집니다.
Cloud 클라이언트 라이브러리 사용
google-auth 라이브러리의 버전 2.61.0 이상이 포함된 Cloud 클라이언트 라이브러리 버전을 사용하는 경우 애플리케이션 기본 사용자 인증 정보 (ADC)가 에이전트 ID 액세스 토큰을 자동으로 가져옵니다. 코드를 추가로 변경할 필요는 없습니다. iam.gke.io/inject-podcertificates: "true" 주석을 설정하여 포드의 인증서 삽입을 사용 설정하면 바운드 토큰을 사용 중지하지 않는 한 액세스 토큰이 기본적으로 X.509 인증서에 바인딩됩니다.
Cloud 클라이언트 라이브러리를 사용할 때 바인딩되지 않은 액세스 토큰을 가져오려면 다음 중 하나를 실행합니다.
- 포드에서 인증서 삽입을 사용 설정하고
GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN환경 변수를false로 설정합니다. - 포드에서 인증서 삽입을 사용 설정하지 마세요.
Google Cloud API 엔드포인트에 직접 호출 사용
Cloud 클라이언트 라이브러리를 사용하여 서비스와 상호작용하지 않는 경우 다음을 실행하여 에이전트의 ID를 사용하여 Google Cloud API에 인증할 수 있습니다.
노드의 메타데이터 서버에서 액세스 토큰을 가져옵니다. 다음 방법 중 하나를 사용하여 토큰을 가져올 수 있습니다.
바인딩된 액세스 토큰: 포드의 X.509 인증서를 검색하고 기본적으로 바인딩된 액세스 토큰을 자동으로 가져오는
google-authPython 라이브러리를 사용합니다. 다른 프로그래밍 언어의 경우 바인딩되지 않은 토큰을 사용하세요.바인딩되지 않은 액세스 토큰: 포드에 에이전트 ID 사용자 인증 정보 번들이 없는 경우 프로그래밍 언어에 Google 인증 라이브러리를 사용합니다. 인증 라이브러리는 바인드되지 않은 액세스 토큰을 자동으로 가져오고 만료되는 토큰을 새로고침합니다. 인증 정보 번들이 있는 포드의 Python 애플리케이션의 경우 포드 사양에서
GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN환경 변수를false로 설정합니다(예: 다음 예시 참고).# Multiple lines are omitted here. spec: containers: - name: example-agent image: example-image env: - name: GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN value: "false" # Multiple lines are omitted here.이 환경 변수는 라이브러리가 바인드된 액세스 토큰과 ID 토큰을 가져오지 못하도록 합니다.
바인딩된 액세스 토큰의 경우 API의 mTLS 엔드포인트로 요청을 보내고 HTTP 전송에 에이전트 ID X.509 인증서 체인을 포함합니다. Python용 Google 인증 라이브러리를 사용하는 경우 라이브러리에서 HTTP 전송 구성을 처리합니다.
다음 예시에서는 Python용 Google 인증 라이브러리를 사용하여 바인딩된 액세스 토큰을 가져오고 Cloud Storage mTLS 엔드포인트에 요청하는 방법을 보여줍니다.
import google.auth
from google.auth.transport.requests import AuthorizedSession
def call_storage_api_mtls(bucket_name: str) -> None:
# Discover the Pod's X.509 certificate chain by using the auth library
credentials, project = google.auth.default(
scopes=["https://www.googleapis.com/auth/cloud-platform"]
)
# Configure the mTLS session by using the Pod's certificate chain
session = AuthorizedSession(credentials)
session.configure_mtls_channel()
# Call the Google Cloud mTLS endpoint
mtls_url = f"https://storage.mtls.googleapis.com/storage/v1/b/{bucket_name}/o"
response = session.get(mtls_url)
response.raise_for_status()
print(response.json())
외부 도구 및 서비스에 인증
외부 도구 및 서비스에 인증하려면 에이전트가 에이전트 ID 인증 관리자로부터 필요한 사용자 인증 정보를 가져오도록 구성하면 됩니다. 플랫폼 관리자는 인증 관리자에서 다양한 인증 제공자를 구성하며, 각 인증 제공자는 특정 인증 워크플로와 사용자 인증 정보를 관리합니다. 특정 인증 제공업체를 호출하고 인증 워크플로에 따라 사용자 동의 및 대화 재개를 처리하도록 애플리케이션 코드를 수정합니다. 에이전트에 적용하는 구체적인 변경사항은 액세스해야 하는 항목에 따라 다음과 같이 달라집니다.
- 최종 사용자를 대신하여 외부 서비스에 액세스하려면 다음을 실행합니다.
- 3-legged OAuth 인증 제공업체를 호출하도록 에이전트를 수정합니다.
- 클라이언트 측 애플리케이션을 수정하여 사용자 로그인 및 리디렉션을 처리합니다.
- 에이전트 자체 권한을 사용하여 외부 서비스에 액세스하려면 2-legged OAuth 인증 제공업체를 호출하도록 에이전트를 수정하세요.
- API 키를 사용하여 외부 API에 액세스하려면 API 키 인증 제공업체를 호출하도록 에이전트를 수정하세요.
인증 관리자는 해당 인증 워크플로를 처리하고 에이전트에게 암호화된 사용자 인증 정보에 대한 액세스 권한을 부여합니다. 그러면 이 사용자 인증 정보가 외부 서비스에 대한 요청에 포함될 수 있습니다. 플랫폼 관리자가 이러한 인증 제공업체를 구성하고 에이전트 ID에 대한 액세스 권한을 부여하기 위해 해야 하는 작업에 대한 자세한 내용은 에이전트 인증 워크플로를 참고하세요.
다른 에이전트에 인증
멀티 에이전트 아키텍처에서 에이전트는 피어 에이전트 또는 다운스트림 서비스를 직접 호출하여 자주 공동작업합니다. ID 토큰을 사용하여 에이전트 워크로드 간에 직접 통신을 설정할 수 있습니다. GKE 메타데이터 서버에서 바인딩된 ID 토큰 또는 바인딩되지 않은 ID 토큰을 가져와서 해당 토큰을 사용하여 다른 에이전트에 직접 인증할 수 있습니다.
ID 토큰을 가져와 HTTP 요청에서 토큰을 사용하려면 Python용 Google 인증 라이브러리를 사용하세요. 이 라이브러리는 인증서 검색 및 ID 토큰 획득을 자동으로 처리합니다. 다른 프로그래밍 언어를 사용하는 경우 Google 인증 라이브러리가 바인드된 ID 토큰을 가져오지 못할 수 있습니다. 대신 바인드되지 않은 ID 토큰으로 전환하세요.
ID 토큰 가져오기
에이전트 코드에서 ID 토큰을 요청하려면 프로그래밍 언어에 맞는 Google 인증 라이브러리를 사용하세요. 라이브러리를 사용하여 다음과 같이 바인딩된 ID 토큰 또는 바인딩되지 않은 ID 토큰을 요청할 수 있습니다.
- 바운드 ID 토큰:
iam.gke.io/inject-podcertificates: "true"주석을 사용하여 포드의 인증서 삽입을 사용 설정합니다. Python용 인증 라이브러리는 GKE 메타데이터 서버에서 인증서 바인딩 ID 토큰을 자동으로 요청합니다. mTLS를 사용하여 Google Cloud 에서 실행되는 에이전트 간에 인증할 때는 바운드 ID 토큰을 사용합니다. 바인딩되지 않은 ID 토큰:
- Pod의 인증서 삽입을 사용 설정하고 다음 중 하나를 수행합니다.
- 애플리케이션 코드의
id_token.fetch_id_token함수에서bind_id_token인수를False값으로 설정합니다. 이 인수로 인해 인증 라이브러리가 바인딩되지 않은 ID 토큰을 요청합니다. 액세스 토큰 요청은 영향을 받지 않습니다. - 포드 사양에서
GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN환경 변수를false값으로 설정합니다. 이 환경 변수는 라이브러리가 바인드된 액세스 토큰과 ID 토큰을 요청하지 못하도록 합니다.
- 애플리케이션 코드의
- 포드에 인증서 삽입을 사용 설정하지 마세요. 인증 라이브러리는 포드에 인증 정보 번들이 없으므로 바인딩되지 않은 ID 토큰을 가져옵니다.
비 mTLS 연결을 사용하여 Google Cloud API, 외부 서비스 또는 기타 에이전트에 인증할 때는 바인딩되지 않은 ID 토큰을 사용합니다.
- Pod의 인증서 삽입을 사용 설정하고 다음 중 하나를 수행합니다.
다음 예시에서는 사용자 인증 정보 삽입이 사용 설정된 에이전트에 대해 바인딩된 또는 바인딩되지 않은 ID 토큰을 요청하는 방법을 보여줍니다.
바인딩된 ID 토큰을 요청합니다.
import google.auth.transport.requests from google.oauth2 import id_token # Application Default Credentials automatically requests a certificate-bound # ID token. def get_bound_id_token(target_audience: str) -> str: auth_req = google.auth.transport.requests.Request() return id_token.fetch_id_token(auth_req, audience=target_audience)바인드된 ID 토큰에는
cnf.x5t#S256매개변수에 포드의 X.509 인증서 체인의 SHA-256 인증서 지문이 포함됩니다.바인딩되지 않은 ID 토큰을 요청합니다.
import google.auth.transport.requests from google.oauth2 import id_token def get_unbound_id_token(target_audience: str) -> str: auth_req = google.auth.transport.requests.Request() return id_token.fetch_id_token( auth_req, audience=target_audience, # Always get an unbound ID token, even if the Pod has a credential # bundle. bind_id_token=False, )
다른 에이전트에 대한 요청에서 ID 토큰 사용
에이전트의 ID 토큰을 가져온 후 토큰을 사용하여 다른 에이전트에 직접 인증할 수 있습니다. 연결을 인증하는 방법은 바인드된 ID 토큰을 사용하는지 여부에 따라 다음과 같이 달라집니다.
- 바인딩된 ID 토큰의 경우 수신 에이전트와 mTLS 연결을 설정하고 포드의
/var/run/secrets/workload-spiffe-credentials/디렉터리에서 다음 두 사용자 인증 정보를 모두 사용하여 연결을 인증합니다.x509.credential-bundle.private-key.pem파일에 있는 에이전트 ID 사용자 인증 정보 번들입니다. 여기에는 포드의 리프 인증서 체인이 포함됩니다.TRUST_DOMAIN.spiffe-trust-bundle.pem파일에 있는 클러스터 신뢰 번들입니다. 이 파일에는 수신 에이전트의 루트 CA 인증서가 포함되어 있으며 mTLS 핸드셰이크 중에 수신 에이전트의 인증서 체인을 검증하는 데 사용됩니다. 호출 및 수신 에이전트가 동일한 에이전트 ID 풀에 있어야 합니다.
- 바인드되지 않은 ID 토큰의 경우 수신 에이전트와 mTLS가 아닌 연결을 설정합니다.
다음 예에서는 바인딩된 또는 바인딩되지 않은 ID 토큰을 사용하여 다른 에이전트에 요청을 보내는 방법을 보여줍니다.
바인딩된 ID 토큰: 수신 에이전트의 mTLS 엔드포인트로 전송하는 요청의
Authorization: Bearer헤더에 바인딩된 ID 토큰을 포함합니다. 포드의 X.509 인증서와 비공개 키를 사용하여 TLS 연결을 인증합니다.import ssl import urllib3 BUNDLE_PATH = "/var/run/secrets/workload-spiffe-credentials/x509.credential-bundle.private-key.pem" TRUST_BUNDLE_PATH = "/var/run/secrets/workload-spiffe-credentials/TRUST_DOMAIN.spiffe-trust-bundle.pem" def call_peer_agent_bound_mtls(target_mtls_url: str, target_audience: str) -> None: # Configure the mTLS context by using the certificate chain and trust # bundle from the Pod. ctx = ssl.create_default_context(cafile=TRUST_BUNDLE_PATH) ctx.load_cert_chain(BUNDLE_PATH) http = urllib3.PoolManager(ssl_context=ctx, assert_hostname=False) # Call a peer agent's mTLS endpoint by using the bound ID token and Pod # certificate chain. bound_id_token = get_bound_id_token(target_audience) response = http.request( "POST", target_mtls_url, headers={"Authorization": f"Bearer {bound_id_token}"}, json={"task": "analyze_data"}, timeout=10, ) print(response.json())TRUST_DOMAIN을 에이전트 ID 풀의 트러스트 도메인으로 바꿉니다.바인딩되지 않은 ID 토큰: 피어 에이전트에 대한 요청의
Authorization: Bearer헤더에 토큰을 포함합니다.import requests def call_peer_agent_unbound(target_url: str, target_audience: str) -> None: unbound_id_token = get_unbound_id_token(target_audience) # Send the request by using a standard TLS connection or plain HTTP. response = requests.post( target_url, headers={"Authorization": f"Bearer {unbound_id_token}"}, json={"task": "analyze_data"}, timeout=10, ) response.raise_for_status() print(response.json())
수신 상담사에서 요청 유효성 검사
수신 에이전트에서 다음을 실행하여 수신 요청에 있는 ID 토큰을 검증합니다. Tink와 같은 암호화 라이브러리를 사용하여 맞춤 코드를 작성하는 대신 이러한 확인 단계를 실행할 수 있습니다.
- 요청
Authorization: Bearer헤더에서 ID 토큰을 추출합니다. - ID 토큰의
iss(발급기관) 클레임이 호출 에이전트의 에이전트 ID 풀인지 확인합니다. 호출 에이전트가 조직에 속한 프로젝트에 있는지 여부에 따라 발급자는 다음 중 하나입니다.- 조직에 속한 프로젝트:
https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/agents.global.org-ORGANIZATION_ID.system.id.goog, 여기서ORGANIZATION_ID은 호출 에이전트의 프로젝트가 포함된 조직의 조직 ID입니다. - 조직에 속하지 않는 프로젝트:
https://sts.googleapis.com/v1/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/agents.global.proj-PROJECT_NUMBER.system.id.goog, 여기서PROJECT_NUMBER은 호출 에이전트의 GKE 클러스터의 프로젝트 번호입니다.
- 조직에 속한 프로젝트:
- 발급기관의 JSON 웹 키 세트 (JWKS) URI를 검색하고 공개 JSON 웹 키 (JWK)를 캐시합니다. JWKS의 엔드포인트는
ISSUER_URL/openid/jwks형식을 따릅니다. 여기서ISSUER_URL은 발급기관 URL입니다. - ID 토큰의 JOSE 헤더에서 다음 정보를 사용하여 토큰 서명을 검증합니다.
kid헤더 매개변수와 일치하는 공개 JWK입니다.alg헤더 매개변수와 일치하는 암호화 알고리즘입니다(예:RS256).
cnf.x5t#S256매개변수에 있는 SHA-256 인증서 지문이 호출 에이전트가 mTLS 연결을 인증하는 데 사용한 X.509 인증서의 지문과 일치하는지 확인합니다.- ID 토큰에서 다음 클레임을 확인합니다.
exp클레임의 만료 시간이 미래입니다.aud클레임의 대상은 수신 상담사입니다.
- 토큰의
sub(주체) 클레임에 있는 SPIFFE ID를 기반으로 요청을 승인합니다.