키체인 자격 증명 저장

키체인 자격 증명 저장 (Keychain credential storage)

이 문서에서는 gcx가 토큰 형태의 자격 증명을 운영 체제 자격 증명 저장소에 저장하는 방법과, 자격 증명 저장 정책(credential storage) 구성, 그리고 키체인이 잠겼을 때의 해결 방법을 알아봐요.

출처: 문서

본문

gcx는 토큰 형태의 자격 증명을 운영 체제 자격 증명 저장소에 저장해요. macOS에서는 Keychain, Windows에서는 Credential Manager, Linux와 BSD에서는 Secret Service를 사용해요. YAML 파일에는 저장된 자격 증명에 대한 참조(reference)가 들어 있어요. 참조는 다음 값에 바인딩돼요:

  • (값 목록)

복사된 구성 파일은 저장된 자격 증명을 사용할 수 없어요. 복사된 파일은 별도로 인증해야 해요.

일반 텍스트 폴백 (Plaintext fallback)

gcx는 자격 증명 저장 정책이 off로 해석될 때(GCX_KEYCHAIN=off 또는 신뢰하는 credentials.keychain: off를 통해)에만 새 자격 증명을 mode-0600 구성 파일에 보관해요. 이때 gcx는 경고를 출력해요. 자격 증명 저장 구성을 참고하세요.

gcx는 다음 조건에서는 일반 텍스트 폴백을 사용하지 않아요:

  • (조건 목록)

자격 증명 저장 구성 (Configure credential storage)

자격 증명 저장 정책은 신뢰하는 프로세스 전역 설정이에요. on과 off만 허용해요(트리밍 후 대소문자 무시). 생략하면 on이에요. 시스템 또는 사용자 구성 파일에서 구성해요:

credentials:
  keychain: off

off는 mode-0600 YAML 파일에 일반 텍스트로 저장하는 것이 의도적일 때만 사용해요. 예를 들어 OS 자격 증명 저장소를 사용할 수 없는 헤드리스(headless) 머신이나 CI 러너 같은 경우예요. off 모드에서 gcx는 OS 저장소에 접촉하지 않으며, 새 자격 증명과 갱신된 자격 증명은 그 구성 파일에 저장돼요.

GCX_KEYCHAIN은 한 번의 호출이나 셸 환경에서 구성을 덮어쓸 수 있어요:

export GCX_KEYCHAIN=off

정책 우선순위는 구성이 어떻게 선택되는지에 따라 달라져요(높은 것부터):

  • --config GCX_CONFIG GCX_KEYCHAIN on
  • GCX_KEYCHAIN on

자동으로 발견된 저장소 로컬 .gcx.yaml은 이 정책을 설정할 수 있도록 신뢰되지 않아요. gcx는 그 credentials.keychain 값을 무시하고 경고하지만, 그 파일의 일반 구성 필드는 여전히 병합해요. 파일을 검토한 뒤 의도적으로 선택해야 정책이 적용돼요: GCX_CONFIG=.gcx.yaml은 매 호출에서 신뢰하고, --config .gcx.yaml은 현재 명령어에만 신뢰해요.

잘못된 GCX_KEYCHAIN 값은 경고 후 on으로 해석되므로, 오타가 조용히 일반 텍스트 저장을 활성화할 수 없어요. 신뢰하는 구성 파일의 잘못된 값은 검증에 실패하고 credentials.keychain과 원본 파일을 명시해요. 자동으로 발견된 로컬 파일의 잘못된 값은 같은 로컬 정책 경고와 함께 무시돼요.

off 모드에서 저장된 자격 증명 교체 (Replacing a stored credential in off mode)

off로 전환해도 gcx는 저장된 자격 증명을 구성 파일로 되돌리지 않아요. 참조를 보존하지만 읽을 수는 없어요. 각각에 대해 두 가지 선택지가 있어요.

참조 유지하기. 호출에서 GCX_KEYCHAIN=on을 설정하거나, GCX_KEYCHAIN을 해제하고 신뢰하는 구성 파일에 credentials.keychain: on을 설정해요. 유효 정책이 on이 되면 자격 증명이 다시 동작해요.

자격 증명 교체하기. 다시 인증하면 gcx가 새 값을 일반 텍스트로 기록해요. 이는 되돌릴 수 없어요. 비활성화된 저장소를 통해 삭제할 수 없으므로, 교체한 자격 증명은 OS 자격 증명 저장소에 참조 없이 남아 있고 어떤 gcx 명령어도 다시 도달할 수 없어요. 이런 경우 gcx는 정리 안내와 함께 경고해요. 변경을 마치려면 그 오래된 OS 저장소 항목을 직접 삭제하고, 유출된 자격 증명을 교체할 때는 그 정리를 필수로 처리해요.

gcx는 off가 해석되는 동안 자격 증명 저장소에 있는 자격 증명을 제거할 수 없어요. 해당 필드에 대한 gcx config unset과, 그 필드를 소유하는 스택이나 Cloud 항목 삭제는 모두 실패해요. gcx는 참조를 버리고 자격 증명 저장소에 비밀을 남겨두지 않아요. 왜냐하면 그건 일어나지 않은 삭제를 보고하는 것이기 때문이에요. 정책을 on으로 설정하고 명령어를 다시 실행해요. 자격 증명 저장소를 영구적으로 사용할 수 없을 때 on으로 설정해도 소용없어요. 여전히 항목을 읽을 수 없으니까요. 구성 파일을 편집해 참조를 제거한 다음, OS 자격 증명 저장소를 통해 항목을 삭제해요.

이 사항은 자격 증명 저장소에 있는 자격 증명에만 적용돼요. 이미 구성 파일에 일반 텍스트로 있는 자격 증명은 저장소에서 제거할 것이 없으므로 gcx config unset과 항목 삭제가 모두 평소대로 동작해요.

제한된 실행 세션 (Restricted execution sessions)

일부 에이전트 도구는 샌드박스에서 명령어를 실행해요. 샌드박스가 자격 증명 읽기는 허용하고 쓰기는 차단할 수 있어요. 읽기 전용 검사로는 이 상태를 감지할 수 없어요. gcx는 OAuth 로그인이나 토큰 갱신 전에 무작위의 비밀 아닌(비-시크릿) 테스트 값을 쓰고, 읽고, 제거해요. 검사가 실패하면 gcx는 OAuth 흐름을 중단해요. 저장된 OAuth 세션은 그대로 유지돼요.

해결책은 샌드박스 밖에서 같은 명령어를 실행하는 것이에요. 에이전트가 명령어를 실행했다면 에이전트 승인 흐름을 사용해 운영 체제 자격 증명 저장소에 접근할 수 있도록 gcx를 실행해요.

gcx는 이 조건을 자격 증명 저장소 동작에서 감지해요. 하나의 에이전트 도구의 환경 변수에 의존하지 않아요.

Keychain locked

이 오류는 macOS Keychain 또는 Linux·BSD Secret Service가 사용 가능하지만, gcx가 현재 세션에서 잠금을 해제할 수 없다는 뜻이에요. gcx는 자격 증명이 필요한 명령어를 중단해요. 일반 텍스트 자격 증명을 사용하거나 기록하지 않아요. 구성 검사와 복구 명령어는 계속 사용할 수 있어요.

Windows Credential Manager 잠금 실패는 이 오류 클래스에 포함되지 않아요.

자격 증명 저장소를 잠금 해제할 수 없을 때는 환경 변수로 자격 증명을 제공할 수 있어요. 예를 들어 GRAFANA_TOKEN을 사용할 수 있어요.

macOS Keychain 잠금 해제 (Unlock macOS Keychain)

gcx를 실행하는 것과 같은 보안 세션에서 로그인 키체인을 잠금 해제해요. 다른 터미널이나 프로세스 트리에서의 잠금 해제는 gcx 프로세스에 적용되지 않을 수 있어요. gcx 세션에서 다음 명령어를 실행해요:

security unlock-keychain

이 명령어는 키체인 비밀번호를 요청해요. -p 옵션은 사용하지 마세요. 이 옵션은 프로세스 인자에서 비밀번호를 노출해요.

잠금 해제 후 gcx 명령어를 다시 실행해요. 여전히 키체인을 사용할 수 없다면 잠금 해제된 데스크톱 세션에서 gcx를 실행해요.

헤드리스 세션에서 GNOME keyring 잠금 해제 (Unlock a GNOME keyring in a headless session)

헤드리스 또는 SSH 세션에는 잠금 해제 프롬프트에 응답할 에이전트가 없을 수 있어요. 먼저 잠금 상태를 읽어요:

busctl --user get-property org.freedesktop.secrets \
  /org/freedesktop/secrets/collection/login \
  org.freedesktop.Secret.Collection Locked

b true는 컬렉션이 잠겨 있다는 뜻이에요.

gnome-keyring-daemon --unlock은 표준 입력에서 비밀번호를 읽어요. 프롬프트를 표시하지 않아요. --daemonize 옵션은 자식 프로세스를 만들므로, 입력한 비밀번호가 그 프로세스에 도달하지 않아요. 끝의 줄바꿈도 잠금 해제를 막아요. 다음 절차를 사용해요:

stty -echo; printf 'Keyring password: '; read -r PW; stty echo; echo
printf '%s' "$PW" | gnome-keyring-daemon --replace --daemonize --unlock
unset PW

잠금 상태를 다시 읽어요. b false는 컬렉션이 잠금 해제되었다는 뜻이에요.

상태가 바뀌지 않으면 서비스 관리자가 org.freedesktop.secrets 이름을 소유하고 있을 수 있어요. 서비스를 중지하고 잠금 해제 절차를 다시 실행해요:

systemctl --user stop gnome-keyring-daemon.service gnome-keyring-daemon.socket

A credential was rejected before network use

이 오류는 gcx가 자격 증명을 보내지 않았다는 뜻이에요. 이 오류는 다음 원인 중 하나일 수 있어요:

  • (원인 목록)

키체인이 잠겨 있으면 gcx는 Keychain locked 오류를 표시하고 이 페이지의 절차가 적용돼요.

다른 원인이면 파일을 검토하고 오류에서 안내한 정확한 복구 명령어를 실행해요. 오류가 해당 명령어를 주는 경우 gcx config edit user 또는 gcx config edit --config "<path>"를 사용할 수 있어요. 그런 다음 다시 인증하거나, 필드를 교체하거나, 필드를 해제해요.

명시적인 구성 경로가 있어도 누락되었거나, 외부에 있거나, 대상이 일치하지 않는 키체인 참조가 유효해지지는 않아요.

더 알아보기 (Learn more)