Сакрэт у Docker ENV застаецца ў вобразе: перанясіце яго ў secret mount

|Аўтар: Рэдакцыя QUASA|4 хв чытання| 1
Сакрэт у Docker ENV застаецца ў вобразе: перанясіце яго ў secret mount

Інструкцыя Docker па сакрэтах зборкі папярэджвае: ENV і ARG не падыходзяць для ключоў, якія патрэбны падчас зборкі, бо могуць раскрыцца ў выніковым вобразе. Значэнне ENV захоўваецца ў яго канфігурацыі; ARG можа пакінуць след у гісторыі або метаданых. Перадайце такі ключ праз BuildKit secret mount: ён будзе даступны патрэбнай інструкцыі RUN без запісу самога файла ў вобраз.

Сакрэт, патрэбны ўжо запушчанай праграме, патрабуе асобнага рашэння. Docker Compose можа змантаваць файл для канкрэтнага сэрвісу, а Docker Swarm — выдаць сакрэт толькі прызначанаму сэрвісу. Праграма пры гэтым павінна чытаць змесціва файла. Само імя файла secret нічога не кажа пра тое, хто захоўвае ключ, мае да яго доступ і замяняе яго.

Дзе ключ трапляе ў вобраз

Паглядзіце на Dockerfile і параметры зборкі. Радок ENV API_KEY=... задае зменную, якая захоўваецца ў канфігурацыі вобраза і пераходзіць у створаныя з яго кантэйнеры. ARG API_KEY=... не становіцца такой зменнай аўтаматычна, але яго значэнне можа выявіцца ў гісторыі зборкі або звестках пра паходжанне вобраза. Замена ENV на ARG таму не вырашае праблему сакрэту.

Праверце таксама інструкцыі COPY і ADD. Калі імі ў вобраз трапіў файл з токенам, выдаленне файла пазнейшай інструкцыяй не прыбірае яго з ужо створанага слоя. Для ключа, які патрэбны толькі пры ўсталяванні залежнасцей, падавайце файл асобна на час адпаведнага кроку зборкі. Для пароля, які праграма выкарыстоўвае пры працы, увогуле не ўключайце яго ў зборку.

Зборка: часовы доступ праз BuildKit

Умоўны прыклад: npm ci павінен атрымаць прыватны .npmrc з токенам рэестра пакетаў. Захоўвайце файл па-за кантэкстам зборкі, напрыклад у ../secrets/private.npmrc адносна каталога праекта. Пасля капіравання package.json і package-lock.json дадайце ў Dockerfile інструкцыю RUN --mount=type=secret,id=npmrc,target=/root/.npmrc,required=true npm ci. Шлях /root/.npmrc падыходзіць, калі npm на гэтым кроку працуе ад root; для іншага карыстальніка задайце адпаведны target.

З каталога праекта запусціце docker build --secret id=npmrc,src=../secrets/private.npmrc -t myapp:clean . . Параметр id звязвае перададзены файл з mount у Dockerfile, а required=true спыняе крок, калі файл не перадалі. Сакрэт даступны толькі падчас гэтай інструкцыі RUN. Ён не стане часткай выніковага слоя, пакуль сама каманда не скапіруе яго туды.

Таму ўмоўны рэцэпт патрабуе яшчэ адной праверкі: npm і скрыпты залежнасцей не павінны друкаваць токен у журнал або запісваць яго ў файлы, што застануцца ў вобразе. Не пераносьце змесціва mount у ENV у наступным радку Dockerfile. Файл на хосце таксама трэба захоўваць з абмежаваным доступам і не дадаваць у рэпазіторый.

Запуск праз Docker Compose: файл для сэрвісу

Інструкцыя Docker Compose апісвае падачу сакрэту як файла ў /run/secrets і доступ толькі для сэрвісаў, якім ён прызначаны. Умоўна, у верхнім раздзеле secrets файла compose.yaml абвясціце db_password з полем file: ../secrets/db_password. У раздзеле services.api.secrets пералічыце db_password і запусціце docker compose up -d. У Linux-кантэйнеры сэрвісу api змесціва будзе даступнае па шляху /run/secrets/db_password.

Праграма павінна адкрыць гэты файл і прачытаць пароль. Некаторыя гатовыя вобразы падтрымліваюць зменную з суфіксам _FILE: у такім выпадку яна змяшчае толькі шлях да сакрэту, напрыклад /run/secrets/db_password, а не сам пароль. Праверце падтрымку гэтай умоўнасці ў дакументацыі канкрэтнага вобраза; калі яе няма, наладзьце чытанне файла ў самой праграме.

Пры выкарыстанні file Docker Compose падае сакрэт з файла на хосце праз bind mount. Гэта не асобнае сховішча ключоў: доступ да зыходнага файла і яго замена застаюцца вашай адказнасцю. Не ўключайце файл у кантэкст зборкі або рэпазіторый і вызначце, хто можа яго чытаць на хосце. Падача новага файла сэрвісу таксама не сцірае пароль з раней сабранага вобраза.

Запуск у Docker Swarm: сакрэт для сэрвісу

У кластары Swarm выкарыстоўвайце механізм Docker secrets для Swarm: ён шыфруе сакрэты пры перадачы і захоўванні, а дазволенаму сэрвісу мантуе расшыфраванае значэнне ў файлавай сістэме ў памяці. Пасля наладжвання Swarm умоўны пароль можна стварыць камандай docker secret create db_password ../secrets/db_password. Каманда docker service create --name api --secret db_password myapp:clean выдасць яго сэрвісу api; вобраз myapp:clean павінен быць даступны вузлам, дзе запусціцца сэрвіс.

У Linux-кантэйнеры праграма прачытае /run/secrets/db_password. Доступ прызначаецца сэрвісу, а не любому кантэйнеру: docker secret create не падае ключ асобнаму кантэйнеру, запушчанаму праз docker run. Калі пароль змяняецца, стварыце новы сакрэт, абнавіце сэрвіс і прыбярыце доступ да старога. Асобна змяніце пароль у базе даных або іншай сістэме, якая яго правярае: замена файла ў кантэйнеры не змяняе ўліковыя даныя там.

Праверка вобраза і замена раскрытага ключа

Пасля новай зборкі выканайце docker image inspect myapp:clean --format '{{json .Config.Env}}'. Вывад паказвае зменныя, захаваныя ў канфігурацыі вобраза; сакрэтнага значэння там быць не павінна. Затым запусціце docker history --no-trunc myapp:clean і праглядзіце поўныя запісы гісторыі на наяўнасць ключа або каманд, якія маглі яго запісаць.

Гэтыя каманды правяраюць канфігурацыю і гісторыю, але не праглядаюць усе файлы слаёў, журналы зборкі і раней распаўсюджаныя копіі вобраза. Калі сапраўдны ключ ужо трапіў у ENV, ARG, скапіраваны файл або вывад зборкі, замяніце яго ў сістэме, якая выдала ключ. Новая зборка з secret mount змяняе спосаб падачы ключа надалей, але не адклікае раней раскрытае значэнне.

Чытайце таксама:

Падзяліцца:

Падпішыцеся на нашу рассылку

Атрымлівайце свежыя навіны пра Web3, ШІ і крыптавалюты проста на пошту.

0