콘텐츠 트러스트를 위한 위임(Delegations)
콘텐츠 트러스트를 위한 위임(Delegations)
Docker Content Trust(DCT)에서 위임은 특정 이미지 태그에 누가 서명할 수 있는지를 통제하는 핵심 기능이에요. 위임은 개인 키와 공개 키로 이루어진 키 쌍을 사용하는데, 하나의 위임 안에 여러 키 쌍이나 기여자를 넣을 수 있어요. 덕분에 여러 사용자가 한 위임에 참여할 수도 있고, 키를 교체해야 하는 상황도 유연하게 처리할 수 있답니다.
Docker Content Trust에서 가장 중요한 위임은 바로 targets/releases예요. 이 위임이 신뢰할 수 있는 이미지 태그의 기준이 되는데, 기여자의 키가 이 위임에 등록되어 있지 않으면 태그에 서명할 수 없어요. 다행히 $ docker trust 명령을 사용하면 저장소 초기화, 저장소 키 관리, 그리고 docker trust signer add를 통한 targets/releases 위임에 기여자 키 추가까지 자동으로 처리해 준답니다.
출처: 공식문서
본문
Docker 클라이언트 설정하기
기본적으로 $ docker trust 명령은 이미지 태그에 적힌 레지스트리 URL과 동일한 주소를 Notary 서버 URL로 기대해요. $ docker push와 비슷한 방식이라고 생각하면 돼요. Docker Hub나 DTR을 사용할 때는 레지스트리 URL과 Notary 서버 URL이 같지만, 자체 호스팅 환경이나 서드파티 레지스트리를 사용한다면 Notary 서버의 별도 URL을 지정해 줘야 해요. 이때 다음과 같이 환경 변수를 설정하면 돼요.
$ export DOCKER_CONTENT_TRUST_SERVER=https://<URL>:<PORT>
자체 호스팅 환경에서 이 변수를 내보내지 않으면, 아래와 같은 오류를 만날 수 있어요.
$ docker trust signer add --key cert.pem jeff registry.example.com/admin/demo
Adding signer "jeff" to registry.example.com/admin/demo...
<...>
Error: trust data missing for remote repository registry.example.com/admin/demo or remote repository not found: timestamp key trust data unavailable. Has a notary repository been initialized?
$ docker trust inspect registry.example.com/admin/demo --pretty
WARN[0000] Error while downloading remote metadata, using cached timestamp - this might not be the latest version available remotely
<...>
Notary 서버에 인증이 활성화되어 있거나 DTR을 사용하는 경우에는 Notary 서버에 데이터를 푸시하기 전에 로그인을 해야 해요.
$ docker login registry.example.com/user/repo
Username: admin
Password:
Login Succeeded
$ docker trust signer add --key cert.pem jeff registry.example.com/user/repo
Adding signer "jeff" to registry.example.com/user/repo...
Initializing signed repository for registry.example.com/user/repo...
Successfully initialized "registry.example.com/user/repo"
Successfully added signer: jeff to registry.example.com/user/repo
로그인하지 않으면 이런 오류가 나타나요.
$ docker trust signer add --key cert.pem jeff registry.example.com/user/repo
Adding signer "jeff" to registry.example.com/user/repo...
Initializing signed repository for registry.example.com/user/repo...
you are not authorized to perform this operation: server returned 401.
Failed to add signer to: registry.example.com/user/repo
Notary 클라이언트 설정하기
DCT의 고급 기능 중 일부는 Notary CLI가 필요해요. Notary CLI를 설치하고 설정하는 방법은 다음과 같아요.
-
클라이언트를 다운로드하고 PATH에 등록해 두세요.
-
~/.notary/config.json파일을 만들고 아래 내용을 넣어 주세요.
{
"trust_dir" : "~/.docker/trust",
"remote_server": {
"url": "https://registry.example.com",
"root_ca": "../.docker/ca.pem"
}
}
이렇게 만든 설정 파일에는 로컬 Docker 트러스트 데이터의 위치와 Notary 서버 URL 정보가 담겨 있어요.
Docker Content Trust 사용 사례 밖에서 Notary를 어떻게 활용하는지 더 자세한 내용이 궁금하다면 Notary CLI 문서를 참고하세요.
위임 키 생성하기
첫 번째 기여자를 추가하려면 먼저 위임 키 쌍이 필요해요. 이 키는 $ docker trust 명령으로 로컬에서 생성하거나, 인증 기관(Certificate Authority)을 통해 생성할 수 있어요.
Docker Trust로 키 생성하기
Docker Trust에는 위임 키 쌍을 생성하는 내장 기능이 있어요. $ docker trust generate <name> 명령을 실행하면 위임 개인 키가 자동으로 로컬 Docker 트러스트 저장소에 로드된답니다.
$ docker trust key generate jeff
Generating key for jeff...
Enter passphrase for new jeff key with ID 9deed25:
Repeat passphrase for new jeff key with ID 9deed25:
Successfully generated and loaded private key. Corresponding public key available: /home/ubuntu/Documents/mytrustdir/jeff.pub
수동으로 키 생성하기
RSA나 ECDSA 개인 키와 공개 키가 포함된 X.509 인증서를 직접 생성해야 한다면, openssl이나 cfssl 같은 로컬 도구를 사용할 수 있어요. 회사 내부 CA나 로컬 CA를 함께 활용할 수도 있구요.
다음은 2048비트 RSA 키를 생성하는 예시예요. RSA 키는 최소 2048비트여야 해요.
$ openssl genrsa -out delegation.key 2048
Generating RSA private key, 2048 bit long modulus
....................................................+++
............+++
e is 65537 (0x10001)
delegation.key는 태그 서명에 사용되기 때문에 절대 외부에 노출하면 안 돼요.
이제 공개 키가 포함된 x509 인증서를 생성해야 해요. 상대방에게 필요한 건 바로 이 인증서랍니다. 먼저 CSR(인증서 서명 요청)을 생성하는 명령이에요.
$ openssl req -new -sha256 -key delegation.key -out delegation.csr
그 다음, 이 CSR을 여러분이 신뢰하는 CA에 보내 서명을 받거나, 자체 서명(self-sign)할 수 있어요. 아래 예시는 1년 동안 유효한 자체 서명 인증서를 만드는 방법이에요.
$ openssl x509 -req -sha256 -days 365 -in delegation.csr -signkey delegation.key -out delegation.crt
이제 상대방은 delegation.crt를 여러분에게 전달해 주면 돼요. 자체 서명이든 CA 서명이든 상관없어요.
마지막으로, 개인 키를 로컬 Docker 트러스트 저장소에 추가해야 해요.
$ docker trust key load delegation.key --name jeff
Loading key from "delegation.key"...
Enter passphrase for new jeff key with ID 8ae710e:
Repeat passphrase for new jeff key with ID 8ae710e:
Successfully imported key from delegation.key
로컬 위임 키 확인하기
로컬 Docker 트러스트 저장소에 가져온 키 목록을 확인하려면 Notary CLI를 사용하면 돼요.
$ notary key list
ROLE GUN KEY ID LOCATION
---- --- ------ --------
root f6c6a4b00fefd8751f86194c7d87a3bede444540eb3378c4a11ce10852ab1f96 /home/ubuntu/.docker/trust/private
jeff 9deed251daa1aa6f9d5f9b752847647cf8d705da0763aa5467650d0987ed5306 /home/ubuntu/.docker/trust/private
Notary 서버에서 위임 관리하기
$ docker trust 명령으로 Notary 서버에 첫 번째 위임을 추가하면, 해당 저장소의 트러스트 데이터가 자동으로 초기화돼요. 이 과정에서 Notary 타깃 키와 스냅샷 키가 생성되고, 스냅샷 키는 Notary 서버가 관리하도록 교체된답니다. 이 키들에 대한 자세한 내용은 콘텐츠 트러스트 키 관리 문서에서 확인할 수 있어요.
저장소를 초기화할 때는 로컬의 Notary Canonical Root Key와 그 비밀번호가 필요해요. 이전에 저장소를 초기화한 적이 없어서 Notary 루트 키가 없다면, $ docker trust가 자동으로 새로 만들어 준답니다.
중요
Notary Canonical Root Key는 반드시 안전하게 보관하고 백업해 두세요.
저장소 초기화하기
저장소를 초기화하면서 동시에 첫 번째 키를 위임에 업로드하려면 $ docker trust signer add 명령을 사용하면 돼요. 이 명령은 기여자의 공개 키를 targets/releases 위임에 추가하고, 별도의 targets/<name> 위임도 함께 만들어요.
DCT에서 두 번째 위임의 이름은, 아래 예시에서는 jeff, 키 소유자를 추적하는 데 도움을 주기 위한 것이에요. Notary의 더 고급 사용 사례에서는 추가 위임을 계층 구조로 활용하기도 해요.
$ docker trust signer add --key cert.pem jeff registry.example.com/admin/demo
Adding signer "jeff" to registry.example.com/admin/demo...
Initializing signed repository for registry.example.com/admin/demo...
Enter passphrase for root key with ID f6c6a4b:
Enter passphrase for new repository key with ID b0014f8:
Repeat passphrase for new repository key with ID b0014f8:
Successfully initialized "registry.example.com/admin/demo"
Successfully added signer: jeff to registry.example.com/admin/demo
각 저장소에 어떤 키가 Notary 서버로 푸시되었는지는 $ docker trust inspect 명령으로 확인할 수 있어요.
$ docker trust inspect --pretty registry.example.com/admin/demo
No signatures for registry.example.com/admin/demo
List of signers and their keys for registry.example.com/admin/demo
SIGNER KEYS
jeff 1091060d7bfd
Administrative keys for registry.example.com/admin/demo
Repository Key: b0014f8e4863df2d028095b74efcb05d872c3591de0af06652944e310d96598d
Root Key: 64d147e59e44870311dd2d80b9f7840039115ef3dfa5008127d769a5f657a5d7
Notary CLI로도 위임과 키 목록을 확인할 수 있어요. 아래 출력을 보면 키가 targets/releases와 targets/jeff에 연결되어 있다는 게 확실히 보이죠.
$ notary delegation list registry.example.com/admin/demo
ROLE PATHS KEY IDS THRESHOLD
---- ----- ------- ---------
targets/jeff "" <all paths> 1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1 1
targets/releases "" <all paths> 1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1 1
추가 서명자 추가하기
Docker Trust는 저장소당 여러 위임을 설정할 수 있게 해 줘서, 위임의 수명 주기를 관리하기 좋아요. $ docker trust로 추가 위임을 등록하면, 그 기여자의 키도 역시 targets/releases 역할에 함께 추가된답니다.
참고
저장소 키의 비밀번호가 필요해요. 이 비밀번호는 저장소를 처음 초기화할 때 설정했던 값이에요.
$ docker trust signer add --key ben.pub ben registry.example.com/admin/demo
Adding signer "ben" to registry.example.com/admin/demo...
Enter passphrase for repository key with ID b0014f8:
Successfully added signer: ben to registry.example.com/admin/demo
이제 위임(서명자)이 2개가 되었는지 확인해 볼게요.
$ docker trust inspect --pretty registry.example.com/admin/demo
No signatures for registry.example.com/admin/demo
List of signers and their keys for registry.example.com/admin/demo
SIGNER KEYS
ben afa404703b25
jeff 1091060d7bfd
Administrative keys for registry.example.com/admin/demo
Repository Key: b0014f8e4863df2d028095b74efcb05d872c3591de0af06652944e310d96598d
Root Key: 64d147e59e44870311dd2d80b9f7840039115ef3dfa5008127d769a5f657a5d7
기존 위임에 키 추가하기
키를 교체하거나 만료/폐기해야 하는 상황을 지원하기 위해, 하나의 위임에 여러 기여자 키를 게시할 수 있어요. 이때 필요한 조건은 같은 위임 이름을 사용하는 것뿐이에요. 여기서는 jeff라는 이름을 그대로 사용했어요. Docker Trust가 자동으로 새 키를 targets/releases에 추가해 준답니다.
참고
저장소 키의 비밀번호가 필요해요. 이 비밀번호는 저장소를 처음 초기화할 때 설정했던 값이에요.
$ docker trust signer add --key cert2.pem jeff registry.example.com/admin/demo
Adding signer "jeff" to registry.example.com/admin/demo...
Enter passphrase for repository key with ID b0014f8:
Successfully added signer: jeff to registry.example.com/admin/demo
이제 위임(서명자)에 키 ID가 여러 개 들어 있는지 확인해 볼게요.
$ docker trust inspect --pretty registry.example.com/admin/demo
No signatures for registry.example.com/admin/demo
List of signers and their keys for registry.example.com/admin/demo
SIGNER KEYS
jeff 1091060d7bfd, 5570b88df073
Administrative keys for registry.example.com/admin/demo
Repository Key: b0014f8e4863df2d028095b74efcb05d872c3591de0af06652944e310d96598d
Root Key: 64d147e59e44870311dd2d80b9f7840039115ef3dfa5008127d769a5f657a5d7
위임 제거하기
targets/releases 역할에 연결된 기여자 키까지 포함해서 위임 자체를 제거해야 한다면, $ docker trust signer remove 명령을 사용하면 돼요.
참고
제거된 위임이 서명했던 태그는 활성 위임이 다시 서명해야 해요.
$ docker trust signer remove ben registry.example.com/admin/demo
Removing signer "ben" from registry.example.com/admin/demo...
Enter passphrase for repository key with ID b0014f8:
Successfully removed ben from registry.example.com/admin/demo
트러블슈팅
targets/releases에 사용 가능한 키가 없다는 오류가 나오면, 이미지에 다시 서명하기 전에docker trust signer add로 추가 위임을 등록해야 해요.
WARN[0000] role targets/releases has fewer keys than its threshold of 1; it will not be usable until keys are added to it
- 이미 추가 위임을 등록했는데도
targets/releases에 유효한 서명이 없다는 오류가 나온다면, Notary CLI로targets/releases위임 파일을 다시 서명해야 해요.
WARN[0000] Error getting targets/releases: valid signatures did not meet threshold for targets/releases
위임 파일을 다시 서명할 때는 $ notary witness 명령을 사용해요.
$ notary witness registry.example.com/admin/demo targets/releases --publish
notary witness 명령에 대한 자세한 내용은 Notary 클라이언트 고급 사용 가이드를 참고하세요.
위임에서 기여자의 키 제거하기
위임 키를 교체하는 과정에서 개별 키만 제거하고 위임 자체는 유지하고 싶을 수 있어요. 이때는 Notary CLI를 사용하면 됩니다.
기억해야 할 점은 targets/releases 역할과 해당 서명자 전용 역할인 targets/<name> 양쪽에서 키를 모두 제거해야 한다는 거예요.
- 먼저 Notary 서버에서 키 ID를 확인할게요.
$ notary delegation list registry.example.com/admin/demo
ROLE PATHS KEY IDS THRESHOLD
---- ----- ------- ---------
targets/jeff "" <all paths> 8fb597cbaf196f0781628b2f52bff6b3912e4e8075720378fda60d17232bbcf9 1
1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1
targets/releases "" <all paths> 8fb597cbaf196f0781628b2f52bff6b3912e4e8075720378fda60d17232bbcf9 1
1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1
targets/releases위임에서 키를 제거해요.
$ notary delegation remove registry.example.com/admin/demo targets/releases 1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1 --publish
Auto-publishing changes to registry.example.com/admin/demo
Enter username: admin
Enter password:
Enter passphrase for targets key with ID b0014f8:
Successfully published changes for repository registry.example.com/admin/demo
targets/<name>위임에서도 키를 제거해요.
$ notary delegation remove registry.example.com/admin/demo targets/jeff 1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1 --publish
Removal of delegation role targets/jeff with keys [5570b88df0736c468493247a07e235e35cf3641270c944d0e9e8899922fc6f99], to repository "registry.example.com/admin/demo" staged for next publish.
Auto-publishing changes to registry.example.com/admin/demo
Enter username: admin
Enter password:
Enter passphrase for targets key with ID b0014f8:
Successfully published changes for repository registry.example.com/admin/demo
- 남아 있는 위임 목록을 확인해 볼게요.
$ notary delegation list registry.example.com/admin/demo
ROLE PATHS KEY IDS THRESHOLD
---- ----- ------- ---------
targets/jeff "" <all paths> 8fb597cbaf196f0781628b2f52bff6b3912e4e8075720378fda60d17232bbcf9 1
targets/releases "" <all paths> 8fb597cbaf196f0781628b2f52bff6b3912e4e8075720378fda60d17232bbcf9 1
로컬 위임 개인 키 제거하기
위임 키를 교체하는 과정에서는 로컬 Docker 트러스트 저장소에 있는 위임 개인 키를 제거해야 할 때도 있어요. 이때는 Notary CLI의 $ notary key remove 명령을 사용해요.
- 먼저 로컬 Docker 트러스트 저장소에서 키 ID를 확인할게요.
$ notary key list
ROLE GUN KEY ID LOCATION
---- --- ------ --------
root f6c6a4b00fefd8751f86194c7d87a3bede444540eb3378c4a11ce10852ab1f96 /home/ubuntu/.docker/trust/private
admin 8fb597cbaf196f0781628b2f52bff6b3912e4e8075720378fda60d17232bbcf9 /home/ubuntu/.docker/trust/private
jeff 1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1 /home/ubuntu/.docker/trust/private
targets ...example.com/admin/demo c819f2eda8fba2810ec6a7f95f051c90276c87fddfc3039058856fad061c009d /home/ubuntu/.docker/trust/private
- 로컬 Docker 트러스트 저장소에서 키를 제거해요.
$ notary key remove 1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1
Are you sure you want to remove 1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1 (role jeff) from /home/ubuntu/.docker/trust/private? (yes/no) y
Deleted 1091060d7bfd938dfa5be703fa057974f9322a4faef6f580334f3d6df44c02d1 (role jeff) from /home/ubuntu/.docker/trust/private.
저장소의 모든 트러스트 데이터 제거하기
저장소의 모든 트러스트 데이터를 제거해야 할 때가 있어요. 저장소 키, 타깃 키, 스냅샷 키, 그리고 모든 위임 키까지 포함해서요. Notary CLI로 처리할 수 있어요.
컨테이너 레지스트리에서 특정 저장소를 삭제하기 전에 이 작업이 필요한 경우가 많아요.
$ notary delete registry.example.com/admin/demo --remote
Deleting trust data for repository registry.example.com/admin/demo
Enter username: admin
Enter password:
Successfully deleted local and remote trust data for repository registry.example.com/admin/demo
$ docker trust inspect --pretty registry.example.com/admin/demo
No signatures or cannot access registry.example.com/admin/demo