메인 콘텐츠로 건너뛰기 탐색으로 건너뛰기 푸터로 건너뛰기

설정 저장소

패스키, 마스터 비밀번호, 복구 코드 잠금 해제를 지원하는 클라이언트 측 암호화 설정 동기화

설정 저장소

설정 저장소는 여러 기기 간에 CLI 설정을 동기화합니다. 설정은 서버가 절대 보유하지 않는 콘텐츠 암호화 키(CEK)로 기기에서 암호화됩니다. 이것이 정확히 무엇을 막고 무엇을 막지 못하는지는 보안 섹션에서 설명합니다.

잠금 해제 방법 (키 슬롯)

저장소당 CEK는 하나이며, LUKS 키 슬롯과 유사하게 각 잠금 해제 방법마다 독립적으로 래핑됩니다. 슬롯 중 하나만 있어도 동일한 키를 열 수 있으며, 데이터를 다시 암호화하지 않고도 슬롯을 추가하거나 제거할 수 있습니다.

방법설명참고
패스키PRF 확장을 지원하는 WebAuthn 패스키가장 강력한 옵션이며 하드웨어 기반
마스터 비밀번호직접 정한 비밀번호를 PBKDF2-SHA256(60만 회 반복)으로 스트레칭PRF 지원 하드웨어 없이도 사용 가능하며, 헤드리스 CLI 등록도 지원
복구 코드RC1-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX 형식으로 생성되는 코드생성 시 단 한 번만 표시되므로 안전한 곳에 보관

모든 방법은 동일한 파이프라인을 거칩니다. 슬롯이 시크릿을 생성하면 이를 서버가 보유한 시크릿과 결합해 CEK의 래핑을 해제합니다. 어느 한쪽만으로는 충분하지 않으며, 슬롯 시크릿은 서버에 전달되지 않습니다. 세 방법 중 마스터 비밀번호가 가장 약합니다. 서버가 비밀번호 추측을 오프라인으로 시도하는 데 필요한 모든 것을 갖고 있으므로 비밀번호는 강력해야 합니다. 패스키와 복구 코드 슬롯에는 이런 약점이 없습니다.

슬롯은 포털의 설정 저장소 페이지에서 관리합니다. 하드웨어 전용 잠금 해제를 원하는 조직은 패스키 필수 정책을 활성화할 수 있으며, 이 정책은 저장소 전체에서 패스키가 아닌 슬롯을 거부하고 취소합니다.

잠금 해제는 기기별로 이루어집니다. 새 기기에서 한 번만 잠금을 해제하면 이후 일상적인 CLI 작업(push/pull)은 패스키를 터치하거나 비밀번호를 입력하지 않아도 작동합니다.

사전 요건

  • 계정에서 2단계 인증 활성화
  • 패스키 방법의 경우: FIDO2 보안 키(예: YubiKey), iCloud Keychain, Google 비밀번호 관리자, 1Password, Dashlane 등 PRF를 지원하는 패스키 제공자
  • 브라우저: Chrome 133+, Edge 133+, Firefox 130+, 또는 Safari 17+

PRF 요건은 패스키 슬롯에만 적용됩니다. 마스터 비밀번호와 복구 코드 방법은 지원되는 모든 브라우저에서 작동합니다.

설정 방법

  1. 사이드바에서 설정 저장소로 이동한 후 설정 저장소 설정을 클릭하세요.
  2. 요건 체크리스트가 브라우저, 2FA, 세션 상태를 확인합니다.
  3. 첫 번째 잠금 해제 방법을 선택한 뒤 설정 저장소 만들기를 클릭합니다.
    • 패스키: 제공자가 PRF를 지원하는 경우입니다. 보안 키를 두 번 터치합니다(등록 한 번, 암호화 키 파생 한 번).
    • 마스터 비밀번호: 모든 브라우저에서 동작하며, Bitwarden처럼 PRF를 지원하지 않는 패스키 제공자에서도 쓸 수 있습니다.
    • 선택 사항으로 복구 코드: 한 번만 표시되므로 스토어를 만들기 전에 저장해 두세요.
  4. 설정이 끝났습니다. CLI는 잠금 해제 비밀을 OS 키링에 보관합니다.

패스키는 나중에 Config Storage 페이지에서 추가할 수 있습니다. 인증기를 잃어버리거나 지원되지 않아도 잠기지 않도록 잠금 해제 방법을 두 개 이상 유지하세요.

PRF 제공자 호환성

제공자PRF 지원플랫폼
YubiKey / FIDO2 보안 키✅Windows 11, macOS, Linux
iCloud Keychain✅macOS 15+, iOS 18+
Google 비밀번호 관리자✅Android
1Password✅Android, iOS
Dashlane✅크로스 플랫폼
Bitwarden 확장❌대신 마스터 비밀번호를 사용하세요
Windows Hello❌미지원

헤드리스 CLI 등록

브라우저가 없는 머신(서버, CI 러너, 실행기 데몬 등)도 마스터 비밀번호 방법으로 기존 저장소에 등록할 수 있습니다.

rdc config remote enable --master-password

요건:

  • 포털을 통해 이미 프로비저닝된 마스터 비밀번호 슬롯 (프로비저닝 과정에서는 브라우저가 키를 보유하므로 이 단계 자체는 헤드리스로 수행할 수 없습니다)
  • 호출을 인증할 config:enroll 범위를 가진 API 토큰

등록은 읽기 작업입니다. CLI는 슬롯의 공개 KDF 매개변수와 래핑된 키를 가져와 로컬에서 비밀번호 시크릿을 파생시키고, 기기에서 CEK의 래핑을 해제합니다. 이를 통해 해당 기기는 설정을 복호화하고 동기화할 수 있게 되며, 저장소 자체를 변경하지는 않습니다.

키가 CLI에 전달되는 방식

rdc config remote enable(그리고 rdc config rotate-cek)은 계정 서버를 통해 잠금 해제 시크릿을 CLI에 전달합니다. CLI와 브라우저는 서로 직접 통신하지 않으므로, 브라우저가 없는 서버에서도, 브라우저가 Windows에 있는 WSL에서도, 휴대폰에서도 똑같이 동작합니다.

  1. 먼저 rdc subscription login으로 CLI에 로그인합니다. 서버는 요청을 해당 계정에 묶어 둡니다.
  2. CLI가 수명이 짧은 요청을 만들고, 링크와 7KQ2-M9XD-P4RT 같은 페어링 코드를 출력합니다. 링크에 담긴 정보는 모두 # 뒤에 들어 있으며, 브라우저는 이 부분을 서버로 보내지 않습니다.
  3. 같은 계정으로 로그인한 아무 브라우저에서나 링크를 엽니다. 다른 계정의 요청은 거부됩니다.
  4. 페이지에서 요청하면 터미널에 출력된 페어링 코드를 입력합니다. 코드가 일치할 때까지 잠금 해제 버튼은 비활성 상태로 유지됩니다.
  5. 패스키 또는 마스터 비밀번호로 잠금을 해제합니다. 브라우저는 키를 CLI 앞으로 봉인하고, 서버는 내용을 읽을 수 없는 데이터를 그대로 전달만 합니다.
  6. CLI가 그 데이터를 복호화하고, 시크릿을 OS 키링에 저장한 뒤 성공을 알립니다.

요청은 10분 후에 만료됩니다. CLI에서 Ctrl+C를 누르면 요청이 취소되고 CLI가 서버에 링크 폐기를 요청하여 링크가 즉시 작동하지 않게 되며, 페이지에는 명령을 다시 실행하라는 안내가 표시됩니다. 이 요청이 전달되지 않으면 링크는 요청이 만료될 때까지 계속 사용할 수 있습니다. 만료된 뒤에 링크를 열었거나, 로그인 리디렉션 과정에서 # 뒷부분이 사라졌다면 명령을 다시 실행하세요.

페어링 코드는 링크 안의 키에서 파생됩니다. 누군가 링크를 자신의 것으로 바꿔치기해도 터미널의 코드와 페이지가 기대하는 코드가 맞지 않으므로, 아무것도 전달되지 않습니다.

이 방식은 링크 변조와, 중계 서버가 데이터를 바꿔치기하거나 위조하는 공격을 막아 줍니다. 반면 변조된 페이지 코드를 내려보내는 서버는 막지 못합니다. 열어 보는 페이지는 계정 서버가 제공하므로, 키의 안전성은 그 코드의 신뢰도만큼입니다. 이 전제는 설정 키를 다루는 포털의 모든 페이지에 똑같이 적용됩니다.

활성화와 오프라인 읽기

rdc config remote enable은 활성 설정을 저장소에 연결합니다. 저장소가 비어 있으면 활성화 시 현재 로컬 설정으로 저장소를 초기화합니다: 로컬 리소스가 저장소의 첫 번째 버전으로 푸시된 후 다시 풀되어 라운드트립이 제대로 이루어졌는지 확인합니다. 저장소에 이미 내용이 있으면 활성화는 덮어쓰는 대신 기존 내용과 조정합니다(실제로 내용이 어긋난 경우 --force를 전달하지 않으면 중단됩니다).

활성화 후에는 설정이 완전한 읽기 캐시를 유지하며, 로컬 설정과 동일한 방식으로 저장 시 암호화되므로 계정 서버에 연결할 수 없을 때도 저장소를 계속 사용할 수 있습니다.

  • 읽기는 오프라인에서도 동작합니다. 캐시된 내용은 캐시된 버전과 타임스탬프(cachedVersion / cachedAt)가 표시된 오래됨 경고와 함께 stderr로 제공됩니다.
  • 쓰기는 서버가 필요하며, 실패 시 안전하게 차단됩니다. 오프라인 쓰기 대기열은 없습니다: 서버에 연결할 수 없는 쓰기는 오류를 내며 해당 서버 이름을 알려줍니다. 쓰기 명령이 성공했다면 그 변경 사항은 반드시 서버에 반영되어 있습니다.
  • 두 기기에서의 동시 편집은 풀-리플레이-리푸시 방식으로 해결됩니다. 서버는 대체 대상 버전 위에 놓인 푸시만 받아들이며, 진 쪽의 푸시는 최신 사본 위에서 다시 재생되므로 다른 곳에서의 동시 편집이 내 변경 사항을 덮어쓰지 않습니다.
  • 로컬 설정(remote 블록이 없는 설정)은 이 영향을 받지 않으며 완전히 오프라인으로 동작합니다.

동기화 대상

각 리포지토리의 네트워크 ID를 포함해 설정의 모든 항목이 동기화됩니다. 다음의 기기 로컬 필드는 예외입니다: schemaVersion, version, remote, encryption, renetPath, credentials.masterPasswordVerifier, 그리고 로그인 관련 필드인 account.accountServer와 account.e2ePublicKey. 로그인과 로그아웃은 기기별로 이루어집니다.

버전과 복원

서버는 각 설정의 최근 50개 버전을 보관합니다.

rdc config remote versions
rdc config remote restore <version>

복원은 이전 내용을 현재 버전 위에 새 버전으로 게시합니다. 버전 번호가 거꾸로 이동하는 일은 없습니다. 복원된 내용은 각 기기가 다음에 풀할 때 반영되며, 복원 작업은 감사 로그에 기록됩니다.

키 순환

저장소의 CEK를 순환하면 새로운 세대로 다시 래핑됩니다.

  • 복구 코드는 순환 시 항상 무효화되므로, 순환 후 새 코드를 생성하여 보관하세요
  • 마스터 비밀번호 슬롯은 순환 마법사에서 비밀번호를 다시 입력한 경우에만 유지됩니다
  • 이전 세대에 남겨진 슬롯은 알 수 없는 복호화 오류로 실패하는 대신 오래된 슬롯(stale)으로 표시됩니다
  • 다른 구성원들의 설정 토큰이 취소되며, 이전 키를 여전히 가지고 있는 기기에는 rdc config remote enable로 다시 활성화하라는 안내가 표시됩니다

구성원 관리

설정 저장소는 조직 단위로 범위가 지정됩니다. 구성원은 웹 포털을 통해 관리됩니다.

  • 구성원 보기: 설정 저장소 → 구성원
  • 구성원 추가: 현재 CLI를 통해서만 가능 (웹 UI 계획 중)
  • 구성원 제거: 구성원 페이지의 제거 버튼 클릭 (2FA + 재인증 필요)

마지막 활성 구성원을 제거하거나 자기 자신을 제거하는 것을 방지하는 안전 장치가 있습니다.

저장소 내 설정은 팀 단위로도 범위가 지정되지만, 이 범위 지정은 서버 측 접근 제어이며 암호학적 격리가 아닙니다: 조직 전체에 걸쳐 하나의 CEK가 모든 팀의 설정을 암호화하며, 어떤 팀을 구성원이 읽을 수 있는지는 서버가 강제합니다.

보안

보호되는 것. 저장된 설정은 서버 스토리지가 침해당한 경우와 수동적인 운영자에 대해 기밀성을 유지합니다. 모든 블롭은 해당 저장소, 설정, 팀, 버전에 묶여 있으므로 서버는 한 설정의 블롭을 다른 것으로 바꿔치기하거나 탐지되지 않게 변경할 수 없습니다.

보호되지 않는 것. 악성 포털 코드를 제공하는 운영자는 브라우저에서 키를 읽을 수 있습니다. 운영자는 또한 아직 최신 버전을 본 적 없는 기기에 최신 버전을 주지 않고 보류할 수도 있습니다.

서버가 할 수 있는 것서버가 할 수 없는 것
설정 ID, 팀, 버전 번호, 타임스탬프, 블롭 크기, 설정이 커밋하는 필드 수와 각 필드의 타입, 클라이언트 IP 주소를 보는 것머신, 리포지토리, 스토리지 이름(블라인드 처리됨)이나 설정 값을 보는 것
설정과 그 이력을 거부, 지연, 삭제하는 것한 설정의 내용을 다른 설정인 것처럼 제공하거나, 기기가 알아채지 못하게 수정하는 것
아직 새 버전을 본 적 없는 기기에 이전 버전을 제공하는 것CLI가 이미 본 것보다 오래된 버전을 CLI에 제공하는 것(CLI가 이를 거부합니다)
마스터 비밀번호 추측을 오프라인으로 시도하는 것패스키나 복구 코드 슬롯을 여는 것

그 밖의 보호 장치:

  • 분할 키: 복호화에는 슬롯 시크릿(기기 측)과 서버 시크릿이 모두 필요합니다
  • 삭제에는 지식이 필요: 설정에서 커밋된 값을 제거하려면 그 값을 알고 있었다는 것을 증명해야 하므로, 부분적인 접근 권한만 가진 에이전트가 조용히 필드를 지울 수 없습니다
  • 순환 토큰: 모든 요청이 설정 토큰을 순환시킵니다. 토큰은 처음 사용된 IP 주소에 바인딩되며 7일 후 만료됩니다
  • 취소: 구성원을 제거하면 그 구성원의 키 슬롯과 토큰이 한꺼번에 삭제됩니다. 이미 받아 간 내용은 해당 기기에 남아 있지만, CEK 순환을 거치면 그 구성원이 가지고 있던 키로는 이후 버전을 열 수 없게 됩니다

문제 해결

오류원인해결 방법
PRF 미지원인증자에 PRF 확장 없음YubiKey, iCloud Keychain, 1Password, Dashlane을 사용하거나 마스터 비밀번호 슬롯을 추가하세요
X25519 미지원브라우저 버전이 너무 오래됨Chrome 133+, Edge 133+, Firefox 130+, 또는 Safari 17+로 업데이트
이미 설정됨조직에 저장소 이미 존재/account/config-storage에서 관리
설정 저장소 미설정서버에 블롭 스토리지 없음관리자에게 R2/RustFS 설정 문의
토큰 만료7일 동안 활동이 없거나 기기가 네트워크를 변경함로그인을 통해 자동으로 갱신됩니다. 저장된 로그인이 없다면 rdc subscription login 또는 rdc config remote enable을 실행하세요
설정이 이전 버전으로 되돌아옴서버가 이 기기가 이미 본 것보다 오래된 사본을 반환함로컬에서는 변경된 것이 없습니다. 다시 시도하고, 계속되면 신고하세요
마지막 구성원 제거 불가저장소가 영구적으로 잠길 수 있음먼저 다른 구성원을 추가하세요
오래된 슬롯슬롯이 마지막 키 순환 이전에 생성됨슬롯을 다시 추가하세요 (복구 코드는 순환할 때마다 재생성해야 합니다)
  • 웹 콘솔, 브라우저에서 저장소 잠금을 해제해 명령을 실행하는 방법
  • 프록시 & 실행기, 잠금 해제된 키가 실행기에 전달되는 방식