시크릿 관리

OpenClaw는 지원되는 인증 정보가 설정에 평문으로 저장될 필요가 없도록 추가적인 SecretRef를 지원합니다.

평문도 여전히 작동합니다. SecretRef는 인증 정보별로 선택적으로 사용합니다.

목표 및 런타임 모델

시크릿은 인메모리 런타임 스냅샷으로 확인됩니다.

  • 확인은 활성화 시 즉시(eager) 수행되며, 요청 경로에서 지연(lazy) 수행되지 않습니다.
  • 효과적으로 활성 상태인 SecretRef를 확인할 수 없으면 시작 시 즉시 실패합니다.
  • 리로드는 원자적 교체를 사용합니다: 완전히 성공하거나, 마지막으로 알려진 정상 스냅샷을 유지합니다.
  • 런타임 요청은 활성 인메모리 스냅샷에서만 읽습니다.
  • 아웃바운드 전달 경로도 해당 활성 스냅샷에서 읽습니다 (예: Discord 응답/스레드 전달, Telegram 액션 전송). 각 전송마다 SecretRef를 다시 확인하지 않습니다.

이렇게 하면 시크릿 프로바이더 장애가 핫 요청 경로에 영향을 미치지 않습니다.

활성 표면 필터링

SecretRef는 효과적으로 활성인 표면에서만 유효성을 검사합니다.

  • 활성화된 표면: 확인되지 않은 ref가 시작/리로드를 차단합니다.
  • 비활성 표면: 확인되지 않은 ref가 시작/리로드를 차단하지 않습니다.
  • 비활성 ref는 코드 SECRETS_REF_IGNORED_INACTIVE_SURFACE와 함께 비치명적 진단을 생성합니다.

비활성 표면 예시:

  • 비활성화된 채널/계정 항목.
  • 활성화된 계정이 상속하지 않는 최상위 채널 인증 정보.
  • 비활성화된 도구/기능 표면.
  • tools.web.search.provider에 의해 선택되지 않은 웹 검색 프로바이더별 키. 자동 모드(프로바이더 미설정)에서는 프로바이더 자동 감지를 위해 우선순위별로 키가 참조됩니다. 선택 후 선택되지 않은 프로바이더 키는 선택될 때까지 비활성으로 처리됩니다.
  • gateway.remote.token / gateway.remote.password SecretRef는 다음 중 하나가 참이면 활성입니다:
    • gateway.mode=remote
    • gateway.remote.url이 설정됨
    • gateway.tailscale.modeserve 또는 funnel
    • 해당 원격 표면 없이 로컬 모드에서:
      • gateway.remote.token은 토큰 인증이 우선할 수 있고 env/auth 토큰이 설정되지 않았을 때 활성입니다.
      • gateway.remote.password는 비밀번호 인증이 우선할 수 있고 env/auth 비밀번호가 설정되지 않았을 때만 활성입니다.
  • gateway.auth.token SecretRef는 OPENCLAW_GATEWAY_TOKEN (또는 CLAWDBOT_GATEWAY_TOKEN)이 설정된 경우 시작 인증 확인에서 비활성입니다. env 토큰 입력이 해당 런타임에서 우선하기 때문입니다.

게이트웨이 인증 표면 진단

gateway.auth.token, gateway.auth.password, gateway.remote.token, gateway.remote.password에 SecretRef가 설정된 경우, 게이트웨이 시작/리로드 시 표면 상태를 명시적으로 로그합니다:

  • active: SecretRef가 유효한 인증 표면의 일부이며 반드시 확인되어야 합니다.
  • inactive: 다른 인증 표면이 우선하거나 원격 인증이 비활성/미활성이므로 해당 런타임에서 SecretRef가 무시됩니다.

이 항목들은 SECRETS_GATEWAY_AUTH_SURFACE와 함께 로그되며, 활성 표면 정책이 사용한 이유를 포함하여 인증 정보가 활성 또는 비활성으로 처리된 이유를 확인할 수 있습니다.

온보딩 참조 사전 검증

온보딩이 대화형 모드에서 실행되고 SecretRef 저장소를 선택하면, OpenClaw는 저장 전에 사전 유효성 검사를 실행합니다:

  • Env ref: 환경 변수 이름을 유효성 검사하고 온보딩 중 비어 있지 않은 값이 표시되는지 확인합니다.
  • 프로바이더 ref (file 또는 exec): 프로바이더 선택을 유효성 검사하고, id를 확인하며, 확인된 값 유형을 검사합니다.
  • 빠른 시작 재사용 경로: gateway.auth.token이 이미 SecretRef인 경우, 온보딩은 probe/대시보드 부트스트랩 전에 동일한 즉시 실패 게이트를 사용하여 확인합니다 (env, file, exec ref용).

유효성 검사에 실패하면, 온보딩이 오류를 표시하고 재시도할 수 있게 합니다.

SecretRef 규약

모든 곳에서 하나의 객체 형태를 사용하세요:

{ source: "env" | "file" | "exec", provider: "default", id: "..." }

source: "env"

{ source: "env", provider: "default", id: "OPENAI_API_KEY" }

유효성 검사:

  • provider^[a-z][a-z0-9_-]{0,63}$와 일치해야 합니다
  • id^[A-Z][A-Z0-9_]{0,127}$와 일치해야 합니다

source: "file"

{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }

유효성 검사:

  • provider^[a-z][a-z0-9_-]{0,63}$와 일치해야 합니다
  • id는 절대 JSON 포인터(/...)여야 합니다
  • RFC6901 이스케이핑: ~ => ~0, / => ~1

source: "exec"

{ source: "exec", provider: "vault", id: "providers/openai/apiKey" }

유효성 검사:

  • provider^[a-z][a-z0-9_-]{0,63}$와 일치해야 합니다
  • id^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$와 일치해야 합니다
  • id에 슬래시 구분 경로 세그먼트로 . 또는 ..가 포함되면 안 됩니다 (예: a/../b는 거부됨)

프로바이더 설정

secrets.providers에 프로바이더를 정의하세요:

{
  secrets: {
    providers: {
      default: { source: "env" },
      filemain: {
        source: "file",
        path: "~/.openclaw/secrets.json",
        mode: "json", // 또는 "singleValue"
      },
      vault: {
        source: "exec",
        command: "/usr/local/bin/openclaw-vault-resolver",
        args: ["--profile", "prod"],
        passEnv: ["PATH", "VAULT_ADDR"],
        jsonOnly: true,
      },
    },
    defaults: {
      env: "default",
      file: "filemain",
      exec: "vault",
    },
    resolution: {
      maxProviderConcurrency: 4,
      maxRefsPerProvider: 512,
      maxBatchBytes: 262144,
    },
  },
}

Env 프로바이더

  • allowlist를 통한 선택적 허용 목록.
  • 누락되거나 빈 환경 변수 값은 확인 실패.

File 프로바이더

  • path에서 로컬 파일을 읽습니다.
  • mode: "json"은 JSON 객체 페이로드를 기대하고 id를 포인터로 확인합니다.
  • mode: "singleValue"는 ref id "value"를 기대하고 파일 내용을 반환합니다.
  • 경로는 소유권/권한 검사를 통과해야 합니다.
  • Windows 폐쇄적 실패 참고: 경로에 대한 ACL 검증이 불가능하면 확인이 실패합니다. 신뢰할 수 있는 경로에만 해당 프로바이더에 allowInsecurePath: true를 설정하여 경로 보안 검사를 우회하세요.

Exec 프로바이더

  • 설정된 절대 바이너리 경로를 실행하며, 셸을 사용하지 않습니다.
  • 기본적으로 command는 심볼릭 링크가 아닌 일반 파일을 가리켜야 합니다.
  • 심볼릭 링크 명령 경로를 허용하려면 allowSymlinkCommand: true를 설정하세요 (예: Homebrew 심). OpenClaw가 확인된 대상 경로를 유효성 검사합니다.
  • allowSymlinkCommand를 패키지 관리자 경로(예: ["/opt/homebrew"])에 대한 trustedDirs와 함께 사용하세요.
  • 타임아웃, 무출력 타임아웃, 출력 바이트 제한, 환경 허용 목록, 신뢰할 수 있는 디렉터리를 지원합니다.
  • Windows 폐쇄적 실패 참고: 명령 경로에 대한 ACL 검증이 불가능하면 확인이 실패합니다. 신뢰할 수 있는 경로에만 해당 프로바이더에 allowInsecurePath: true를 설정하여 경로 보안 검사를 우회하세요.

요청 페이로드 (stdin):

{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }

응답 페이로드 (stdout):

{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "<openai-api-key>" } } // pragma: allowlist secret

ID별 선택적 오류:

{
  "protocolVersion": 1,
  "values": {},
  "errors": { "providers/openai/apiKey": { "message": "not found" } }
}

Exec 통합 예시

1Password CLI

{
  secrets: {
    providers: {
      onepassword_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/op",
        allowSymlinkCommand: true, // Homebrew 심볼릭 링크 바이너리에 필요
        trustedDirs: ["/opt/homebrew"],
        args: ["read", "op://Personal/OpenClaw QA API Key/password"],
        passEnv: ["HOME"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "onepassword_openai", id: "value" },
      },
    },
  },
}

HashiCorp Vault CLI

{
  secrets: {
    providers: {
      vault_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/vault",
        allowSymlinkCommand: true, // Homebrew 심볼릭 링크 바이너리에 필요
        trustedDirs: ["/opt/homebrew"],
        args: ["kv", "get", "-field=OPENAI_API_KEY", "secret/openclaw"],
        passEnv: ["VAULT_ADDR", "VAULT_TOKEN"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "vault_openai", id: "value" },
      },
    },
  },
}

sops

{
  secrets: {
    providers: {
      sops_openai: {
        source: "exec",
        command: "/opt/homebrew/bin/sops",
        allowSymlinkCommand: true, // Homebrew 심볼릭 링크 바이너리에 필요
        trustedDirs: ["/opt/homebrew"],
        args: ["-d", "--extract", '["providers"]["openai"]["apiKey"]', "/path/to/secrets.enc.json"],
        passEnv: ["SOPS_AGE_KEY_FILE"],
        jsonOnly: false,
      },
    },
  },
  models: {
    providers: {
      openai: {
        baseUrl: "https://api.openai.com/v1",
        models: [{ id: "gpt-5", name: "gpt-5" }],
        apiKey: { source: "exec", provider: "sops_openai", id: "value" },
      },
    },
  },
}

지원되는 인증 정보 표면

정규 지원 및 미지원 인증 정보는 다음에 나열되어 있습니다:

런타임 생성 또는 순환 인증 정보와 OAuth 갱신 자료는 읽기 전용 SecretRef 확인에서 의도적으로 제외됩니다.

필수 동작 및 우선순위

  • ref가 없는 필드: 변경 없음.
  • ref가 있는 필드: 활성화 시 활성 표면에서 필수.
  • 평문과 ref가 모두 있으면, 지원되는 우선순위 경로에서 ref가 우선합니다.

경고 및 감사 신호:

  • SECRETS_REF_OVERRIDES_PLAINTEXT (런타임 경고)
  • REF_SHADOWED (auth-profiles.json 인증 정보가 openclaw.json ref보다 우선할 때의 감사 발견)

Google Chat 호환성 동작:

  • serviceAccountRef가 평문 serviceAccount보다 우선합니다.
  • 형제 ref가 설정되면 평문 값은 무시됩니다.

활성화 트리거

시크릿 활성화는 다음에서 실행됩니다:

  • 시작 (사전 검증 + 최종 활성화)
  • 설정 리로드 핫 적용 경로
  • 설정 리로드 재시작 확인 경로
  • secrets.reload를 통한 수동 리로드

활성화 규약:

  • 성공하면 스냅샷을 원자적으로 교체합니다.
  • 시작 실패 시 게이트웨이 시작을 중단합니다.
  • 런타임 리로드 실패 시 마지막으로 알려진 정상 스냅샷을 유지합니다.
  • 아웃바운드 헬퍼/도구 호출에 명시적 채널별 토큰을 제공하는 것은 SecretRef 활성화를 트리거하지 않습니다. 활성화 지점은 시작, 리로드, 명시적 secrets.reload입니다.

저하 및 복구 신호

정상 상태 후 리로드 시 활성화가 실패하면, OpenClaw는 저하된 시크릿 상태에 진입합니다.

일회성 시스템 이벤트 및 로그 코드:

  • SECRETS_RELOADER_DEGRADED
  • SECRETS_RELOADER_RECOVERED

동작:

  • 저하: 런타임이 마지막으로 알려진 정상 스냅샷을 유지합니다.
  • 복구: 다음 성공적인 활성화 후 한 번 발생합니다.
  • 이미 저하 상태에서 반복 실패 시 경고를 로그하지만 이벤트를 스팸하지 않습니다.
  • 시작 시 즉시 실패는 런타임이 활성화된 적이 없으므로 저하 이벤트를 발생시키지 않습니다.

명령 경로 확인

명령 경로는 게이트웨이 스냅샷 RPC를 통해 지원되는 SecretRef 확인에 참여할 수 있습니다.

두 가지 넓은 동작이 있습니다:

  • 엄격한 명령 경로(예: openclaw memory 원격 메모리 경로, openclaw qr --remote)는 활성 스냅샷에서 읽고 필수 SecretRef를 사용할 수 없으면 즉시 실패합니다.
  • 읽기 전용 명령 경로(예: openclaw status, openclaw status --all, openclaw channels status, openclaw channels resolve, 읽기 전용 doctor/설정 복구 흐름)도 활성 스냅샷을 선호하지만, 대상 SecretRef가 해당 명령 경로에서 사용 불가능하면 중단 대신 저하됩니다.

읽기 전용 동작:

  • 게이트웨이가 실행 중이면, 이 명령들은 먼저 활성 스냅샷에서 읽습니다.
  • 게이트웨이 확인이 불완전하거나 게이트웨이를 사용할 수 없으면, 특정 명령 표면에 대한 대상 로컬 대체를 시도합니다.
  • 대상 SecretRef가 여전히 사용 불가능하면, 명령은 저하된 읽기 전용 출력과 “configured but unavailable in this command path”와 같은 명시적 진단으로 계속됩니다.
  • 이 저하 동작은 명령 로컬 전용입니다. 런타임 시작, 리로드, 전송/인증 경로를 약화시키지 않습니다.

기타 참고:

  • 백엔드 시크릿 순환 후 스냅샷 갱신은 openclaw secrets reload로 처리됩니다.
  • 이 명령 경로에서 사용하는 게이트웨이 RPC 메서드: secrets.resolve.

감사 및 설정 워크플로우

기본 운영자 흐름:

openclaw secrets audit --check
openclaw secrets configure
openclaw secrets audit --check

secrets audit

발견 항목:

  • 저장된 평문 값 (openclaw.json, auth-profiles.json, .env, 생성된 agents/*/agent/models.json)
  • 생성된 models.json 항목의 평문 민감 프로바이더 헤더 잔여물
  • 확인되지 않은 ref
  • 우선순위 섀도잉 (auth-profiles.jsonopenclaw.json ref보다 우선)
  • 레거시 잔여물 (auth.json, OAuth 알림)

헤더 잔여물 참고:

  • 민감한 프로바이더 헤더 감지는 이름 휴리스틱 기반입니다 (일반적인 인증/인증 정보 헤더 이름 및 authorization, x-api-key, token, secret, password, credential과 같은 단편).

secrets configure

다음을 수행하는 대화형 도우미:

  • 먼저 secrets.providers 설정 (env/file/exec, 추가/편집/제거)
  • openclaw.json 및 하나의 에이전트 범위의 auth-profiles.json에서 지원되는 시크릿 포함 필드 선택
  • 대상 선택기에서 새 auth-profiles.json 매핑을 직접 생성 가능
  • SecretRef 세부 정보 캡처 (source, provider, id)
  • 사전 확인 실행
  • 즉시 적용 가능

유용한 모드:

  • openclaw secrets configure --providers-only
  • openclaw secrets configure --skip-provider-setup
  • openclaw secrets configure --agent <id>

configure 적용 기본값:

  • 대상 프로바이더에 대해 auth-profiles.json에서 일치하는 정적 인증 정보 스크럽
  • auth.json에서 레거시 정적 api_key 항목 스크럽
  • <config-dir>/.env에서 일치하는 알려진 시크릿 줄 스크럽

secrets apply

저장된 계획 적용:

openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run

엄격한 대상/경로 규약 세부 정보 및 정확한 거부 규칙은 다음을 참고하세요:

단방향 안전 정책

OpenClaw는 과거 평문 시크릿 값을 포함하는 롤백 백업을 의도적으로 작성하지 않습니다.

안전 모델:

  • 쓰기 모드 전에 사전 검증 성공 필요
  • 커밋 전에 런타임 활성화 유효성 검사
  • 적용은 원자적 파일 교체를 사용하며 실패 시 최선 노력으로 복원

레거시 인증 호환성 참고

정적 인증 정보의 경우, 런타임은 더 이상 평문 레거시 인증 저장소에 의존하지 않습니다.

  • 런타임 인증 정보 소스는 확인된 인메모리 스냅샷입니다.
  • 레거시 정적 api_key 항목은 발견 시 스크럽됩니다.
  • OAuth 관련 호환성 동작은 별도로 유지됩니다.

웹 UI 참고

일부 SecretInput 유니언은 폼 모드보다 원시 편집기 모드에서 설정하기 더 쉽습니다.

관련 문서