Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке Docker Content Trust (DCT)?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Docker Content Trust (DCT)** це система підписування image у Docker. З `DOCKER_CONTENT_TRUST=1` daemon відмовляє pull або run непідписані image і верифікує підписи проти довірених publisher через Notary v1. ```bash export DOCKER_CONTENT_TRUST=1 docker pull myorg/myapp:1.0 # успіх лише якщо підписано docker push myorg/myapp:1.0 # підписує image твоїм ключем ``` **Головне:** DCT працює, але переважно витіснений **Cosign / Sigstore** у 2026, ширша екосистема, краще UX, OCI-native. Багато команд мігрували. DCT все ще валідний для Docker-Hub-центричних workflow; Cosign це сучасний дефолт для нових pipeline.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Docker Content Trust (DCT)** це оригінальний механізм підписування image у Docker. Використовує Notary v1, щоб підписувати image-manifest і верифікувати при pull. У 2026 індустрія переважно перейшла на **Cosign / Sigstore**, але DCT все ще у проді в організаціях, що стандартизовані на Docker Hub. ## Теорія ### TL;DR - DCT підписує image-manifest криптографічними ключами; daemon верифікує підписи перед pull/run. - Вмикається per-process через `DOCKER_CONTENT_TRUST=1`. - Базується на **Notary v1** (TUF-based: The Update Framework). - Ієрархія ключів: root-key → repository-key → tagging-keys → timestamp/snapshot-keys. - **Тренд індустрії:** перехід на Cosign / Sigstore для нової роботи. DCT все ще валідний, але не дефолт. - **Обидва розв'язують:** «чи цей image справді від publisher, якому я довіряю, і не tampered?». ### Як працює DCT 1. Publisher генерує root-key (cold storage) і repository-keys. 2. На `docker push` publisher підписує image-manifest. Підпис зберігається поряд з image у Notary. 3. На `docker pull` з увімкненим DCT daemon тягне підпис з Notary і верифікує проти відомих ключів publisher. 4. Якщо підпис відсутній або невалідний, pull відхиляється. ```bash export DOCKER_CONTENT_TRUST=1 docker pull alpine:3.21 # Pulling - успіх (Alpine-image підписані Docker Inc). docker pull random/image:1.0 # Error: remote trust data does not exist for random/image: # notary.docker.io does not have trust data for docker.io/random/image ``` Непідписані image не pull'аються при увімкненому DCT. ### Push підписаних image ```bash export DOCKER_CONTENT_TRUST=1 docker push myorg/myapp:1.0 # Перший push питає дві passphrase: # - root-key passphrase (раз, тримай у cold) # - repository-key passphrase (для кожного push) # Наступні push'і питають лише repository-key. ``` Ключі живуть у `~/.docker/trust/` за замовчуванням. **Бекап root-key.** Втратив = не можеш ротувати compromised repository-keys. ### Чому команди перейшли на Cosign / Sigstore DCT працює, але має ліміти: - **Прив'язано до Notary v1** — єдиний backend, інтегрований з Docker Hub конкретно. Інші registry мали реалізувати свої Notary-сервери. - **Operational-біль** — custody root-key важка. Загубив root = repo нerecoverable. - **Обмежено image** — DCT підписує Docker-image, крапка. Cosign підписує SBOM, attestation, config, будь-що OCI. - **OCI-native vs grafted-on** — Cosign використовує OCI-native signature-artifacts; DCT окрему Notary-базу. - **Keyless signing (Sigstore)** — Cosign + Sigstore дозволяє підписувати short-lived OIDC-based identities (без long-lived ключів). Дефолт 2026. ```bash # Cosign (сучасно) cosign sign --identity-token=$OIDC_TOKEN myorg/myapp:1.0 cosign verify --certificate-identity=ci@myorg.com myorg/myapp:1.0 # vs DCT (legacy) DOCKER_CONTENT_TRUST=1 docker push myorg/myapp:1.0 ``` Нова supply-chain security-робота у 2026 починається з Cosign + Sigstore. DCT підтримується, але не розширюється. ### Концепт TUF (коротко) DCT побудовано на **The Update Framework (TUF)**, спроектованому у NYU, щоб подолати відомі атаки на software update-системи: - **Root-роль** — визначає, кому довіряти. Найвища довіра, рідко використовується. - **Targets-роль** — підписує реальні targets (image). - **Timestamp-роль** — short-lived підпис, що доводить свіжість. - **Snapshot-роль** — підписує список поточних targets. Ця шарова key-модель захищає від сценаріїв як «attacker компрометує registry, але не може mint підписи» або «old-version replay». ### Коли все ще брати DCT - **Docker-Hub-центричні workflow**, де DCT уже інтегровано і працює. - **Compliance-вимоги**, що специфічно посилаються на DCT (рідко; зазвичай вони кажуть «підписані image» загально). - **Закриті екосистеми** без інтернет-доступу, де Sigstore-OIDC не можна (DCT можна налаштувати чисто offline). ### Коли брати Cosign / Sigstore натомість - Нові pipeline, крапка. - Multi-registry workflow. - Треба підписувати більше за image (SBOM, attestation, config). - Хочеш keyless signing через OIDC (GitHub Actions, GitLab CI). - OCI-native pipeline. ### Типові помилки **Сприймати DCT як «увімкнено за замовчуванням»** DCT потребує `DOCKER_CONTENT_TRUST=1` per shell або daemon-wide config. Без нього daemon охоче pull'ить unsigned image. CI має явно ставити. **Втратити root-key** ``` ~/.docker/trust/private/<repo>/. ``` Один ключ, один бекап. Втратив = не можеш revoke repository-keys, не можеш ротувати, не можеш recover. **Міксувати DCT і Cosign без policy** Repo, підписане і DCT, і Cosign, плутає tooling. Обери один підхід per repo. Якщо migrate'єш, крути обидва під час переходу, тоді відправ DCT на пенсію. **Припускати, що DCT підписує image-content напряму** Підписує **manifest**, що посилається на layer-digests. Підпис transitively покриває image. Але самі layer-файли не підписані, manifest це integrity-якір. ### Реальне застосування - **Docker Hub workflow:** організації, що побудували навколо DCT у 2017-2020, все ще використовують для pull-time-верифікації. - **Notary-сервери:** деякі self-hosted registry (Harbor) інтегрують Notary v1 для in-cluster DCT. - **Cosign у CI:** GitHub Actions + Sigstore keyless signing став de-facto дефолтом для нових open-source-image. - **Гібрид:** підписуй через Cosign, верифікуй через admission-controllers (Kyverno, OPA Gatekeeper) при K8s-admission. ### Питання для поглиблення **Q:** Чи DCT верифікує image-content чи лише manifest? **A:** Верифікує manifest, що містить layer-digests. Оскільки digests content-addressed, manifest-signature transitively гарантує layer-integrity. Tampering з layers міняє їхні digests, що інвалідує manifest. **Q:** Чи можу використовувати DCT без Docker Hub? **A:** Так — будь-який registry з Notary-сервером (Harbor, JFrog Artifactory). Постав `DOCKER_CONTENT_TRUST_SERVER` на Notary-endpoint. Менш поширено, ніж Docker Hub. **Q:** Що таке Notary v2? **A:** Спадкоємець Notary v1, спроектовано як частина OCI Notary-spec. Інший signature-формат, OCI-native. На практиці індустрія coalesced навколо Cosign/Sigstore замість Notary v2 для більшості нової роботи. **Q:** Як Cosign відрізняється від DCT на практиці? **A:** Cosign-підписи зберігаються як OCI-artifacts у тому самому registry (без окремого Notary-сервера). Cosign підтримує keyless signing через OIDC (без key-management). Cosign розширюється на SBOM, attestation тощо. DCT image-only і key-based. **Q:** (Senior) Як спроектувати image-signing для multi-team прод-середовища? **A:** Cosign + Sigstore + admission-control. CI білдить і підписує image keyless-OIDC (GitHub Actions / GitLab CI / Buildkite). Rekor Sigstore логує signing-подію. K8s admission-controller (Kyverno, OPA Gatekeeper або sigstore-policy-controller) перевіряє підпис кожного pulled image проти expected-identities. Attestation (SBOM, provenance), підписані поряд з image. Доповни vulnerability-scan, gated при admission. Результат: прод відмовляє будь-якому image, не підписаному OIDC-identity твого CI, і ти маєш audit-trail кожної signing-події у Rekor. ## Приклади ### Увімкнення DCT для CI-pipeline ```bash # CI environment-змінні DOCKER_CONTENT_TRUST=1 DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=$REPO_KEY_PASSPHRASE DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE=$ROOT_KEY_PASSPHRASE # Build і push (підписує автоматично) docker build -t myorg/myapp:1.0 . docker push myorg/myapp:1.0 # Notary-запис створено з підписом. # Прод pull'ить з увімкненим DCT export DOCKER_CONTENT_TRUST=1 docker pull myorg/myapp:1.0 # Daemon тягне підпис, верифікує, pull'ить. ``` ### Еквівалент з Cosign (сучасний) ```bash # CI: GitHub Actions з OIDC - uses: sigstore/cosign-installer@v3 - run: | docker push myorg/myapp:1.0 cosign sign --yes myorg/myapp:1.0 # Без ключів, Sigstore видає short-lived cert, прив'язаний до OIDC-identity GHA-workflow. # Верифікація будь-де cosign verify \ --certificate-identity=https://github.com/myorg/myrepo/.github/workflows/build.yml@refs/heads/main \ --certificate-oidc-issuer=https://token.actions.githubusercontent.com \ myorg/myapp:1.0 ``` Сучасний flow без long-lived ключів, OIDC issuer-pinning і працює на будь-якому OCI-registry. ### Notary CLI для inspect ```bash # Подивитися trust-дані image notary -s https://notary.docker.io list docker.io/library/alpine NAME DIGEST SIZE (BYTES) ROLE 3.21 sha256:abc123... 1234 targets 3.20 sha256:def456... 1234 targets ``` Прямий inspect, що підписано і ким. Корисно для аудитів.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.