---
title: 에이전트 ID 및 자격 증명
url: https://platform.claude.com/docs/ko/managed-agents/self-hosted/agent-identity
description: 자체 호스팅 Claude Managed Agents 서버가 각 에이전트를 식별하는 수명이 짧은 토큰에 서명하도록 하고, 볼트 자격 증명을 시크릿 매니저에 보관하며, 이그레스 게이트웨이로 시크릿을 샌드박스 밖에 둡니다.
---

<Note>
  자체 호스팅 Claude Managed Agents에 대한 접근 권한을 요청하려면 Anthropic 계정 팀에 문의하세요.
</Note>

이 페이지에서는 서버 외부의 시스템이 에이전트를 신뢰하도록 하는 방법과 에이전트가 사용하는 자격 증명을 보관할 위치를 보여 줍니다:

* [에이전트 ID](https://platform.claude.com/docs/ko/managed-agents/self-hosted/agent-identity#agent-identity): MCP 서버 또는 게이트웨이가 각 에이전트에 고유한 액세스 권한을 부여하도록 합니다. 서버가 에이전트를 식별하는 수명이 짧은 토큰에 서명합니다.
* [시크릿 매니저](https://platform.claude.com/docs/ko/managed-agents/self-hosted/agent-identity#secret-manager): 서버가 볼트 자격 증명을 AWS Secrets Manager, Google Cloud Secret Manager, HashiCorp Vault 또는 Azure Key Vault에 보관합니다.
* [환경 변수 자격 증명](https://platform.claude.com/docs/ko/managed-agents/self-hosted/agent-identity#environment-variable-credentials): 샌드박스가 플레이스홀더만 보유한 상태에서 에이전트의 명령이 서비스를 호출하도록 합니다. “egress gateway”(이그레스 게이트웨이)가 에이전트의 요청에 실제 값을 넣습니다.

## 에이전트 ID

서버는 에이전트를 식별하는 수명이 짧은 “JSON Web Token”(JSON 웹 토큰), 즉 JWT에 서명하고, 해당 에이전트의 MCP 호출과 함께 보낼 수 있습니다. 수신자인 MCP 서버 또는 게이트웨이는 사용자가 게시한 공개 키로 토큰을 검증한 후, 각 에이전트에 고유한 액세스 권한을 부여할 수 있습니다.

### 발급자 설정

1. **발급자 URL을 선택하세요.** 3단계에서 이 URL에 공개 키를 게시하며, 수신자는 이 URL에서 공개 키를 가져옵니다. 정적 웹 호스트를 사용할 수 있습니다. 서버는 수신자가 가져오는 경로에서 키를 제공하지 않으므로 서버의 주소는 사용하지 마세요. 계속 유지할 수 있는 호스트 이름에서 경로나 후행 슬래시가 없는 `https://` URL을 사용하세요.

2. **서명 키를 생성하세요.** 압축을 푼 아카이브의 최상위 디렉터리에서 다음 명령을 실행하세요:

   ```bash
   mkdir -m 700 agent-identity
   openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out agent-identity/signing-key.pem
   ```

3. **공개 키를 게시하세요.** 이 명령은 공개 키를 `issuer-files/.well-known/`에 씁니다. 발급자 호스트 이름의 루트에서 콘텐츠 유형 `application/json`으로 `issuer-files`를 제공하세요.

   ```bash
   CMA_AGENT_IDENTITY__ISSUER=https://agents.example.com \
   CMA_AGENT_IDENTITY__KEY_FILE=./agent-identity/signing-key.pem \
     ./cma-server export-issuer -out issuer-files
   ```

4. **서버에 키를 제공하세요.**

   <Tabs>
     <Tab title="Docker Compose">
       1. 아카이브에 `compose` 디렉터리가 있다면 키의 디렉터리를 그 안으로 옮기세요: `mv agent-identity compose/agent-identity`.
       2. `docker-compose.yml`에서 `cma-server` 서비스의 `volumes: *server_mounts` 줄을 삭제하고, 그 아래의 `volumes:` 블록의 주석을 해제하세요. `x-server-mounts` 목록을 변경했다면, `cma-server` 서비스가 더 이상 이 목록을 읽지 않으므로 해당 블록에도 같은 변경을 적용하세요.
       3. macOS의 Docker Desktop이나 rootless Docker를 사용하는 경우가 아니라면 `agent-identity`가 있는 디렉터리에서 `sudo chown -R root:root agent-identity`를 실행하세요.
     </Tab>

     <Tab title="Kubernetes">
       `kubectl -n cma-server create secret generic cma-agent-identity --from-file=agent-identity/signing-key.pem`을 실행하세요. 그런 다음 서버 차트의 values 파일에서 `server.agentIdentity.secretName`을 `cma-agent-identity`로 설정하세요.
     </Tab>
   </Tabs>

5. **[설정 파일](https://platform.claude.com/docs/ko/managed-agents/self-hosted/configuration-reference#where-settings-go)을 변경하세요.** [`mcp.allowed_hostnames`](https://platform.claude.com/docs/ko/managed-agents/self-hosted/differences#mcp-servers-need-an-allowlist-entry)에 수신자의 호스트 이름을 나열하고 다음 섹션을 추가하세요:

   ```yaml
   agent_identity:
     issuer: https://agents.example.com
     key_file: /run/cma-server/agent-identity/signing-key.pem
     direct:
       audiences:
         - audience: https://mcp-gateway.example.com
           urls:
             - https://mcp-gateway.example.com
   ```

   각 `audience`는 하나의 수신자를 `https://` URL로 지정합니다. 해당 `urls`는 그 audience에 대한 토큰을 받을 수 있는 MCP 서버의 URL 접두사입니다.

6. **서버를 다시 시작하세요.** Compose 스택에서는 다시 시작하는 대신 Compose 파일의 디렉터리에서 `docker compose up -d`를 실행하세요.

개인 키를 파일에 두지 않으려면 `key_secret`([시크릿 매니저](https://platform.claude.com/docs/ko/managed-agents/self-hosted/agent-identity#secret-manager)) 또는 `kms_key`(AWS KMS 또는 Google Cloud KMS)를 사용하세요. [구성 레퍼런스](https://platform.claude.com/docs/ko/managed-agents/self-hosted/configuration-reference#agent-identity)에서 두 설정을 설명합니다.

### MCP 서버로 토큰 보내기

[MCP 커넥터](https://platform.claude.com/docs/ko/managed-agents/mcp-connector)에서 에이전트의 MCP 서버 항목의 필드를 설명합니다. 해당 항목에 `auth` 필드를 추가하세요:

```yaml
mcp_servers:
  - type: url
    name: tickets
    url: https://mcp-gateway.example.com/tickets
    auth:
      type: agent_token
      audience: https://mcp-gateway.example.com
```

각 도구 목록 조회 또는 도구 호출마다 서버는 새 토큰에 서명합니다. 서버는 vault 자격 증명 대신 `Authorization: Bearer <token>`으로 토큰을 보냅니다. 모델과 워커 모두 이 토큰을 받지 않습니다.

토큰과 [볼트 자격 증명](https://platform.claude.com/docs/ko/managed-agents/vaults)을 모두 보내려면 `auth` 필드를 `agent_token_header` 필드로 바꾸세요:

```yaml
mcp_servers:
  - type: url
    name: tickets
    url: https://mcp-gateway.example.com/tickets
    agent_token_header:
      audience: https://mcp-gateway.example.com
```

볼트 자격 증명은 두 필드가 모두 없는 항목과 마찬가지로 `Authorization` 헤더에 담겨 전송됩니다. 토큰은 `Bearer` 접두사 없이 `Agent-Identity-Token` 헤더에 담겨 전송됩니다.

SDK에는 `auth` 및 `agent_token_header` 필드가 없습니다. SDK 코드에서는 MCP 서버 항목에 해당 필드를 추가 필드로 추가하거나, 요청을 일반 JSON으로 보내세요.

다음 페이지에서 추가 필드를 보내는 방법을 보여 줍니다:

[Python SDK](https://platform.claude.com/docs/ko/cli-sdks-libraries/sdks/python#undocumented-request-params) · [TypeScript SDK](https://platform.claude.com/docs/ko/cli-sdks-libraries/sdks/typescript#undocumented-request-params) · [Go SDK](https://platform.claude.com/docs/ko/cli-sdks-libraries/sdks/go#request-fields) · [Java SDK](https://platform.claude.com/docs/ko/cli-sdks-libraries/sdks/java#undocumented-parameters) · [PHP SDK](https://platform.claude.com/docs/ko/cli-sdks-libraries/sdks/php#undocumented-request-parameters) · [Ruby SDK](https://platform.claude.com/docs/ko/cli-sdks-libraries/sdks/ruby#undocumented-request-params)

그중 일부 페이지에서는 목록 항목 안이 아니라 요청의 최상위 수준에서만 추가 필드를 보여 줍니다. 이 경우 `mcp_servers` 자체를 추가 필드로 만드세요. 항목에 `auth` 또는 `agent_token_header`를 포함하여 목록 전체를 그 방식으로 보내세요.

에이전트의 토큰을 중지하려면 에이전트에서 해당 항목을 제거하거나 에이전트를 보관하세요. 이미 전송된 토큰은 `exp`까지 유효하며, 기본값으로 최대 5분입니다.

### 수신자가 확인하는 사항

다음 조건이 모두 충족될 때만 수신자가 요청을 수락하도록 하세요:

* 서명이 키 세트 `<issuer>/.well-known/jwks.json`의 키로 검증됩니다. 올바른 키는 ID가 토큰 헤더의 `kid`와 일치하는 키입니다. RSA 키의 경우 알고리즘은 `RS256`입니다.
* `iss`가 발급자 URL과 같고, `aud`가 수신자의 audience와 같습니다.
* `exp`는 미래 시점이고, `iat`는 미래 시점이 아닙니다.
* 토큰 헤더의 `typ`이 `agent+jwt`이고, `token_use`가 `agent`입니다.

그런 다음 다음 규칙을 적용하세요:

* 각 에이전트의 액세스 규칙은 API에서의 에이전트 ID인 `agent_id` 클레임을 기준으로 하세요.
* 하나의 목록 조회 또는 호출에 같은 토큰으로 여러 요청이 발생할 수 있으므로, 반복되는 `jti`를 허용하세요.
* 게이트웨이가 각 도구를 자체 자격 증명으로 호출하도록 하고, 토큰을 절대 전달하지 마세요.

[싱글 사인온](https://platform.claude.com/docs/ko/managed-agents/self-hosted/configure#single-sign-on)을 사용하면 도구 호출의 토큰에 세션을 생성한 호출자도 `actor_sub` 및 `actor_iss` 클레임으로 명시됩니다. `actor_sub`는 호출자가 호출을 승인했다는 의미가 아닙니다. 각 호출은 모델이 선택합니다.

다음 토큰에는 `actor_sub`가 없습니다:

* 도구 목록 조회의 토큰
* 서브에이전트 호출의 토큰
* 서버 API 키로 생성된 세션의 모든 토큰

규칙이 호출자에 의존하는 경우, `actor_sub`가 없는 도구 호출은 거부하세요.

### MCP 게이트웨이 테스트하기

`check-gateway` 명령은 MCP 게이트웨이에 유효한 토큰과 유효하지 않은 토큰을 보냅니다. 이 명령에 전용 설정 파일(여기서는 `check-gateway.yaml`)을 제공하세요:

1. 서버 설정 중 `mcp` 및 `agent_identity` 섹션만, 그리고 서버가 `limits.mcp_call_timeout`을 설정한 경우 이 값도 파일에 복사하세요.
2. 복사본에서 `key_file`을 명령을 실행하는 머신에서의 키 경로(예: `./agent-identity/signing-key.pem`)로 변경하세요. 디렉터리를 `compose`로 옮겼다면 경로는 `./compose/agent-identity/signing-key.pem`입니다.

`-agent`에는 게이트웨이가 허용하는 에이전트의 ID를 지정하세요. root가 키를 소유하고 있다면 `sudo`를 사용하세요.

```bash
./cma-server check-gateway -config check-gateway.yaml -agent agent_011CYm1BLqPXpQRk5khsSXrs \
  -url https://mcp-gateway.example.com/tickets
```

이 명령은 보내는 각 요청마다 게이트웨이의 응답과 함께 한 줄을 출력합니다. 통과한 실행은 이어서 `check-gateway: PASS`로 시작하는 줄을 출력하고 코드 `0`으로 종료됩니다. 실패한 실행은 `check-gateway:`로 시작하는 줄에 무엇이 잘못되었는지 표시하고 코드 `1`로 종료됩니다.

## 시크릿 매니저

기본적으로 서버는 [볼트 자격 증명](https://platform.claude.com/docs/ko/managed-agents/vaults)의 시크릿을 데이터베이스에 저장합니다. `secret_store` 섹션을 추가하면 서버는 새로운 각 볼트 자격 증명의 시크릿을 사용자가 이를 위해 예약한 이름 접두사 아래에 두고 시크릿 매니저에 씁니다. 데이터베이스에는 참조만 유지됩니다.

사용하는 시크릿 매니저의 블록을 [설정 파일](https://platform.claude.com/docs/ko/managed-agents/self-hosted/configuration-reference#where-settings-go)에 추가하세요:

<Tabs>
  <Tab title="AWS Secrets Manager">
    ```yaml
    secret_store:
      type: aws_secrets_manager
      region: us-east-1
      prefix: cma-server/prod/
    ```
  </Tab>

  <Tab title="Google Cloud Secret Manager">
    ```yaml
    secret_store:
      type: gcp_secret_manager
      project: my-project        # the project ID, not its number
      prefix: cma-server-prod--
    ```
  </Tab>

  <Tab title="Azure Key Vault">
    ```yaml
    secret_store:
      type: azure_key_vault
      vault_url: https://my-vault.vault.azure.net
      prefix: cma-server-prod--
    ```
  </Tab>

  <Tab title="HashiCorp Vault">
    ```yaml
    secret_store:
      type: hashicorp_vault
      address: https://vault.internal:8200
      prefix: cma-server/prod/
      approle:
        role_id: <role-id>
        secret_id_file: /run/vault/secret-id
      #kubernetes: { role: cma-server }
      #token_file: /run/vault/token
    ```

    세 가지 로그인 방식 중 정확히 하나를 설정하세요:

    * **`approle`:** Docker Compose, 호스트 또는 서버 Helm 차트와 함께 사용하세요. 서버는 역할 ID와 파일에서 읽은 시크릿 ID로 로그인합니다.
    * **`kubernetes`:** 서버 파드에 서비스 계정 토큰이 있는 자체 Kubernetes 설치에서만 사용하세요. 서버는 해당 토큰으로 로그인합니다. 서버 Helm 차트는 서버의 파드에 이러한 토큰을 제공하지 않으므로, 이 방식은 차트에서 작동하지 않습니다.
    * **`token_file`:** 그 밖의 Vault 로그인 방식에 사용하세요. 서버 옆에서 Vault Agent를 실행하고, Vault Agent가 이 파일에 토큰을 쓰도록 하세요.

    서버 Helm 차트를 사용하는 경우, Secret으로 서버에 시크릿 ID를 제공하세요:

    1. 서버의 네임스페이스에 있는 Secret에 시크릿 ID를 넣고, 차트의 `server.extensionFiles.secretName`에 해당 Secret의 이름을 지정하세요.
    2. `approle.secret_id_file`을 시크릿 ID의 경로로 설정하세요. 차트는 해당 Secret의 각 키를 `/run/cma-server/extension-files/` 아래에 파일로 마운트하므로, `secret-id`라는 키는 `/run/cma-server/extension-files/secret-id`에 있습니다.

    `kubernetes` 방식의 경우, Vault Kubernetes 역할을 샌드박스의 네임스페이스인 `cma`가 아니라 서버의 네임스페이스와 서비스 계정에 바인딩하세요.
  </Tab>
</Tabs>

### 접근 권한 부여

서버에 하나의 ID를 부여하고, 해당 ID의 접근 범위를 접두사로 제한하세요. 아카이브의 `iam/` 디렉터리에는 각 시크릿 매니저에 대한 파일이 있습니다:

* **AWS Secrets Manager:** `aws-secrets-manager-policy.json`의 플레이스홀더를 바꾸고, 서버가 실행되는 ID에 정책을 연결하세요.
* **Google Cloud Secret Manager:** `gcp-secret-manager-role.yaml`의 주석에 있는 명령을 실행하세요.
* **Azure Key Vault:** Azure 역할은 접두사가 아니라 키 볼트 전체에 적용됩니다. 따라서 배포에 Azure 역할 기반 액세스 제어를 사용하는 전용 키 볼트를 제공하세요. `azure-key-vault-role.json`에서 `SUBSCRIPTION_ID`를 바꾸고, 이 파일로 사용자 지정 역할을 생성하세요. 키 볼트에서 서버가 실행되는 ID에 해당 역할을 할당하세요.
* **HashiCorp Vault:** `hashicorp-vault-policy.hcl`의 플레이스홀더를 바꾸고, 서버가 실행되는 ID에 정책을 연결하세요.

AWS와 Google Cloud에 대해서는 서버가 추론할 때와 같은 방식으로 인증합니다. Azure Key Vault에 대해서는 [Microsoft Foundry](https://platform.claude.com/docs/ko/managed-agents/self-hosted/inference-provider#microsoft-foundry)와 마찬가지로 Microsoft Entra ID로 인증합니다.

### 설정 확인

처음 시작하기 전과 정책을 변경한 후에는 `validate-store`를 실행하세요. 이 명령은 서버를 시작하지 않고 접두사 아래에 테스트 시크릿을 생성하고, 읽고, 삭제합니다. 서버가 실행되는 곳에서 서버의 환경으로 명령을 실행하세요:

* **Docker Compose:** 서버의 컨테이너에서 실행하세요. Arm에서는 이 명령의 `linux_amd64`를 `linux_arm64`로 바꾸세요:

  ```bash
  docker compose exec cma-server /opt/cma-server/bin/linux_amd64/cma-server validate-store -config /etc/cma-server/config.yaml
  ```

* **호스트에서:**

  ```bash
  ./cma-server validate-store -config /etc/cma-server/config.yaml
  ```

* **Kubernetes:** 서버의 서비스 계정으로 같은 명령을 Job으로 실행하세요.

통과한 실행은 `pass`라고 표시된 줄로 끝나며 코드 `0`으로 종료됩니다.

Azure Key Vault를 사용하는 경우, 이를 사용하기 전에 키 볼트를 대상으로 이 확인을 실행하세요.

### 시크릿 매니저 제한 사항

* **설정은 한 번만 선택하세요.** 다음 변경 중 하나라도 하면, 서버는 변경 전에 작성한 시크릿을 더 이상 찾지 못합니다:

  * `secret_store` 섹션을 제거합니다.
  * `type`, `prefix`, `region`, `project`, `vault_url`, `mount`, `namespace`를 변경합니다. 마지막 두 개는 선택적인 HashiCorp Vault 설정입니다.
  * `address`가 다른 Vault를 가리키도록 합니다.

  서버는 이전 값을 복원할 때만 해당 시크릿을 다시 찾습니다.

* **하나의 ID가 접두사 전체를 읽습니다.** 두 그룹이 서로의 자격 증명에 접근할 수 없어야 한다면, 각 그룹에 별도의 배포를 제공하세요. 각 배포에는 자체 접두사 또는 키 볼트와 자체 ID가 필요합니다.

## 환경 변수 자격 증명

[환경 변수 자격 증명](https://platform.claude.com/docs/ko/managed-agents/vaults#add-a-credential)을 사용하면 샌드박스가 시크릿의 플레이스홀더만 보유한 상태에서 에이전트의 명령이 서비스를 호출할 수 있습니다. 이그레스 게이트웨이는 자격 증명에 나열된 호스트로 가는 요청에 실제 값을 넣습니다.

게이트웨이인 `cma-egress`는 릴리스 아카이브에 포함된 프록시로, 샌드박스와 인터넷 사이에 위치합니다. 기본적으로 꺼져 있으며, 서버는 게이트웨이가 켜져 있을 때만 이러한 자격 증명을 허용합니다.

게이트웨이가 켜져 있으면 샌드박스에 두 가지 제한이 적용됩니다:

* 샌드박스는 게이트웨이를 통해서만 인터넷에 접근합니다.
* 게이트웨이는 서버의 `egress.allowed_hostnames` 설정에 나열한 호스트에만 연결합니다.

와일드카드 없이 정확한 공개 호스트 이름을 나열하세요. 에이전트의 명령이 다운로드하는 모든 호스트를 포함하세요.

자체 샌드박스 이미지를 빌드했다면, [자체 샌드박스 이미지 빌드하기](https://platform.claude.com/docs/ko/managed-agents/self-hosted/call-the-api#what-an-image-of-your-own-needs)에 나온 대로 `cma-with-egress`를 통해 워커를 시작하세요.

### Compose 스택에서 게이트웨이 켜기

`docker-compose.yml`이 있는 디렉터리에서 `.env`에 두 줄을 추가하세요. 첫 번째 줄은 게이트웨이가 연결하는 호스트를 쉼표로 구분하여 나열합니다. 두 번째 줄은 게이트웨이의 Compose 파일을 로드합니다. 그런 다음 스택을 시작하세요:

```bash
echo 'CMA_EGRESS__ALLOWED_HOSTNAMES=api.github.com' >> .env
echo 'COMPOSE_FILE=docker-compose.yml:docker-compose.egress.yml' >> .env
docker compose up --build -d
```

다른 Compose 파일도 사용하는 경우 `COMPOSE_FILE` 줄에 추가하세요. 셸의 `COMPOSE_FILE` 변수는 `.env`의 변수보다 우선하므로 셸의 변수 설정을 해제하세요.

게이트웨이의 파일이 서버의 다른 `egress` 설정을 지정하므로, `compose.config.yaml`에 `egress` 섹션을 추가하지 마세요.

### Kubernetes에서 게이트웨이 켜기

이 단계는 [Kubernetes에 배포하기](https://platform.claude.com/docs/ko/managed-agents/self-hosted/kubernetes)의 배포에서 시작합니다. 해당 페이지의 `REGISTRY`, `TAG`, `PLATFORM` 변수와 두 개의 values 파일을 사용합니다. OpenSSL 3.0 이상을 사용하여 아카이브의 최상위 디렉터리에서 명령을 실행하세요. 샌드박스 차트는 Azure Kubernetes Service(AKS)에서 게이트웨이를 제공하지 않습니다.

이 단계에서 수행하는 서버 차트의 업그레이드는 서버 파드에 네트워크 정책도 추가합니다. 시작하기 전에 이 정책이 적용되는 포트 중 두 개를 확인하세요:

* **포트 9464(메트릭 포트):** 정책이 이 포트를 닫습니다. Prometheus가 해당 포트를 스크레이프하는 경우 `cma-server-values.yaml`에서 `server.telemetry.prometheus.scraper.namespace`를 Prometheus가 실행되는 네임스페이스로 설정하세요.
* **포트 8400(API 포트):** 정책이 모든 소스를 허용합니다. 포트 8400에 접근할 수 있는 대상을 제한하는 자체 정책이 있다면, 그 제한은 더 이상 작동하지 않습니다. 네트워크 정책은 누적되므로, 어느 하나의 정책이라도 허용하면 연결이 통과합니다.

<Steps>
  <Step title="게이트웨이 이미지 빌드 및 푸시">
    ```bash
    docker buildx build --platform "$PLATFORM" -f kubernetes/egress/Dockerfile -t "$REGISTRY/cma-egress:$TAG" --push .
    ```
  </Step>

  <Step title="인증 기관 및 게이트웨이 키 생성">
    ```bash
    (umask 077 && openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -days 825 \
      -subj "/CN=cma-server egress gateway" \
      -addext "basicConstraints=critical,CA:TRUE,pathlen:0" \
      -addext "keyUsage=critical,keyCertSign,cRLSign" \
      -keyout egress-ca.key -out egress-ca.crt)
    kubectl -n cma create secret tls cma-egress-ca --cert=egress-ca.crt --key=egress-ca.key
    kubectl -n cma-server create configmap cma-egress-ca --from-file=ca.crt=egress-ca.crt
    GATEWAY_KEY=$(openssl rand -hex 32)
    printf %s "$GATEWAY_KEY" | kubectl -n cma create secret generic cma-egress-gateway-key --from-file=gateway-key=/dev/stdin
    printf %s "$GATEWAY_KEY" | kubectl -n cma-server create secret generic cma-egress-gateway-key --from-file=gateway-key=/dev/stdin
    unset GATEWAY_KEY
    ```

    그런 다음 인증 기관의 개인 키인 `egress-ca.key`를 삭제하세요. 이 키를 보유한 사람은 누구나 샌드박스에 대해 어떤 웹사이트로든 가장할 수 있습니다. 인증서는 825일 동안 유효합니다. [인증서 갱신](https://platform.claude.com/docs/ko/managed-agents/self-hosted/agent-identity#renew-the-certificate)을 참조하세요.
  </Step>

  <Step title="이전 세션의 샌드박스 제거">
    환경에서 실행된 세션이 없다면 이 단계를 건너뛰세요. 변경 전의 샌드박스는 변경 후 워커를 시작할 수 없습니다. 다음 명령은 각 샌드박스의 작업 공간도 삭제합니다:

    ```bash
    kubectl -n cma scale deployment cma-dispatcher --replicas=0
    kubectl -n cma delete sandboxwarmpool cma-sandbox
    kubectl -n cma delete sandboxclaims --all
    ```

    Google Kubernetes Engine(GKE)에서는 다음 명령도 실행하세요:

    ```bash
    kubectl -n cma delete sandboxes --all
    ```

    `kubectl -n cma get sandboxes,pods,pvc`가 아무것도 찾지 않을 때까지 반복하세요. "샌드박스 측 켜기" 단계의 `helm upgrade`가 디스패처를 다시 시작합니다.
  </Step>

  <Step title="서버 측 켜기">
    클러스터의 Service 범위에서 게이트웨이에 사용할 비어 있는 IPv4 주소를 선택하세요. `kubectl get svc -A`의 `CLUSTER-IP` 열에 해당 범위의 주소가 표시됩니다. 다음 내용을 `cma-server-values.yaml`에 추가하세요. 파일에 이미 `server` 블록이 있다면 이 줄들을 해당 블록에 병합하세요:

    ```yaml
    egressGateway:
      enabled: true
      proxyAddress: 34.118.224.53:3128   # the address that you chose, and port 3128
    server:
      config:
        egress:
          allowed_hostnames:
            - api.github.com
    ```

    그런 다음 업그레이드를 실행하세요:

    ```bash
    helm upgrade cma-server kubernetes/server/chart --namespace cma-server -f cma-server-values.yaml --wait
    ```
  </Step>

  <Step title="샌드박스 측 켜기">
    `kubectl -n cma-server get svc`를 실행하여 서버의 두 Service를 나열하세요. 새로 설치한 경우 이름은 `cma-server` 및 `cma-server-egress`입니다.

    `cma-values.yaml`에서 `egress.mode`를 `gateway`로 변경하고, `egress` 아래에 `gateway` 블록을 추가하세요. 명령이 나열한 두 이름을 블록에 지정하세요:

    ```yaml
    egress:
      mode: gateway
      gateway:
        serviceIP: 34.118.224.53   # the address that you chose
        serverService: cma-server
        serverEgressService: cma-server-egress
        apiServerCIDRs:
          - 203.0.113.10/32        # the cluster's API endpoint
    ```

    파일의 다른 `egress` 값은 유지하세요. API 엔드포인트의 주소와 포트를 출력하려면 `kubectl get endpoints kubernetes -n default`를 실행하세요. 포트가 443이 아니라면 `egress.gateway.apiServerPort`도 설정하세요.

    ```bash
    helm upgrade cma kubernetes/chart --namespace cma -f cma-values.yaml --wait
    ```

    업그레이드가 `.spec.replicas`에 대한 충돌로 중단되면 `kubectl -n cma scale deployment cma-dispatcher --replicas=1`을 실행한 다음 업그레이드를 다시 실행하세요.
  </Step>
</Steps>

### 자격 증명 추가

[자격 증명 추가](https://platform.claude.com/docs/ko/managed-agents/vaults#add-a-credential)에 나온 대로 환경 변수 자격 증명을 생성하세요. 호스팅 가이드에는 이러한 자격 증명이 자체 호스팅 샌드박스에서 지원되지 않는다고 나와 있습니다. 이는 사용자의 서버가 아니라 호스팅 서비스에 관한 것입니다.

서버는 자체 규칙을 추가합니다. 규칙을 위반하는 요청은 해당 필드를 명시한 `400` 오류로 거부합니다. 그중 두 가지 규칙은 다음과 같습니다:

* `networking` (csharp, go: `Networking`)은 유형이 `limited`여야 하며, `allowed_hosts` (java, php: `allowedHosts`; csharp, go: `AllowedHosts`)의 모든 호스트가 서버의 `egress.allowed_hostnames` 목록에 있어야 합니다.
* `injection_location` (java, php: `injectionLocation`; csharp, go: `InjectionLocation`)은 JSON에서 `{"header": true}`여야 하며, 생략할 수 없습니다.

서버의 목록에 호스트를 추가한 후에는 변경 사항을 적용하세요. Docker Compose에서는 `docker compose up -d`를 실행하세요. Kubernetes에서는 서버의 `helm upgrade` 명령과 `kubectl -n cma-server rollout restart deployment -l anthropic.com/role=server`를 실행하세요.

### 이그레스 게이트웨이 확인

자격 증명의 vault로 세션을 생성하고, 에이전트에게 두 명령을 실행하도록 요청하세요. 이 예시는 `api.github.com`을 나열하는 `GITHUB_TOKEN`이라는 이름의 자격 증명에 대한 것입니다:

```bash
printenv GITHUB_TOKEN
curl -sS -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/user
```

첫 번째 명령은 `cma_ph_`로 시작하는 플레이스홀더를 출력합니다. 두 번째 명령은 게이트웨이가 플레이스홀더를 토큰으로 대체했기 때문에 토큰의 GitHub 계정 프로필을 출력합니다. 게이트웨이는 목록에 없는 호스트로의 요청을 `403` 오류로 거부합니다.

Kubernetes에서 모든 요청이 `503` 오류를 받는다면, kube-proxy의 `--masquerade-all` 옵션처럼 클러스터의 네트워크가 파드의 주소를 재작성하고 있을 가능성이 높습니다. 게이트웨이는 파드의 주소로 샌드박스를 구분하므로, 해당 주소가 변경되지 않은 채로 게이트웨이에 도달해야 합니다.

### 인증서 갱신

Kubernetes에서는 실행 중인 세션이 없을 때 인증서를 갱신하세요. [Kubernetes에서 게이트웨이 켜기](https://platform.claude.com/docs/ko/managed-agents/self-hosted/agent-identity#turn-on-the-gateway-on-kubernetes)의 "인증 기관 및 게이트웨이 키 생성" 단계 전체를 반복하세요. 이 단계는 인증 기관과 게이트웨이 키를 다시 생성하므로, 삭제한 `egress-ca.key` 파일이 필요하지 않습니다. 한 가지만 변경하세요: `kubectl create`를 실행하는 네 줄 각각의 끝에 `--dry-run=client -o yaml | kubectl apply -f -`를 추가하세요. 예를 들어 `--from-file=gateway-key=/dev/stdin`으로 끝나는 줄은 `--from-file=gateway-key=/dev/stdin --dry-run=client -o yaml | kubectl apply -f -`로 끝나게 됩니다.

그런 다음 서버와 게이트웨이를 다시 시작하세요:

```bash
kubectl -n cma-server rollout restart deployment -l anthropic.com/role=server
kubectl -n cma rollout restart deployment/cma-egress
```

### 이그레스 게이트웨이 제한 사항

* **헤더:** 게이트웨이는 요청 헤더에만 값을 넣으며, URL이나 본문에는 절대 넣지 않습니다. 기본적으로 허용되는 헤더는 `Authorization`뿐입니다. 다른 헤더를 허용하려면 `egress.swap_header_names`에, 또는 Compose 스택의 경우 `.env`의 `CMA_EGRESS__SWAP_HEADER_NAMES`에 `Authorization`과 함께 나열하세요.
* **프록시 변수를 무시하는 프로그램:** 샌드박스는 `HTTPS_PROXY` 및 관련 변수를 통해 게이트웨이를 찾습니다. Maven과 Gradle 같은 Java 도구는 이 변수를 읽지 않으므로 어디에도 접근하지 못합니다.
