Moby: 비밀: 작성 모범 사례, 해야 할 일과 하지 말아야 할 일, 로드맵

에 만든 2015년 05월 26일  ·  203코멘트  ·  출처: moby/moby

Docker에서 비밀(비밀번호, 키 및 관련)을 처리하는 것은 반복되는 주제입니다. 많은 풀 요청이 비밀을 처리하기 위해 특정 기능을 (오용) 사용하려는 사람들에 의해 '하이재킹'되었습니다.

지금까지 우리는 사람들이 이러한 기능을 사용하는 것을 _권장_하지 않습니다. 그 기능은 입증되지 않았거나 비밀을 처리하도록 설계되지 않았기 때문에 "가능성이 있는" 안전하지 않기 때문입니다. 우리는 그들에게 실제적인 대안을 제공하지 _않습니다_ 적어도 모든 상황에 대해 그리고 실제적인 예가 없는 _if_에 대해서는 제공하지 않습니다.

그저 '비밀'이 너무 오래 남아 있는 것 같아요. 그 결과 사용자는 이를 위해 설계되지 않은 기능을 (오용) 사용하게 되며(토론이 이 영역의 기능 요청으로 인해 오염된다는 부작용이 있음) 비밀 작업을 수행할 수 있기 위해 골똘히 건너뛰게 만듭니다.

비밀에 (잘못) 사용되는 기능 / 해킹

이 목록은 불완전하지만 언급할 가치가 있습니다.

  • 환경 변수 . 아마도 "12 factor app" 의 일부이기 때문에 가장 많이 사용됩니다. 환경 변수는 권장되지 않습니다.

    • 컨테이너의 모든 프로세스에서 액세스할 수 있으므로 쉽게 "유출"됨

    • 이미지의 중간 레이어에 보존되고 docker inspect에서 볼 수 있습니다.

    • 컨테이너에 연결된 모든 컨테이너와 공유됨

  • 빌드 시 환경 변수 (https://github.com/docker/docker/pull/9176, https://github.com/docker/docker/pull/15182). 빌드 시 환경 변수는 비밀을 처리하도록 설계 되지 않았습니다 . 다른 옵션이 없기 때문에 사람들은 이를 위해 사용할 계획입니다. 비밀에 적합하다는 _인상_을 방지하기 위해 프로세스에서 해당 변수를 의도적으로 암호화 하지 않기로 결정했습니다.
  • 표시 .. 스쿼시 / 레이어 병합 . (https://github.com/docker/docker/issues/332, https://github.com/docker/docker/pull/12198, https://github.com/docker/docker/pull/4232, https //github.com/docker/docker/pull/9591). 스쿼싱 레이어는 최종 이미지에서 중간 레이어를 제거하지만 이러한 중간 레이어에 사용된 비밀은 여전히 ​​빌드 캐시에 남게 됩니다.
  • 볼륨 . IIRC 일부 사람들은 각 빌드 단계에 대해 볼륨이 다시 생성되어 비밀을 저장할 수 있다는 사실을 사용할 수 있었습니다. 이것이 실제로 작동하는지 확실하지 않으며 수행 방법에 대한 참조를 찾을 수 없습니다.
  • 수동으로 컨테이너 구축 . Dockerfile 사용을 건너뛰고 수동으로 컨테이너를 빌드하여 결과를 이미지에 커밋합니다.
  • 맞춤 해킹 . 예를 들어, 서버에서 비밀을 호스팅하는 curl - 비밀을 처리하고 나중에 모두 단일 레이어에서 제거합니다. (https://github.com/dockito/vault 참조)

그래서, 무엇이 필요합니까?

  • 비밀을 다룰 때 "해야 할 일"과 "하지 말아야 할 일"에 대한 문서를 추가하십시오. @diogomonicahttps://github.com/docker/docker/pull/9176#issuecomment -99542089에서 몇 가지 훌륭한 점을 지적했습니다.
  • 가능한 경우 _current_ 기능을 사용하여 공식적으로 "승인된"/승인된 비밀 처리 방법을 설명합니다.
  • 공식적으로 비밀을 처리하기 위한 로드맵/디자인을 제공합니다. 이를 플러그형으로 만들 수 있으므로 바퀴를 다시 발명하고 이 영역에서 기존 제품(예: Vault , Keywiz , Sneaker)을 사용할 필요가 없습니다.

위의 내용은 빌드 시간런타임 비밀 모두를 염두에 두고 작성/설계해야 합니다.

@calavera 는 새로운 Volume-Drivers(https://github.com/docker/docker/pull/13161)를 사용하는 방법에 대한 빠르고 간단한 개념 증명을 만들었습니다. https://github.com/calavera/docker-volume-keywhiz-fs

참고: 환경 변수는 비밀MySQL , WordPress , PostgreSQL )가 포함됩니다. 이러한 이미지는 작성/구현 시 새로운 '모범 사례'를 채택해야 합니다.

좋은 전통에서, 여기에 비밀을 다루기 위한 몇 가지 오래된 제안이 있습니다.

aresecurity statuneeds-attention

가장 유용한 댓글

나는 그것이 주제에서 벗어났다는 것을 알고 있지만 다른 사람이 이 문제가 거의 1년 동안 활성화되었다는 것을 알아차렸습니다! 내일은 기념일입니다. 👏

모든 203 댓글

ping @ewindisch @diogomonica @NathanMcCauley 이것은 단지 빠른 기록입니다. 설명이 필요하다고 생각되면 자유롭게 수정/업데이트하세요. :)

@dreamcat4 일반 "비밀 API"를 구현하려는 몇 가지 계획이 있습니다. 이를 통해 Vault, Keywiz 또는 Docker와 함께 이름을 지정할 수 있지만 모두 같은 방식으로 사용할 수 있습니다. 이는 초기 생각일 뿐이므로 추가 연구가 필요할 것입니다.

@thaJeztah 예 죄송합니다. 그러한 노력/토론을 어떤 식으로든 방해하고 싶지 않습니다. 나는 그것이 우리가 지금 얼마나 멀리 갈 수 있는지 알아보는 것이 (더 긴 과정의 일부로 그리고 우리가 기다리는 동안) 유용한 연습이 될 수 있다고 더 생각합니다. 그런 다음 현재 프로세스의 한계와 결함을 다른 사람들에게 더 명확하게 나타냅니다. 비밀을 개선하기 위해 기본이 누락되고 추가해야 하는 것이 가장 필요합니다.

또한 런타임 비밀과 빌드 시간 비밀의 다양한 상황에 대해 고려해 볼 가치가 있습니다. 영역 중첩 영역도 있습니다.

그리고 아마도 (도커의 경우) "메모리 내" 비밀을 처리하는 메커니즘을 제공하는 솔루션 간의 한계(장단점)를 고려할 가치가 있을 수도 있습니다. 더 많이 파일 기반 비밀 방법이나 네트워크 기반 방법(예: 로컬 비밀 서버)과는 대조적입니다. 테이블에 대한 현재 해킹은 무엇입니까(적절한 비밀 API까지). 이것은 우리가 현재 docker 기능 세트 위에 핵을 사용하여 달성할 수 없는 docker secrets API에 의해 추가된 고유한 가치(예: 더 강력한 보안)를 이해하는 데 도움이 될 수 있습니다. 그러나 저는 보안 전문가가 아닙니다. 그래서 나는 그러한 것들에 대해 그렇게 확신을 가지고 논평할 수 없습니다.

@dreamcat4 네, 맞습니다. 단기적으로 이러한 링크는 실제로 유용합니다.

또한 런타임 비밀과 빌드 시간 비밀의 다양한 상황에 대해 고려해 볼 가치가 있습니다. 영역 중첩 영역도 있습니다.

감사 해요! 내 원래 설명에 그런 내용이 있었던 것 같은데, 그 과정에서 길을 잃은 것이 틀림없습니다. 나는 총알을 추가 할 것이다

그러나 저는 보안 전문가가 아닙니다.

저도 마찬가지입니다. 그래서 보안 유지 관리자를 "핑"합니다. IMO, 이것은 그들이 쓴 것이어야합니다 😇

@thaJeztah 훌륭한 요약입니다. 시간날때마다 이것저것 찔러봐야겠습니다.

@diogomonica는 _직접 _ 관련이 없지만 빌드 중에 SSH 키 에이전트를 전달하기 위한 긴 공개 기능 요청이 있습니다. https://github.com/docker/docker/issues/6396 댓글 수를 감안할 때 약간의 생각을주는 것이 좋습니다. (실행 여부를 결정하는 경우에도)

루트가 아닌 다른 사용자로 볼륨을 마운트할 수 있다고 가정하면(불가능하다는 것을 알고 있지만 유머러스합니다), 컨테이너에 비밀을 가져오는 데 유리한 접근 방식이 될까요?

그렇다면 -v host_dir:image_dir 데이터 전용 컨테이너를 사용하고 -vc host_dir:image_dir (즉, 볼륨 복사)처럼 보일 수 있는 대안을 옹호하고 싶습니다. 여기서 host_dir의 내용은 다음과 같습니다. 데이터 전용 컨테이너의 image_dir 볼륨에 복사됩니다.

그런 다음 secure-data-only containers 패러다임을 강조하고 해당 볼륨이 암호화되도록 허용할 수 있습니다.

나는 최근에 @jrslv 에서

따라서 두 개의 Dockerfile이 있습니다.

  • Dockerfile.build(여기서 모든 비밀을 복사하기만 하면 됨)
  • Dockerfile.dist(레지스트리에 푸시할 파일)

이제 다음과 같이 배포판을 구축할 수 있습니다.

# !/bin/sh
docker build -t hello-world-build -f Dockerfile.build .
docker run hello-world-build >build.tar.gz 
docker build -t hello-world -f Dockerfile.dist ^

hello-world-build 이미지를 절대 푸시하지 않으므로 귀하의 비밀은 안전합니다.

자세한 내용은 @jrslv 기사를 읽는 것이 좋습니다. http://resources.codeship.com/ebooks/continuous-integration-continuous-delivery-with-docker

@kepkin 을 공유해 주셔서 감사합니다!
방금 기사 읽기를 마쳤습니다. 정말 간결하게!

파일을 내보내고 별도의 Dockerfile을 통해 로드하는 아이디어가 마음에 듭니다. "빌드 캐시에 있는 중간 레이어" 문제 없이 스쿼시하는 것처럼 느껴집니다.

그러나 개발이 복잡해지고 단순성을 위해 세 번째 Dockerfile이 필요할 수 있다는 점이 걱정됩니다.

@kepkin 불쾌 하지 않지만 의미가 없습니다. 비밀은 tarball에 있고 tarball이 프로덕션 이미지로 ADD 되기 때문에 확실히 안전하지 않습니다. tarball을 제거하더라도 찌그러뜨리지 않고 일부 레이어에서 누출됩니다.

@TomasTomecek 예제를 올바르게 이해한다면 tarball은 이미지 레이어가 아니라 _not_ 빌드 컨테이너 내부에 빌드된 바이너리일 뿐입니다. 예를 들어 참조하십시오. https://github.com/docker-library/hello-world/blob/master/update.sh (여기에 관련된 비밀은 없지만 빌드 컨테이너의 간단한 예일 뿐입니다)

@TomasTomecek 도커 이미지 빌드의 비밀에 대해 이야기하고 있습니다. 예를 들어 비공개 GitHub 리포지토리에서 소스 코드를 체크아웃하려면 ssh 키를 전달해야 합니다. 그리고 tarball은 빌드 아티팩트만 포함하지만 GitHub 키는 포함하지 않습니다.

@kepkin 맞아요, 이제야 님의 글을 다시 읽고 볼 수 있게 되었습니다. 미안합니다. 불행히도 배포 이미지를 배포/빌드하는 동안 비밀이 필요한 경우 문제를 해결하지 않습니다(예: 아티팩트 가져오기 및 아티팩트 서비스로 인증). 그러나 빌드 프로세스와 릴리스 프로세스를 분리하는 데는 확실히 좋은 솔루션입니다.

@TomasTomecek 그것이 내가 실제로 아티팩트를 가져오는 방법입니다.

Docker.build 이미지에서 AWS 키 및 암호가 필요한 Amazon S3 이미지의 일부 바이너리 종속성을 다운로드합니다. 검색하고 빌드한 후 필요한 모든 것으로 tarball을 만듭니다.

표준 "모범 사례" 기사("하지 말아야 할 것"에 대해 알려진 "해야 할 것")가 있어 모두 읽을 것을 권장합니까?

Docker Compose가 env_file 옵션을 지원한다는 점에 주목할 가치가 있습니다.

https://docs.docker.com/compose/compose-file/#env - 파일

@afeld docker 자체에도 이 기능이 있습니다. http://docs.docker.com/engine/reference/commandline/run/#set -environment-variables-e-env-env-file을 참조하세요. 하지만 해당 환경 변수는 여전히 같은 장소에 나타나므로 "누출"과 같은 차이를 만들지 마십시오.

나는 이 치트 시트를 우연히 발견했습니다: http://container-solutions.com/content/uploads/2015/06/15.06.15_DockerCheatSheet_A2.pdf

@kepkin 이것은 ssh 키를 docker build 전달하는 방법입니다.

# serve the ssh private key once over http on a private port.
which ncat
if [ "$?" = "0" ]; then
  ncat -lp 8000 < $HOME/.ssh/id_rsa &
else
  nc -lp 8000 < $HOME/.ssh/id_rsa &
fi
nc_pid=$!
docker build --no-cache -t bob/app .
kill $nc_pid || true

172.17.0.1이 도커 게이트웨이 IP인 Dockerfile 내부:

RUN \
  mkdir -p /root/.ssh && \
  curl -s http://172.17.0.1:8000 > /root/.ssh/id_rsa && \
  chmod 600 /root/.ssh/id_rsa && chmod 700 /root/.ssh && \
  ssh-keyscan -t rsa,dsa github.com > ~/.ssh/known_hosts && \
  git clone --depth 1 --single-branch --branch prod [email protected]/app.git . && \
  npm i --production && \
  ... && \
  rm -rf /root/.npm /root/.node-gyp /root/.ssh

누군가 더 간단한 것이 있으면 알려주십시오.

그래서 현재 상태는 어떻습니까?

여름 내내 이러한 우려가 얼마나 널리 퍼졌는지를 나타내는 긴 대화 체인이 있었습니다. 이것은 5월에 제출되었으며 아직 열려 있습니다. 예를 들어 Postgres의 비밀번호는 어떻게 설정합니까?

@thaJeztah 이것을 앞으로 나아가기 위해 무엇을 할 수 있습니까? 다른 다운스트림 프로젝트 전반에 걸쳐 많은 사람들이 이 문제에 관심을 갖고 있는 것 같습니다... ej. https://github.com/rancher/rancher/issues/1269

여기서 하는 일은 _비밀_ 유지되는 것 같아요. :D

이것은 Docker를 프로덕션 스택에 통합할 때 가장 큰 문제입니다. 이것에 대한 진행 상황을 가리키는 로드맵이나 다른 문서가 어딘가에 있습니까?

k8s의 이 주제에 대한 일부 관련 콘텐츠.

이것이 런타임 비밀을 해결하는 잠재적인 방법이라고 생각하십니까?
https://github.com/docker/docker/issues/19508

이 문제는 지원해야 하는 몇 가지 시나리오에 집중하고 각 시나리오에 대한 일련의 지침이 있는지 확인하는 것이 가장 좋습니다. 구현 방법은 프로세스가 끝날 때 요구 사항을 충족하기 위해 결합할 수 있는 일관된 기능 집합이 있는지 여부보다 덜 중요합니다.

꽤 합법적인 우려로 보이는 언급된 몇 가지는 다음과 같습니다.

런타임 자격 증명

  • link 를 공유하는 두 컨테이너 간에 조정된 사용자/비밀번호 정보
  • 정보는 git 저장소에 보관하기 쉽습니다.
  • 푸시된 이미지에서 정보를 유지하기 쉽습니다(로컬 컨테이너는 어떻습니까?)
  • 정보는 .bash_history에서 유지하기 쉽습니다(아마도 너무 먼 다리?)
  • 일부 응용 프로그램은 다른 정보가 포함된 구성 파일의 일부로 비밀을 기대합니다.
  • 일부 응용 프로그램은 비밀을 환경 변수로 예상합니다.
  • 일부 응용 프로그램은 둘 다 허용

내가 '쉬움'이라고 말할 때 사용자가 실수로 잘못된 일을 하고 보안 게시판을 실행하지 않도록 보호하는 이러한 변수를 처리하는 데 인체 공학적으로 제정신인 접근 방식이 있음을 의미합니다. 경험의 스트레스는 종종 실수와 관련된 도구와 관련(읽기: 비난)됩니다.

빌드 타임 자격 증명

  • 프로젝트가 하나 이상의 개인 저장소에서 빌드됨(예: package.json은 git url을 허용함)
  • 빌더가 비밀번호로 보호된 프록시 뒤에 있을 수 있습니다.
  • 빌더가 암호로 보호된 캐시를 사용 중일 수 있습니다.
  • 최종 사용자는 작업 이미지에만 관심을 둡니다(즉, docker build 아닌 pull 또는 FROM을 사용합니다).
  • 푸시된 이미지에서 정보를 쉽게 제거할 수 있습니다.

첫 번째 편집:

일반적인 이미지, 컨테이너에 '누출'된 것과 없는 것에 대한 문서화

  • 이미지에 어떤 파일이 포함됩니까? (COPY 및 ADD만? 다른 것은?)
  • 이미지가 빌드된 후 docker-machine이 유지하는 것은 무엇입니까(특히 boot2docker, 그러나 다른 것은 어떻습니까?)
  • 환경 및 명령줄 변수가 이미지에서 캡처되는 방식 및 캡처되는 위치
  • 이러한 행동 변화에 대한 PR 발행자에 대한 기대

나는 여기서 몇 가지 큰 것을 놓치고 있는 것 같은 느낌이 든다. 내가 잊은 게 있어?

모든 json 서비스에 대한 API 키.

예를 들어(이것이 내 실제 사용 사례임) Docker 빌드는 프로그램을 컴파일하고 API 키는 나를 인증하고 빌드 제품을 Bintray.com에 업로드하는 데 필요합니다.

@dreamcat4 나는 당신이 말하는 것과는 거리가

연속 배포 빌드에 도커 이미지를 사용하고 성공적인 빌드가 끝날 때 빌드 아티팩트를 아카이브로 푸시하는 것에 대해 이야기하고 있습니까? 개인적으로 나는 이것을 더 높은 스트림으로 수행하는 것을 선호하지만(예: Jenkins의 빌드 후 스크립트), 크로스 컴파일하는 경우 약간 까다로울 수 있습니다.

내 세계에서 빌드 에이전트는 바이너리/아카이브를 빌드하고 빌드 프로세스의 '아티팩트'로 유지하며 다른 것이 이를 인프라로 푸시하고 git 리포지토리에 태그를 지정하는 등의 작업을 수행합니다. 프로덕션 문제가 있고 예를 들어 내 npm, docker 또는 Artifactory 저장소가 업그레이드를 위해 다운되었거나 네트워크에 결함이 있습니다.

내가 말하려는 요점은 일반적으로 API 키의 사용에 관한 것이었습니다. API 키가 필요한 컨테이너가 (빌드 타임 또는 런타임에) 상호 작용해야 할 수 있는 다양하고 다양한 온라인 JSON/휴식 서비스가 있습니다. 빌드와 관련하여 구체적으로 설명할 필요는 없습니다.

@dreamcat 오, REST 끝점에 대한 인증 토큰이 있습니까? 그것들이 conf 파일의 postgres 비밀번호와 상당히 다르게 처리된다고 생각하십니까, 아니면 유사하게 처리하시겠습니까?

네, 이 두 가지 유형은 기본 최소 보안 수준을 평가하는 측면에서 다르게 간주되어야 한다고 생각합니다.

API 인증 토큰은 다음과 같은 경향이 있습니다.

  • 비밀번호가 아님
  • 취소 가능
  • 일부(훨씬 적은 하위 집합)는 일회용입니다. 그리고 본질적으로 스스로를 무효화합니다.
  • 종종 API 서비스는 기능의 하위 집합으로 범위가 제한됩니다. (즉, 읽기 전용이거나 특정 작업만 트리거할 수 있음).

비밀번호는 다음과 같은 경향이 있습니다.

  • 보다 완전한 계정 액세스/제어를 위해.
  • 손상되면 공격자가 다른 것으로 변경할 수 있습니다(잠금). 또는 다른 백도어가 삽입되었습니다(예: SQL의 경우 데이터베이스에 있는 다른 계정의 db 수정).
  • 비밀번호가 되면 다른 계정에서 '동일한 비밀번호 재사용' 위험이 상당히 높아집니다. Wheras API 키는 항상 고유하고 다른 용도로는 사용할 수 없는 경향이 있습니다.

따라서 이것이 반드시 비밀 솔루션이 두 가지 유형에 대해 _ 반드시 달라야 함을 의미하지는 않습니다. API 키의 경우 허용되는 최소 기준 보안 수준이 약간 낮을 수 있습니다.

이 최소 수준은 강력한 보안이 설정하기에 더 복잡하거나 문제가 있는 경우 중요합니다. (도커 비밀의 경우 여기에서 사실이거나 솔루션이 얼마나 실현 가능하고 우아한지에 따라 다를 수 있음).

그리고 때때로 비밀번호의 API 키는 보안이 더 강하거나 약할 수 있습니다. 단 하나의 크기가 모든 경우에 가능하지 않다는 것입니다.

예를 들어 - 내 bintray API 키: 내 Dockerfile과 동일한 .git repo에 보관됩니다. 따라서 보안을 유지하기 위해 PRIVATE git repo(SSH를 통해 액세스)에 보관됩니다. 따라서 액세스 권한을 얻는 것은 거기에서 비교적 잘 보호되는 API 키에 대한 것입니다. 그러나 도커에 자체 비밀 기능/보호 기능이 내장되어 있지 않으면 빌드된 도커 이미지에는 항상 API 키가 일반 텍스트로 포함됩니다. 따라서 결과 Docker 빌드 이미지는 git 리포지토리와 같이 비공개로 유지되어야 합니다... 여기에는 다른 사람이 공개적으로 빌드 로그/빌드 상태를 보거나 볼 수 없는 녹온(바람직하지 않은 효과)이 있습니다.

이제 그것은 여러 면에서 이상적이지 않습니다. 그러나 전체 솔루션은 충분히 간단하고 실제로 작동합니다(예: 어제). 앞으로 더 좋은 메카니즘이 있다면 그쪽으로 갈아타는 것도 고려해볼 의향이 있습니다. 그러나 그 메커니즘이 내가 이미 만든 현재 솔루션보다 훨씬 더 비용이 많이 들거나 설정이 복잡하다면 그렇지 않습니다. 따라서 API 키가 1개일 경우 매우 강력한 보안(환영)이 과도할 수 있습니다. 일종의 새로운 NOCAHCE 옵션/Dockerfile 명령을 사용하여 도커의 이미지 레이어 캐시에서 제외하면 됩니다.

암호는 볼트 또는 가능한 볼트와 같은 것이 필요하고 아직 다른 암호 또는 기타 강력한 보안 인증 메커니즘으로 암호화되어야 합니다. (우리는 원하지 않지만 설정이 복잡할 수 있음).

모든 비밀 관련 항목을 관리하고 간소화하기 위한 클라이언트/서버 모델(예: vault )은 구현이 신중하게 수행된 경우 모범 사례이며 대부분의 사용 사례를 다룰 것입니다. 저는 개인적으로 비총체적 접근 방식을 선호하지 않습니다. 왜냐하면 이것이 모범 사례의 기준을 높일 수 있는 기회이기 때문입니다.

이는 장기 실행 클라이언트(이미지를 배포하는 사람의 책임) 및/또는 빌드 시간 클라이언트(빌더의 책임)를 의미합니다. 아마도 전자는 런타임에 인증된 비밀을 제공하는 docker 데몬으로 전송될 수 있습니다.

사실 - 이전 의견에 전적으로 동의합니다. 사람들이 문제를 해결하는 창의적인 방법에 감탄하지 않는다는 것은 아니지만 이것이 꼭 그래야 한다고 생각하지는 않습니다. CI/D와 런타임 모두에서 사용할 수 있는 솔루션을 시도하고 생각해 봅시다. , 컨테이너가 Mesos/Kubernetes 등에 의해 조정될 수 있다는 점을 고려합니다.

글쎄, 나는 Docker가 문제 공간에 몇 가지 추가 꼬임을 제시하기 때문에 약간의 문서가 여기에서 여전히 유용할 것이라고 생각합니다.

볼트 녀석들도 이걸 끝까지 보고 있는 것 같습니다. 이 티켓이 볼 수 있는 티켓이라고 생각합니다.

https://github.com/hashicorp/vault/issues/165

아마도 이것은 협력 할 수있는 것입니다.

@jdmarshall

아마도 이것은 협력 할 수있는 것입니다.

+1

+1 Docker + Hashi Corp 볼트

죄송하지만 더 많은 사람들이 참여함에 따라 솔루션이 복잡해지는 방식이 마음에 들지 않습니다. 예를 들어 Hashi Corp Vault는 암호화된 백엔드 스토리지가 있는 전체 클라이언트 서버 솔루션입니다. 그것은 훨씬 더 많은 움직이는 부품을 추가합니다. 일부 사용 사례는 이러한 수준의 복잡성을 요구하지만 대부분은 그럴 것이라고 확신하지 않습니다. 경쟁 솔루션이 호스트 환경 변수를 사용하는 것이라면 대부분의 개발자가 결국 어느 것이 사용될 것이라고 확신합니다.

개발(예: github 키) 및 배포(예: nginx 인증서 키, db 자격 증명)를 다루는 솔루션을 찾고 있습니다. 환경 변수 또는 빌드 도구로 호스트를 오염시키고 싶지 않으며 물론 비밀이 github(암호화되지 않음) 또는 도커 이미지 디렉토리, 심지어 개인용 디렉토리에 있으면 안 됩니다.

@gittycat 아마도 몇 가지 고유한 사용 사례가 있다는 점에서 귀하의 의견에 동의합니다. 따라서 일부 솔루션은 다른 솔루션보다 간단해야 합니다.

우리는 확실히 ENV 변수에 의존하는 것을 피해야 합니다.

내 취향은 asible의 "vault" mecianism과 유사한 것으로 간단한 키 저장을 달성할 수 있다는 아이디어에 기대고 있습니다. 빌드 컨텍스트(또는 빌드 컨텍스트 외부/옆의 소스) 내에 암호화된 텍스트 파일이 있는 경우. 그런 다음 잠금 해제 키는 해당 파일에서 일반 텍스트 암호 또는 API 키 등을 잠금 해제할 수 있습니다.

나는 단지 ansible의 자체 "vault" 솔루션을 사용한 후에 말하고 있는 것입니다. 상대적으로 고통스럽지 않고 간단합니다. Hashicorp의 금고는 더 안전하지만 설정이 더 어렵고 일반적으로 더 복잡합니다. 나는 당신이 궁극적으로 그것을 백엔드로 사용할 수 없는 기술적 이유를 알지 못하지만(도커 지향 명령줄 도구 뒤에 숨김/단순화).

복잡하고 잠재적으로 신뢰할 수 없는 HTTP 키 저장소 서버를 설정할 필요가 없기 때문에 로컬 파일 저장소를 제안합니다. 비밀 저장소는 보안 문제이므로 기업뿐만 아니라 모든 사용자가 사용할 수 있어야 합니다. 제 2센트 의견일 뿐입니다.

로컬 파일 스토리지 백엔드에 +1, 고급 사용 사례의 경우 Hashicorp Vault와 같은 솔루션의 전체 기능을 선호합니다. 조직에서 배포에 대해 이야기할 때 비밀을 제공하고 통제하는 사람은 비밀을 사용하는 사람이 아닌 다른 사람이라는 주장이 있습니다. 이것은 매우 신뢰할 수 있는 보안 엔지니어로 제한되는 제어 권한을 가진 사람의 범위를 유지하기 위한 일반적인 보안 조치입니다...

이것이 어떤 용도인지 또는 작동할지 모르겠지만 런타임에 비밀을 컨테이너에 주입하려는 경우(예: postgres 암호)를 해결하기 위한 약간의 왼쪽 필드 제안이 있습니다.

docker run 시간에 진입점을 재정의하고 내가 선택한 메커니즘(예: KMS)에서 비밀을 얻은 후 내가 선택한 스크립트로 설정할 수 있다면(예: KMS) 원래 진입점을 실행합니다. (따라서 컨테이너 내부에 비밀이 있는 환경 변수를 설정하는 것이 유일한 목적인 단순한 래퍼가 됩니다. 이러한 스크립트는 볼륨 마운트를 통해 런타임에 제공될 수 있습니다. 이러한 메커니즘은 비밀이 디스크에 기록되는 것을 포함하지 않습니다( 내 애완 동물 중 하나가 싫어함), 또는 도커에 의해 누출되고(도커 검사의 일부가 아님) 컨테이너 내부의 프로세스 1 환경에만 존재하도록 하여 12-factorness를 유지합니다.

진입점이 이미지 메타데이터에 사용되지 않고 cmd만 사용되는 경우 이미 이 작업을 수행할 수 있습니다(믿습니다). 진입점이 명령을 래핑하기 때문입니다. 언급했듯이 래퍼는 volmount를 통해 런타임에 마운트될 수 있습니다. 진입점이 이미 이미지 메타데이터에 사용된 경우 컨테이너 내부에서 원래 진입점이 무엇인지 확인할 수 없다면(cmdline 재정의가 아님) 현재로서는 이를 수행할 수 없다고 생각합니다. 그렇게 할 수 있는지 여부는 확실하지 않습니다. .

마지막으로 외부 /sbin/get_secrets가 실제 비밀(예: postgres 암호)을 요청하는 데 사용할 수 있는 기존 env var 주입을 통해 암호화된 일회성 키를 제공하는 것이 가능하다고 생각하여 도커에 추가 보호 장치를 추가합니다. 1회용 키를 유출합니다.

이것이 레이어의 레이어인지 또는 잠재적으로 문제를 해결할 수 있는지 여부를 알 수 없습니다. 첫 번째 경우 사과드립니다.

@thaJeztah - 위의 솔루션이 작동하는지 확인할 수 있습니다. 비밀은 도커에 의해 누출되지 않고 명시되며, 완벽하게 12개 요소를 준수하는 환경 변수를 통해 프로세스 1에 대한 메모리 내에서만 존재하지만 표시되지 않습니다. docker inspect 아래의 docker api 또는 다른 곳에서는 프로세스 1에만 해당되기 때문입니다. 이 작업을 수행하려면 이미지에서 작업이 필요하지 않습니다. 제 경우에는 비밀 가져오기를 수행하기 위해 golang 정적 바이너리를 컴파일했습니다. 그래서 볼륨을 마운트하고 이것으로 진입점을 덮어쓸 수 있습니다. 이진 파일은 완료되면 이미지 정의 진입점으로 제어를 전송하기 위해 sys exec를 실행합니다.

@gtmtech 흥미

예제 코드 폴더를 사용하면 접근 방식을 좀 더 쉽게 시연/이해할 수 있습니다.

여기 @dreamcat4 @kaos > 예제 코드 및 작업 시나리오

https://github.com/gtmtechltd/secret-squirrel

내가 틀릴 수도 있지만 왜 이러한 복잡한 방법을 사용합니까? 나는 표준 유닉스 파일 권한에 의존합니다. 루트만 읽을 수 있는 -v /etc/secrets/docker1:/etc/secrets 를 사용하여 docker에 모든 비밀을 넘긴 다음 컨테이너 시작 시 루트로 실행하는 스크립트가 있습니다. 이 스크립트는 관련 프로그램(예: apache 구성)의 적절한 위치에 비밀을 전달합니다. 이러한 프로그램은 시작 시 루트 권한을 삭제하므로 해킹되면 나중에 루트 소유의 비밀을 읽을 수 없습니다. 내가 사용하는 이 방법에 결함이 있습니까?

@gtmtech 감사
불행히도 우리는 표준 진입점이 없으며 도커를 제어된 방식으로 실행하기 전에 도커 검사를 실행할 수 없습니다. 하지만 저는 당신의 접근 방식이 좋습니다.

내가 틀릴 수도 있지만 왜 이러한 복잡한 방법을 사용합니까? 나는 표준 유닉스 파일 권한에 의존합니다. -v /etc/secrets/docker1:/etc/secrets 만 읽을 수 있는 -v /etc/secrets/docker1:/etc/secrets 를 사용하여 모든 비밀을 docker에 넘기고 컨테이너 시작 시 루트로 실행하는 스크립트가 있습니다. 이 스크립트는 비밀을 관련 프로그램(예: 아파치)의 적절한 위치에 전달합니다. 구성). 이러한 프로그램은 시작 시 루트 권한을 삭제하므로 해킹되면 나중에 루트 소유의 비밀을 읽을 수 없습니다. 내가 사용하는 이 방법에 결함이 있습니까?

안녕하세요,
나는 이 접근 방식에 동의하고 생각합니다 ^^ 일반적으로 RUNTIME 비밀을 위한 최선의 방법으로 권장되어야 합니다. 여기에 반대하는 다른 사람이 없다면. 그 다음에는 해당되지 않는 나머지 코너 케이스(런타임 시)도 나열할 수 있습니다 ^^.

불행히도 나는 비밀 다람쥐가 이륙하는 것을 볼 수 없습니다. 그 이유는 대부분의 일반 일반 사람들이 일부 인기 있는 전략을 배우고 채택하기에는 너무 복잡하기 때문입니다.

그래서 그것은 떠난다 (아마도 이미 짐작했을 것입니다) ...
빌드 타임의 비밀!

그러나 나는 그것이 발전이라고 생각합니다! 오랜 시간이 지나면 실제로 아무데도 가지 않기 때문에 아마도 일을 절반으로 줄이고 전체 문제의 약 45-50%를 해결할 수 있습니다.

그리고 비밀에 대한 문제가 여전히 남아 있다면, 적어도 그것들은 더 구체적이고/집중되어 있을 것이고, 이후에 계속 진행/해결할 수 있을 것입니다.

예, 너무 자세한 내용은 다루지 않겠지만 이러한 접근 방식은 현재 작업 중인 상황에서는 작동하지 않을 것입니다. 왜냐하면 그들이 제공하는 것보다 더 높은 수준의 보안이 필요하기 때문입니다. 예를 들어 디스크에 암호화되지 않은 비밀 없음, 대상 프로세스에서 복호화되면 유효한 복호화 키 없음, 정기적인 암호화 순환, 암호화된 비밀을 위한 단일 저장소(서버 전체에 확산되지 않음). 따라서 가능한 접근 방식을 제안한 수준의 보안을 수행해야 하는 사람들을 위한 것입니다.

secret_squirrel은 어쨌든 아직 실행 가능한 솔루션을 볼 수 없는 공간에서 해킹입니다. docker 주변에서는 아직 secrets api를 제공하지 않거나 플러그형 secrets-driver를 제공합니다. 언젠가는 제공되기를 바라지만 아마도 ENV 설정을 설명하는 역할을 할 것입니다. 프로세스 실행 전에 컨테이너 내부의 vars, 그러나 docker create 프로세스(또는 메타데이터)의 일부가 아닌 것은 비밀을 준수하는 12단계의 안전한 방법이며, 아마도 docker 개발 커뮤니티는 빌드를 시작할 때 이 아이디어를 사용할 수 있습니다. secrets-api/driver가 좋다고 생각한다면!

즐거운 도킹!

우리는 @gtmtech 가 설명하는 접근 방식을 큰 성공을 거두고 사용하고 있습니다. 환경 변수를 통해 KMS로 암호화된 비밀을 주입한 다음 필요에 따라 컨테이너 내부의 코드가 해독되도록 합니다.

일반적으로 여기에는 애플리케이션 앞에 간단한 shim 진입점이 포함됩니다. 우리는 현재 쉘과 작은 Golang 바이너리(https://github.com/realestate-com-au/shush)의 조합으로 해당 심을 구현하고 있지만 저는 순수 이동 방식의 사운드를 좋아합니다.

@gtmtech @mdub 확실히 더 많이 보게 되어 기쁩니다.
@dreamcat4 "복잡한"의 정의는 경로에 따라 달라질 수 있다고 생각합니다. 이는 분명히 꽤 괜찮습니다. 그러나 그것은 아마도 추상적인 판단이 아닐 것입니다. 따라서 도커 컨테이너 내의 보안 래퍼는 디자인 수준에서 너무 복잡해 보이지 않습니다. 또 다른 측면은 모범 사례입니다. 개발자 전용 관점이 아니라 운영 관점에서 바라봐야 합니다.
내 2센트

금고 +1

금고 -1. Vault에는 많은 사람들에게 실제로 바람직하지 않은 몇 가지 작동 특성(봉인 해제)이 있습니다.

플러그인 가능한 API를 갖는 것이 가장 합리적일 것입니다.

테레즈블의 금고도 있습니다. 그것은 오히려 다른 짐승입니다.

@gtmtech 제안에 감사드립니다. 이 진입점을 작성하는 데 영감을 받았습니다.

#!/bin/bash

if [ -d "/var/secrets" ]; then
  tmpfile="$(mktemp)"
  for file in /var/secrets/*
  do
    if [ -f $file ]; then
      file_contents=$(cat $file)
      filename=$(basename "$file")
      underscored_filename="${filename//-/_}"
      capitalized_filename=${underscored_filename^^}
      echo "export $capitalized_filename=$file_contents" >> $tmpfile
    fi
  done

  source $tmpfile
  rm -f $tmpfile
fi

exec "$@"

다음과 같이 Dockerfile 추가합니다( chmod + x 를 잊지 마세요).

ENTRYPOINT ["/app/docker-entrypoint.sh"]

그리고 짜잔. 런타임에 ENV 변수를 사용할 수 있습니다. 충분하다 :)

내가 올바르게 이해했다면 /var/secrets dir은 볼륨을 통해 마운트되어야 합니까??
또한 비밀이 디스크에 기록되지 않는다는 댓글이 있을 때 디스크에 기록하고 삭제하는 것이 얼마나 나쁜가요???

좋은 것! 그래도 안전하게 파일을 삭제하려면 shred 를 사용해야 합니다.

2016년 3월 3일 목요일 Juan Ignacio Donoso [email protected]
썼다:

내가 올바르게 이해했다면 /var/secrets dir은 다음을 통해 마운트되어야 합니다.
볼륨 맞나요??
또한 비밀이 디스크에 기록되지 않는다는 의견이 있을 때 어떻게
나쁜 것은 디스크에 쓴 다음 삭제하는 것입니다???


이 이메일에 직접 답장하거나 GitHub에서 확인하세요.
https://github.com/docker/docker/issues/13490#issuecomment -191887424.

루이 마리뉴

@gtmtech 의 "secret-squirrel"에서 영감을 받아 이미지 진입점으로 사용할 수 있도록 비밀 관리 도구 "shush"를 확장했습니다.

ADD shush_linux_amd64 /usr/local/bin/shush
ENTRYPOINT ["/usr/local/bin/shush", "exec", "--"]

이것은 모든 KMS_ENCRYPTED_xxx 변수를 해독하고 결과를 환경에 다시 주입합니다.

https://github.com/realestate-com-au/shush#use -as-a-command-shim

따라서 스레드는 DO NOT DO ANY THINGS.....로 시작합니다.

... 하지만 대신해 주세요...대부분 거부/종료된 다양한 제안/해킹만 볼 수 없습니다.

현재 공식적인 모범 사례는 무엇입니까? 도커 사용자로서 우리가 해서는 안 되는 일의 긴 목록을 보고 나서 공식적인 대안이 제공되지 않는 것을 보는 것은 다소 실망스럽습니다. 내가 뭔가를 놓치고 있습니까? 하나가 존재하지 않습니까? 배후에서 일이 일어나고 있고 이것이 도커 팀이 작업하고 있다고 확신하지만, 현재로서는 정식 솔루션이 제시될 때까지 비밀 관리를 가장 잘 처리하는 방법은 무엇입니까?

@alexkolson
내가 아는 한, 런타임에 비밀이 필요한 경우 볼륨(파일 시스템 비밀)이나 HashiCorp Vault(네트워크 비밀)와 같은 일부 서비스를 사용해야 합니다.

빌드 시간 비밀의 경우 더 복잡합니다.
볼륨은 빌드 시 지원되지 않으므로 컨테이너를 사용하여 파일 시스템을 수정하는 명령을 실행하고 docker commit을 사용해야 합니다.

따라서 docker commit 를 사용할 필요 없이 Dockerfile 외에는 아무 것도 사용하지 않고 빌드 시 비밀을 관리할 수 있는 기능이 없습니다.

어떤 사람들은 비밀을 위해 파일 시스템을 사용하는 것이 안전하지 않다고 말하기도 하고 그 도커 데몬은 비밀을 안전하게 제공하기 위해 일부 API를 제공해야 합니다(네트워크/방화벽/자동 마운트된 볼륨 사용?). 그러나 아무도 이 API가 어떻게 생겼는지, 어떻게 사용할지 전혀 모릅니다.

env vars의 짧은 등장을 생각할 때 다음과 같은 도커가 아닌 특정 문제를 생각합니다.

  1. 프로덕션 웹 서버에 남아 있는 모든 환경 변수 또는 잊어버린 phpinfo를 잡는 로그 집계 - 비밀과 구성에 주의해야 합니다.
  2. 환경 변수를 노출하는 트로이 목마일 수 있으므로 신뢰할 수 없는 소프트웨어를 실행하지 마십시오.
  3. SQL 주입과 같은 약점을 악용하는 공격 - 입력을 확인하고 웹 앱 방화벽을 사용하십시오.

이 스레드의 맨 위에 제시된 약점:

컨테이너의 모든 프로세스에서 액세스할 수 있으므로 쉽게 "유출"됨

위에서 1과 2를 교차 적용합니다. 합법이지만 조심스럽게 다루지 않습니까? 또한 도커 컨테이너는 전체 스택 웹 서버보다 훨씬 적은 수의 프로세스를 실행합니다.

env var의 구성은 어떻습니까? 그러나 비밀 env var에는 암호화된 값이 있고 앱에는 코드에 키가 있습니까? 키가 코드에 있기 때문에 이것은 난독화일 뿐이지만 키 및 환경 변수 모두에 액세스하려면 익스플로잇이 필요합니다. 구성 관리를 사용하여 앱 코드가 아닌 도커 호스트에서 키를 관리할 수 있습니다. 루즈 프로세스 및 우발적인 누출에는 도움이 될 수 있지만 분명히 키를 가진 사람의 주입 공격은 아닙니다.

이미지의 중간 레이어에 보존되고 docker inspect에서 볼 수 있습니다.

사람들이 런타임에 설정하는 대신 도커 이미지에 env vars를 굽고 있습니까? 아니면 내가 이것을 오해하고 있습니까? 절대 비밀을 유물로 되돌리지 마십시오. 맞습니까? 예 sudo docker inspect container_name 는 환경 변수를 제공하지만 내 프로덕션 서버에 있는 경우 iv는 이미 손실되었습니다. sudo docker inspect image_name 는 런타임에 설정된 내 환경 변수에 액세스할 수 없습니다.

컨테이너에 연결된 모든 컨테이너와 공유됨

링크와 새로운 네트워킹을 대신 사용하지 않는 것은 어떻습니까?

도커 문제처럼 보이지만 보편적이지 않은 유일한 문제는 링크입니다...

docker build 기간 동안 비밀을 처리하는 좋은 방법이 필요한 사람들의 캠프에 저를 넣어주세요. 우리는 일부 PHP 프로젝트에 작곡가를 사용하고 종속성을 위해 일부 비공개 github 저장소를 참조합니다. 즉, 컨테이너 내부에 모든 것을 구축하려면 이러한 개인 저장소에 액세스하기 위해 ssh 키가 필요합니다.

나는 docker에 대해 유익하다고 생각하는 다른 것들을 물리치지 않고 이 곤경을 처리하는 훌륭하고 합리적인 방법을 찾지 못했습니다( docker squash ).

이제 컨테이너 외부에서 애플리케이션의 일부를 빌드하고 COPY 를 사용하여 최종 제품을 컨테이너로 가져오는 데 회귀해야 했습니다. 음.

내 생각에 docker build 는 비밀과 같은 임시 데이터를 처리하여 최종 배송 컨테이너에 들어가지 않도록 하는 기능이 필요하다고 생각합니다.

도커 빌드에는 비밀과 같은 임시 데이터를 처리하는 기능이 필요하다고 생각합니다.

이것은 기술적인 문제라기보다는 철학적인 문제입니다. 이러한 임시 데이터는 docker의 필수 이점인 재현성을 무효화합니다.

Docker의 철학은 컨텍스트와 함께 Dockerfile이 이미지를 빌드하기에 충분하다는 것입니다.
결과 이미지 외부에 컨텍스트가 필요한 경우 네트워크에서 가져와 파일 시스템에 쓰는 것을 건너뛰어야 합니다. 모든 Dockerfile 행은 파일 시스템 스냅샷을 생성하기 때문입니다.

비밀이 이미지의 일부가 아니어야 하는 경우 비밀로 보호되는 모든 리소스를 미러링/프록시하고 비밀 없는 액세스를 제공하는 임시 컨테이너를 실행할 수 있습니다. 미러링, btw에는 또 다른 근거가 있습니다. https://developers.slashdot.org/story/16/03/23/0652204/how-one-dev-broke-node-and-thousands-of-projects-in-11-lines -of-javascript

ssh 키 자체도 공유할 수 있지만 사용을 제어할 수는 없습니다.

@bhamilton-idexx 개인 저장소에 대한 인증이 수명이 짧은 토큰으로 작동하는지 확인하면 도커 이미지에 비밀이 유지되는 것에 대해 걱정할 필요가 없습니다.
빌드 시스템이 1시간의 ttl로 토큰을 생성하도록 하고 이를 도커 빌드에 대한 환경 변수로 사용할 수 있도록 합니다.
빌드는 필요한 빌드 세부 정보를 가져올 수 있지만 빌드가 완료된 직후 비밀 시간이 초과되어 해당 공격 벡터가 닫힙니다.

여기에 몇 가지 쓰임새를 해결할와 비밀의 쓰임새 외부했을 지금이 스레드의 무리와 하나 개의 기능을 읽고하는 것은입니다 --add 대한 플래그 docker run 복사하는 용기에 파일을 단지 같은 Dockerfiles의 ADD

참으로 훌륭한 기사입니다. 아주 잘 읽었습니다. 그리고 정확히 우리가 보기를 바랐던 것입니다.

BTW:

또한 기사에서 누락된 것으로 보이는 몇 가지 다른 비밀 도구를 찾았습니다. 반복/중복 죄송합니다. 아직 여기에 언급된 것을 눈치채지 못했습니다.

빌드 시간 비밀:

https://github.com/defunctzombie/docket

런타임 비밀:

https://github.com/ehazlett/docker-volume-libsecret

사람들은 어떻게 생각합니까? 감사합니다.

나를위한:

이 새로운 도구 ^^ 이제 아주 좋아 보입니다. 그리고 우리가 이 티켓을 처음 시작할 때 확실히 존재하지 않았습니다. 하지만 지금 내가 느끼는 가장 중요한 것은 여전히 ​​가장 많이 놓치고 있는 부분입니다.

DockerHub에서 빌드 시 비밀에 대한 더 나은 기능을 갖습니다. 그곳에서는 가난하고 둘 중 하나를 선택해야 합니다. 우리는 다른 솔루션의 이점을 위해 한 솔루션의 이점을 포기해야 합니다. 어떤 전체 기능 집합이 더 중요한지에 따라 다릅니다. 로컬 건물은 비밀을 안전하게 유지하는 데 확실히 더 좋지만 다른 면에서는 Dockerhub보다 당연히 더 나쁩니다.

새로운 이미지 형식을 사용하는 docket과 유사한 또 다른 도구를 작성했습니다.

https://github.com/AngryBytes/docker-surgery

우리의 구현은 먼저 SECRETS 주석이 달린 비밀을 포함하는 레이어를 만든 다음 수정된 FROM 가 있는 Dockerfile 복사본을 만들고 결과 이미지에서 모든 SECRETS 레이어를 빌드하고 마지막으로 제거합니다.

이를 해킹할 때는 항상 주의해야 할 사항이 있으며, 도커에 리베이스 또는 레이어 스플라이싱 기능이 내장되어 있다면 더할 나위 없이 좋을 것입니다. 모든 솔루션이 무대 뒤에서 docker save / docker load 춤을 추어야 하기 때문에 지금 중간 레이어를 제거하는 것은 느립니다.

또한 빌드 캐싱이 손상되었습니다. 지금 우리는 docker commit 를 사용하여 주석 처리된 비밀 레이어를 생성하지만 이러한 레이어의 적절한 캐시를 유지하는 것은 여전히 ​​많은 작업이며 우리가 할 것 같지 않습니다. Dockerfile을 사용하여 비밀 계층을 생성하면 이 문제를 해결할 수 있지만 계층에 주석을 달 수 있는 방법이 없으므로 나중에 제거할 항목을 정확히 지적하기 어렵습니다.

@Vanuan [Dockerfile]은 재현할 수 없습니다. RUN 명령은 당신과 내가 두 번의 실행에서 똑같은 이미지를 얻을 것이라고 합리적으로 기대할 수 없도록 보장합니다. 왜요? 대부분의 경우 사람들은 RUN을 사용하여 네트워크 리소스에 액세스하기 때문입니다. 나와 같은 이미지를 원하면 내 이미지 'FROM'을 만들어야 합니다. 다른 어떤 배열도 동일한 이미지를 제공하지 않습니다. 다른 어떤 배열도 우리에게 같은 이미지를 줄 없습니다. 모든 내구성 있는 재현성은 Dockerfile이 아닌 Docker Hub에서 제공됩니다.

임시 데이터를 가질 수 없는 이유에 대한 유일한 방어책이 Docker가 임시 데이터를 모두 제거할 수 있다고 생각하기 때문이라면 RUN 명령을 더 이상 사용하지 않아야 합니다.

@stephank 직장에서 약간 다른 접근 방식을 사용하는 도커 빌드 도구를 구현했습니다. 내 주요 관심사는 빌드 시간 비밀이 아니었지만 그것도 잘 처리합니다.

그리고 그것은 VOLUME의 프로젝트 코드로 "빌드 관리자"를 실행하는 것입니다. 그런 다음 관리자는 관리자의 볼륨을 사용하여 프로젝트 코드를 마운트하는 별도의 컨테이너에서 원하는 수의 빌드 도구를 실행합니다. 따라서 빌드된 아티팩트 및 기타 생성된 파일은 관리자 볼륨에 보관되고 각 빌드 단계의 빌드 파이프라인을 따릅니다. 최종적으로 관리자는 생성된 빌드 결과를 사용하여 최종 프로덕션 이미지를 빌드할 수 있습니다. 그 과정에서 필요한 모든 비밀은 관리자 및/또는 빌드 컨테이너에서 사용할 수 있지만 최종 이미지는 사용할 수 없습니다. 도커 이미지 마법사가 사용되지 않고 빌드 캐시가 예상대로 작동합니다.

빌드 파이프라인의 모양은 빌드 요구 사항을 구성하는 사양 파일을 사용하는 프로젝트에 전적으로 달려 있습니다.

사실, 나는 이 도구에 대해 과대 광고를 하고 있으며, 우리가 이 도구를 오픈 소스로 출시할 수 있기를 기다리고 있습니다(채택될 회사 정책 지침 보류 중).

@kaos 한편으로는 기본 Docker 도구에서 벗어나고 싶지 않았습니다. 반면에 이미지 빌드 도구 간에는 경쟁이 더 치열해야 한다고 생각합니다. 그래서 흥미롭게 들립니다! 😀

@thaJeztah for environment (12-factor) secrets, 우리는 inspect를 통한 환경 변수의 누출을 방지하기 위해 Twistlock(+Scalock)을 통해 Docker 데몬을 잠그고 있습니다. 이를 보다 적절한 현실로 만들기 위해 검사를 통해 많은 특권 정보를 누출하지 않는 Docker 네이티브 기능이 있다면 좋을 것입니다.

@alexkolson 이 스레드의 핵심은 X, Y, Z를 완화하지 않는 한 "DONT DO THIS"라고 생각합니다. 이것은 분명히 엔지니어링 아이디어입니다. 일반적인 문제에 대한 "해결책"이 항상 있을 것입니다. 즉, 실제 해결 방법을 시작할 수 있도록 하지 말아야 할 사항과 그 이유에 대한 교육이 중요합니다. 악마는 항상 기본값에 있습니다. 따라서 새로운 사용자가 위험에 처한 것을 이해하도록 해야 합니다.

아직 docker에 대한 경험이 많지 않기 때문에 여러분 중 일부가 저를 도울 수 있습니다.
나는 Hashicorps Vault를 사용하여 내 비밀을 가져왔습니다.

기본적으로 토큰을 빌드 인수로 전달하고 토큰을 사용하여 Vault에서 중요한 정보를 가져올 수 있습니다. 이것은 빌드 시 발생하며 Vault가 "봉인되지 않은"(데이터 가져오기를 위해 열림) 상태인 경우에만 성공할 수 있습니다. 빌드 후 사용된 토큰은 취소됩니다.

그러나 나는 여전히 몇 가지 일반적인 문제에 직면해 있다고 생각합니다.

  • 민감한 데이터가 변경되면 새 이미지를 만들어야 합니다.
  • 내 이미지가 도난당하거나 해킹당한 경우 민감한 데이터가 이미지 내에 있습니다.

docker inspect로 사용된 토큰을 찾을 수 있지만 더 이상 사용할 수 없습니다.
나는 가능한 한 비밀 저장소에 대한 접근을 제한하기 위해 빌드 시간에만 해시코프 금고를 봉인 및 봉인 해제하기로 결정했습니다. 또한 런타임에 데이터를 가져올 때 비밀을 저장하는 옵션을 보지 못했습니다.

그래서 내가 얼마나 나쁜 짓을 했습니까 (내가 큰 시간을 망쳐 놓았다고해도 괜찮습니다 ;)) 더 안전하게 만들 수 있는 팁과 트릭이 있는 사람이 있습니까?

@weemen AFAIK 이미지에 비밀을 저장하는 것도 좋은 생각이 아닙니다. 이미지에 자격 증명이 구워져서는 안 됩니다(Vault 토큰 포함). 대신 컨테이너에 대해 Vault의 app-id 인증 백엔드를 사용하여 로드 시 비밀을 가져옵니다. 사용 중인 앱 스택에 따라 어떻게든 컨테이너의 메모리에 저장합니다.

또한 Vault는 AWS를 클라우드 공급자로 사용하는 경우 향후에 유용하게 사용할 aws 인증 백엔드 작업을 진행하고 있습니다.

@jaredm4 이 진술을 명확히

"대신 컨테이너에 대해 Vault의 app-id 인증 백엔드를 사용하여 로드 시 비밀을 가져옵니다. 사용 중인 앱 스택에 따라 어떻게든 컨테이너의 메모리에 저장하십시오."

Vault(또는 Keywhiz 등)에서 비밀을 언제/어디서 검색할지 아직 확실하지 않습니다. 이것은 도커가 실행되기 전에 완료되고 실행 명령에 전달됩니까? 컨테이너 초기화 중 특정 시점에서 이러한 일이 발생합니까(있는 경우 예)? 내 애플리케이션이 필요할 때 이를 검색해야 합니까? 예를 들어, 내 레일 앱에는 Google API 키가 필요합니다. 키가 필요할 때 볼트를 호출하기 위해 레일 내부에 무언가를 작성해야 합니까?

나는 Vault와 같은 것을 사용해야 할 필요성에 대해 분명히 알고 구성 방법에 대해 명확하다고 생각합니다. 서비스를 사용하고 레일이 부팅될 때 yml 파일을 업데이트하고 준비하는 방법에 대해서는 명확하지 않습니다.

여기에서 어떤 지침이라도 주시면 감사하겠습니다. 감사 해요

물론 @mcmatthew , 하지만 여전히 Vault를 마스터하려고 노력하고 있으므로 내 경험이 매우 가볍습니다.

내가 코딩을 시도한 방법은 컨테이너에 전달하는 유일한 정보는 코드가 Vault로 인증할 수 있도록 하는 데 필요한 정보라는 것입니다. app-id 백엔드를 사용하는 경우 app-id 자체와 Vault 주소가 됩니다.

컨테이너 부팅 시 Rails 앱은 아직 비밀이 없음을 인지하고 Vault에서 가져와야 합니다. 제공된 app-id 가 있고 어떻게든 user-id 생성해야 합니다. 이 사용자 ID 생성은 귀하가 결정해야 하지만 해당 문서에서는 "일반적으로 MAC 주소 또는 인스턴스 ID와 같은 시스템 고유의 값 또는 이러한 고유 값에서 해시된 값"이라고 암시합니다.

Rails 앱에 app-id와 user-id가 준비되면 Vault의 API를 사용하여 /login할 수 있습니다. 그런 다음 API를 호출하여 필요한 비밀을 얻을 수 있습니다.

이제 메모리에 저장하는 것에 대한 의미를 명확히 하기 위해 -- 이것은 사용 중인 앱 유형에 따라 다르지만 Rails를 사용하면 Rails가 액세스할 수 있도록 사용자 영역 변수 캐시에 비밀을 저장하는 방법이 있어야 합니다. Vault에서 계속해서 가져오는 대신 모든 요청에서 메모리의 비밀을 가져옵니다(상상할 수 있듯이 느릴 수 있음). Rails의 캐싱에 대한 이 가이드를 살펴보세요. 즉, 섹션 2.0이지만 디스크가 아닌 memory_cache를 사용하고 있는지 확인합니다.

마지막으로, 어떤 방식으로 코딩하든 특별한 Docker 진입점 스크립트 또는 이와 유사한 것이 아니라 Rails에서 수행해야 합니다. Rails는 메모리에서 비밀을 감지해야 하며, 존재하지 않는 경우 이를 가져와야 합니다.

도움이 되기를 바랍니다. 조금 높은 수준이라는 것을 압니다. 하지만 이것이 우리가 해결하기 위해 계획한 방법입니다.

명확하지 않은 것은 무엇을 비밀로 유지해야 하는지, app-id, user-id 또는 둘 다를 유지해야 하는지입니다.

좋아, 대답은 둘 다 https://www.vaultproject.io/docs/auth/app-id.html입니다.
그러나 일반 방화벽 액세스보다 더 안전한 이유는 아직 명확하지 않습니다.
아마도 각 호스트 비밀이 애플리케이션(정책) 비밀과 연결되어야 하기 때문일까요?
즉, 호스트의 비밀에 액세스할 수 있는 경우 해당 비밀 이름을 알고 있으면 특정 애플리케이션에 액세스할 수 있습니까?

이제 2개의 토큰을 어딘가에 저장해야 합니까?

@Vanuan 둘 다 가능한 한 비밀로 유지되어야 합니다.

app-id의 주요 목적은 정책을 통해 Vault 내부의 특정 비밀에 대한 액세스를 제한하는 것입니다. app-id에 액세스할 수 있는 모든 사용자는 해당 app-id의 정책 비밀에 액세스할 수 있습니다. 배포 전략에서 app-id를 제공해야 합니다. 예를 들어 Chef를 사용하는 경우 매개변수 백(또는 OpsWorks의 경우 CustomJSON)에서 설정할 수 있습니다. 그러나 그 자체로는 누구도 Vault에 액세스할 수 없습니다. 따라서 Chef에 대한 액세스 권한을 얻은 사람은 Vault에 액세스할 수 없습니다.

사용자 ID는 Chef에서 제공하지 않으며 특정 시스템에 연결되어야 합니다. 앱이 인스턴스 간에 중복 확장되는 경우 각 인스턴스에는 고유한 사용자 ID가 있어야 합니다. 이 사용자 ID가 어디에서 시작되었는지는 중요하지 않지만(제안을 제공하긴 하지만) 앱 ID를 배포한 동일한 위치(예: Chef)에서 가져오면 안 됩니다. 그들이 말했듯이, 그것은 다른 수단을 통해서만 스크립팅 될 수 있습니다. 인스턴스를 확장하는 데 사용하는 소프트웨어는 무엇이든 인스턴스/도커 컨테이너에 사용자 ID를 제공하고 앱 ID에 사용자 ID를 인증할 수 있습니다. 인스턴스를 동적으로 확장하지 않는 경우 수동으로 수행할 수도 있습니다. 사람이 새 인스턴스를 추가할 때마다 새 사용자 ID를 만들고 앱 ID에 권한을 부여하고 가장 적합한 수단을 통해 인스턴스에 제공합니다.

이것이 방화벽 인스턴스보다 낫습니까? 그것이 달려 있다고 생각하십시오. 방화벽은 Vault(afaik)의 비밀에 대한 액세스를 제한하지 않으며 누군가가 인스턴스에 액세스한 경우 Vault에 쉽게 들어갈 수 있습니다.

이런 식으로 퍼즐의 모든 조각을 얻기가 어렵습니다. 한 단계 더 나아가 app-id는 사용해야 하는 CIDR 블록도 허용합니다. 누군가가 어떻게든 앱 ID와 사용자 ID를 얻은 경우 해당 네트워크에 있지 않고는 여전히 Vault에 액세스할 수 없습니다.

(다시 말하지만, 이것은 내가 할 수 있는 한 최선을 다해 문서화한 후의 내 해석입니다)

@Vanuan @mcmatw 좋은 질문입니다! @jaredm4 이 설명에 정말 감사드립니다. 확실히 도움이 될 것입니다. 이것은 보다 실용적인 구현을 원하는 모든 사람에게 매우 유용합니다!! 앞으로 2주 동안 시간이 있다면 다시 시도하겠습니다!

@thaJeztah :

컨테이너의 모든 프로세스에서 액세스할 수 있으므로 쉽게 "유출"됨

이 주장을 지지할 수 있습니까? 권한이 없는 프로세스는 부모가 아닌 프로세스의 환경 변수에 액세스할 수 없습니다. https://help.ubuntu.com/community/EnvironmentVariables#Process_locality를 참조

컨테이너에 대해 설정된 환경 변수( --env 또는 --env-file ) _are_ 컨테이너의 모든 프로세스에서 액세스할 수 있습니다.

물론 진입점 프로세스의 자식이기 때문입니다. 가능한 한 빨리 비밀 환경 변수를 설정 해제하는 것은 해당 프로세스의 작업입니다. 예를 들어 쉘인 경우에는 사용자가 해야 합니다.

더 중요한 것은 0이 아닌 다른 사용자 ID를 가진 프로세스가 컨테이너 내부 및/또는 외부에서 이러한 환경 변수에 액세스할 수 있는지 여부입니다. 컨테이너 내부에서 사용하는 소프트웨어가 권한을 적절하게 삭제하는 경우에도 마찬가지입니다.

나는 그것이 주제에서 벗어났다는 것을 알고 있지만 다른 사람이 이 문제가 거의 1년 동안 활성화되었다는 것을 알아차렸습니다! 내일은 기념일입니다. 👏

컨테이너 프로세스가 프로세스 메모리에서 env 변수를 읽은 다음 (환경에서) 설정을 해제할 수 있습니까? 이것은 대부분의 런타임 보안 문제를 해결합니까?

@davibe 문제는 컨테이너 또는 해당 프로세스가 다시 시작되면 해당 환경 변수가 복구할 방법 없이 사라진다는 것입니다.

시도했지만 다시 시작한 후에도 env vars가 여전히 있는 것 같습니다.

dade<strong i="6">@choo</strong>:~/work/grocerest(master)$ cat test.js
console.log("FOO value: " + process.env.FOO);
delete(process.env.FOO);
console.log("FOO value after delete: " + process.env.FOO);

dade<strong i="7">@choo</strong>:~/work/grocerest(master)$ docker run --name test -it -e FOO=BAR -v $(pwd):/data/ node node /data/test.js
FOO value: BAR
FOO value after delete: undefined

dade<strong i="8">@choo</strong>:~/work/grocerest(master)$ docker restart test
test

dade<strong i="9">@choo</strong>:~/work/grocerest(master)$ docker logs test
FOO value: BAR
FOO value after delete: undefined
FOO value: BAR
FOO value after delete: undefined

아마도 docker-run이 bash의 자식으로 내 일을 실행하고 있습니까? 안된다고 생각합니다..

@davibe :

unset 'SECRET_ENV_VAR'

이 모든 것의 주요 문제/기능은 Docker에 root 로 로그인하므로 토큰, 볼륨, 변수, 암호화 키 등 컨테이너 내부에 넣은 모든 것을 검사할 수 있다는 것입니다. .. 아무것.

따라서 한 가지 아이디어는 컨테이너에서 sudosu 제거하고 ENTRYPOINT 또는 CMD 앞에 USER 명령을 추가하는 것입니다. 컨테이너를 실행하는 사람은 이제 root 로 실행할 수 있는 기회가 없어야 합니다(내가 틀리지 않은 경우). 따라서 이제 실제로 그에게서 무언가를 숨길 수 있습니다.

또 다른 아이디어(최고의 IMHO)는 사용자 및 그룹의 개념을 Docker 소켓과 컨테이너에 추가하여 GROUP-A가 TAG-B를 사용하는 컨테이너에 액세스할 수 있고 USER-C가 GROUP-에 속한다고 말할 수 있도록 하는 것입니다. 따라서 해당 컨테이너에 액세스할 수 있습니다. 작업당 권한일 수도 있습니다(GROUP-A는 TAG-B의 시작/중지 액세스 권한, GROUP-B는 exec 액세스 권한, GROUP-C는 rm/inspect 액세스 권한 등).

몇 시간 동안 이것을 조사한 결과 공식적으로 권장되는 솔루션이나 빌드 시 비밀에 대한 해결 방법이 없는 것 같고 https://github.com/dockito/vault 와 같은 것이 유일하게 실행 가능한 옵션인 것 같습니다. 빌드 시간 비밀(전체 결과 이미지를 찌그러뜨리거나 처음부터 수동으로 빌드). 불행히도 https://github.com/dockito/vault 는 ssh 키에만 해당되므로 git https 자격 증명 저장소 파일도 호스팅하도록 조정하려고 합니다...

영원할 것 같았던 일(원래 2015년 4분기 릴리스로 예정되어 있다고 들었습니다) 이후, AWS ECS는 마침내 도커 앱에 IAM 역할을 제공 하겠다는 약속을 이행한 것 같습니다. 여기 블로그 게시물 도 있습니다.

이것이 KMS의 장점 과 결합되어 실행 가능한 단기 솔루션인 것 같습니다. 이론적으로 비인증 역할이 요청하지 않아야 하는 것을 방지하고 안전한 스토리지를 KMS에 맡기려면 특정 보안 주체/IAM 역할에 비밀을 바인딩해야 합니다.

아직 시도하지 않았지만 내 짧은 목록에 있습니다 ...

Kubernetes에는 Chef 암호화 데이터백을 많이 떠올리게 하는 몇 가지 비밀 처리 기능 이 있는 것 같습니다.

나는 이것이 이 스레드의 요점인 플랫폼 독립적인 OSS 방식이 아니라는 것을 이해합니다.
하지만 _지금_ 무언가가 필요한 인프라 공간에서 노는 사람들을 위해 이 두 가지 옵션을 던지고 싶었습니다.

나는 이와 관련하여 도움이 될 수 있는 것을 발견했습니다: https://github.com/docker/docker/pull/13587

이것은 docker v1.10.0부터 사용 가능한 것처럼 보이지만 지금까지는 눈치채지 못했습니다. 이 시점에서 내가 기대하고 있는 솔루션은 https://www.vaultproject.io/ 를 사용하여 비밀을 저장 및 검색하고, /secrets 또는 그와 같은 속성에 마운트된 tmpfs 파일 시스템의 컨테이너 내부에 저장하는 것입니다. . 컨테이너에 대한 IAM 역할을 활성화하는 새로운 ECS 기능을 통해 볼트의 AWS EC2 인증을 사용하여 비밀 자체에 대한 인증을 보호할 수 있어야 한다고 생각합니다. (플랫폼 독립적인 경우 앱 ID 인증을 사용하는 경향이 있을 수 있습니다.)

어쨌든, 나에게 잃어버린 조각은 비밀을 되찾았을 때 안전하게 보관할 곳이었습니다. tmpfs 옵션은 나에게 좋은 것 같습니다. 누락된 유일한 점은 ECS가 아직 이 매개변수를 지원하지 않는 것 같아서 오늘 제출한 이유입니다. https://github.com/aws/amazon-ecs-agent/issues/469

모두 함께 꽤 포괄적인 솔루션 IMHO처럼 보입니다.

@CameronGo , 포인터 주셔서 감사합니다. 내가 올바르게 이해한다면 이것은 빌드에서 사용할 수 없습니까? 아니면 사용할 수 있습니까?

@NikolausDemmel 죄송합니다 예, 맞습니다. 이것은 빌드 시간이 아닌 런타임 비밀에 대한 솔루션일 뿐입니다. 우리 환경에서 빌드 시간 비밀은 Git에서 코드를 검색하는 데만 사용됩니다. Jenkins는 이를 처리하고 Git 액세스를 위한 자격 증명을 저장합니다. 동일한 솔루션이 여기 있는 모든 사람의 요구 사항을 해결하는지 확신할 수 없지만 빌드 시간 비밀에 대한 다른 사용 사례는 확실하지 않습니다.

Jenkins는 이를 처리하고 Git 액세스를 위한 자격 증명을 저장합니다.

도커에서 어떻게 작동합니까? 아니면 컨테이너 자체 내부에 git clone 하지 않습니까?

이 문제를 완전히 읽은 후 요구 사항이 매우 다른 "빌드 시간" 및 "런타임" 비밀에 대해 별도의 문제로 분할하는 것이 큰 이점이 될 것이라고 생각합니다.

당신이 나와 같으며 지금 무엇을 해야 할지 결정하려고 여기 왔다면 FWIW에서 더 나은 것이 올 때까지 내가 해결한 솔루션을 설명하겠습니다.

런타임 비밀의 경우 http://kubernetes.io/docs/user-guide/secrets/ 를 사용하기로 결정했습니다

빌드 시간 비밀에 관하여 - 개인 코드를 배포하는 것 외에 다른 빌드 시간 비밀 사용 사례를 생각할 수 없습니다. 이 시점에서 호스트 측에서 "비밀"을 수행하고 생성된 패키지/jar/wheel/repo/etc를 추가하는 것보다 더 나은 솔루션은 보이지 않습니다. 이미지에. 호스트 측에서 패키지를 생성하는 하나의 LOC를 저장하는 것은 일부 의견에서 제안된 대로 ssh 키를 노출하거나 프록시 서버를 실행하는 복잡성을 감수할 가치가 없습니다.

docker run 플래그와 유사하게 docker 빌드에 "-v" 플래그를 추가하면 잘 작동할까요? 일시적으로 호스트와 이미지 간에 디렉토리를 공유하지만 캐시나 생성된 이미지에서 비어 있는 것으로 표시되도록 합니다.

저는 현재 Vault를 사용하여 솔루션을 작업 중입니다.

  1. 빌더 머신에 Vault가 설치되어 있고 토큰이 로컬에 저장되어 있습니다.
  2. 빌드가 시작되면 빌더 머신은 몇 분 동안만 유효한 새 임시 토큰을 요청합니다(빌드에 따라 1h도 허용됨).
  3. 빌드 인수로 토큰을 주입합니다.
  4. Docker 이미지에는 Vault도 설치되어 있으며(또는 빌드 중에 설치 및 제거) 이 토큰을 사용하여 실제 비밀을 가져올 수 있습니다.

동일한 명령 내에서 비밀을 제거하는 것이 중요하므로 도커가 주어진 계층을 캐시할 때 잔여물이 없습니다. (물론 이것은 빌드 시간 비밀에만 적용됩니다)

아직 구축하지 않았지만 작업 중입니다.

@kozikow 의 의견과 다소 관련이 있습니다. "빌드 시간 비밀에 대해 - 개인 코드 배포 외에 다른 빌드 시간 비밀 사용 사례를 생각할 수 없습니다."

구체적으로 빌드 시간 비밀은 아니지만 RUN curl 명령을 통해 이미 빌드된 아티팩트를 다운로드할 수 있도록 하기 위해 Dockerfile에서 빌드 시간 동안 비밀번호를 보호해야 하는 유스 케이스가 필요합니다. 빌드 타임 다운로드는 아티팩트를 가져오기 위해 인증을 위한 사용자 자격 증명이 필요합니다. 따라서 현재 Dockerfile의 환경 변수로 암호를 전달합니다(아직 Dev에 있음). OpenShift를 사용하고 Dockerfile의 환경 변수가 도커 빌드 명령과 마찬가지로 빌드 중에 로그에 출력되므로 빌드가 자동으로 뒤에서 발생합니다. 이렇게 하면 개발자를 포함하여 로그에 액세스할 수 있는 모든 사람이 비밀번호를 볼 수 있습니다. 나는 도커 빌드 중에 사용할 수 있도록 비밀번호를 보내는 방법을 필사적으로 알아 내려고 노력했지만 비밀번호가 로그에 출력되지 않거나 결국 레이어에 없게됩니다.

또한 @wpalmer 가 이 스레드를 런타임과 빌드 시간으로 말한 것을 두 번째로 언급합니다.

(런타임) 비밀 메커니즘이 누구에게나 제시되는 테스트를 정의하는 것이 가치가 있다고 생각합니다. 매우 약한 보안을 옹호하는 많은 사람들이 이 스레드에 있기 때문입니다.

시작으로 저는 다음과 같이 제안합니다.

  • 비밀은 docker inspect에 표시되지 않습니다
  • 프로세스 1이 시작된 후에는 컨테이너에서 액세스할 수 있는 파일(볼륨 탑재 파일 포함) 내에서 비밀을 사용할 수 없습니다.
  • 비밀은 /proc/1/cmdline에서 사용할 수 없습니다.
  • 비밀은 암호화된 형태로 컨테이너에 전송됩니다.

이 중 하나를 위반하는 위에서 제안한 솔루션은 문제가 있습니다.

비밀이 따라야 하는 행동에 대한 정의에 동의할 수 있다면 최소한 목적에 맞지 않는 끝없는 솔루션을 제거할 것입니다.

@gtmtech 좋은 제안 :)

프로세스 1이 시작된 후에는 컨테이너에서 액세스할 수 있는 파일(볼륨 탑재 파일 포함) 내에서 비밀을 사용할 수 없습니다.

여기에 동의하는지 잘 모르겠습니다. 컨테이너(이상적으로는 메모리)에서만 액세스할 수 있어야 한다는 데 동의하지만 응용 프로그램이 "시작"하고 그 아래에서 파일을 제거하지 않는 데 시간이 필요한 몇 가지 경우가 있습니다. 컨테이너 실행 기간 동안 메모리에 있는 무언가(중지 시 제거됨)가 조금 더 나은 접근 방식이라고 생각합니다.

런타임 요구 사항 목록에 다음을 추가합니다.

  • 첫 번째 비밀을 부트스트랩할 때 컨테이너 인증/권한 부여.

예를 들어 Vault는 AppRole Backend에 대한 권한 부여를 제공하지만 컨테이너가 자신을 식별하는 방법에 대해서는 개방적입니다.

Nick Sullivan은 몇 주 전에 Clouflare의 PAL 프로젝트에 대해

애플리케이션의 관점에서 이를 처리하는 세 가지 방법이 있습니다.

  1. 환경 변수에서 비밀을 가져옵니다.
  2. 파일에서 비밀을 가져옵니다.
  3. 다른 시스템에서 비밀을 가져옵니다.

대부분의 애플리케이션이 이 메커니즘을 지원하기 때문에 위의 1번과 2번이 일반적으로 가장 일반적입니다. #3은 "부스러기"를 최소화하므로 더 이상적일 수 있지만 응용 프로그램은 이를 위해 특별히 개발되어야 하며 종종 여전히 비밀을 얻기 위해 자격 증명이 있어야 합니다.

Docker는 다재다능하고 다양한 사용 사례를 지원합니다. 이를 기반으로 1.과 2.는 둘 다 시스템에 "부스러기"를 남긴다는 사실에도 불구하고 응용 프로그램의 관점에서 가장 매력적입니다.

내가 확실히 사용하는 한 가지 일반적인 접근 방식은 진입점 스크립트를 통해 비밀을 주입하는 것입니다(예: AWS에서 credstash 또는 일반 KMS와 같은 도구를 사용하고 IAM 역할과 결합). 이와 관련하여 실제로 진입점 스크립트에서 위의 #3을 수행하고 #1(환경 변수 설정) 또는 #2(파일에 쓰기)를 수행합니다. 이 접근 방식은 동적이며 #1(환경 변수)의 경우 도커 로그 또는 도커 검사에 자격 ​​증명을 노출하지 않습니다.

진입점 접근 방식의 좋은 점은 애플리케이션에서 비밀 관리 문제를 분리한다는 것입니다.

이것은 Docker가 자체 진입점 스크립트를 사용할 필요가 없도록 기능을 추가할 수 있는 영역입니다. Docker는 플러그인을 좋아하고 기본적으로 수동 진입점 스크립트의 기능을 수행하고 컨테이너에 비밀을 주입하는 "비밀" 공급자 플러그인을 지원할 수 있는 컨테이너 수명 주기에 대한 후크를 제공할 수 있습니다(내부 환경 변수 또는 파일을 통해). 따라서 Hashicorp Vault 비밀 공급자, AWS KMS 비밀 공급자 등을 가질 수 있습니다. Docker는 RSA 암호화(디지털 인증서를 통해)를 기반으로 하는 자체 공급자를 가질 수 있습니다. 이 전체 개념은 컨테이너 파일 시스템에 비밀을 제시하는 Kubernetes의 비밀 개념과 느슨하게 유사합니다.

물론 오늘날 당신이 직면하고 있는 문제인 비밀 제공자에 대한 액세스 권한을 부여하는 방법의 복잡성이 있습니다. Hashicorp를 사용하면 인증을 위해 일회성/시간 제한 토큰을 발행하고 전달할 수 있으며, AWS에서는 IAM 역할이며, 앞서 언급한 Docker RSA 암호화 접근 방식을 사용하면 Docker 엔진 공개 인증서를 사용하여 암호화된 비밀을 전달할 수 있습니다.

이 스레드는 훌륭합니다. 커뮤니티와 모든 직종의 사람들이 자신의 경험, 생각 및 솔루션을 공유할 수 있는 이와 같은 스레드가 더 많이 표시되기를 바랍니다.

"비밀번호 0" 문제는 까다로운 문제입니다. 빌드 타임 또는 런타임? 둘 다 장단점이 있으며 명백한 보안 조치와 결함(및 해킹 및 해결 방법!)이 있습니다.

즉, 패스/키 관리가 애플리케이션 및/또는 서비스로 이어지는 방식에 대해 많이 생각했습니다.

앞으로 몇 개월 동안 작업할 내용은 키/값 쌍을 통해 공유 글로벌 구성 지원 서비스를 구축하고 Consul에서 배포하고 환경 변수로 사용할 수 있도록 하는 것입니다(또는 환경 변수 사용이 지원되지 않는 경우 주입). 이것은 안전하지 않은 값만 지원합니다. 보안을 위해 Vault로 이동하여 데이터베이스 또는 기타 종속성과 같은 지원 서비스처럼 취급합니다.

코드, 구성 및 비밀은 지원 서비스를 통해 제공됩니다. 이 경우 Stash, Consul 및 Vault를 사용합니다. 종속성이 있는 한 필요에 따라 구성 및 비밀을 가져오는 기능도 있습니다.

나는 이것을 어디에서도 확실한 해결책으로 본 적이 없으므로 여기에 대해 게시하고 있습니다. 그러나 이 스레드의 목적으로 돌아가기 위해 Docker/비밀 문제를 해결하기 위해 실험할 한 가지 접근 방식입니다. 우리는 실행되는 프레임워크와 플랫폼에 의존하기 보다는 기본적으로 이를 지원하는 애플리케이션을 구축할 것입니다.

빌드 시간 비밀과 관련하여 Rocker의 MOUNT 지시문 은 빌드 시간에만 존재하는 임시 디렉토리 및 파일을 만드는 데 유용한 것으로 입증되었습니다. 템플릿 기능 중 일부는 이러한 상황에서도 도움이 될 수 있지만 아직 완전히 사용하지는 않았습니다.

이 기능이 Docker 코어에서 빌더 플러그인으로 구현되는 것을 보고 싶습니다(또한 Rockerfiles의 다른 유용한 기능 중 일부)!

현재 OP에 있는 4개의 제안은 모두 비밀 저장소에 관한 것입니다 🙁

도커는 _docker 인스턴스_에 비밀/비밀번호를 쉽게 전달해야 하지만 이러한 비밀을 저장/관리하는 것은 도커의 범위를 벗어납니다.

_비밀을 전달할 때_ 나는 이것이 일반적으로 기록된다는 점을 제외하고 실행 매개변수가 거의 완벽하다고 말하고 싶습니다. 그래서 저는 이것을 일반 텍스트

_비밀을 관리하는 방법_에 관해서는 홈브류 bash 스크립트에서 Kubernetes 와 같은 소프트웨어에 의한 통합에 이르기까지 사용자가 원하는 모든 것을 말하고 싶습니다.

앞서 언급한 @agilgur5 와 같이 로커 마운트 와 같은 MOUNT를 구현하는 데 문제가 있습니까? 이 논쟁이 너무 오래 지속되어 팀이 이 정말 쉬운 사용 사례를 충족시키기 위해 docker build 명령을 효과적으로 분기해야 했다는 사실이 믿기지 않습니다. 혼합에 다른 HTTP 서버가 필요합니까? 키스.

이 서브제트 주변에서 너무 많은 시간을 보냈습니다 ...

현재로서는 빌드 단계에서 비밀을 관리하는 가장 좋은 방법은 두 단계 내에서 빌드하는 것이므로 두 개의 도커 파일이 있습니다. 여기 좋은 예가 있습니다.

[Habitus](http://www.habitus.io/) 가 또 다른 옵션인 것 같지만 제 경우에는 주로 CI 서버와 사용자 컴퓨터에서 빌드 프로세스를 원하기 때문에 다른 도구를 추가하고 싶지 않습니다. 단순 / 동일 .

그리고 docker-in-docker (dind) 방식은 어떻습니까?

다음은 위에서 말한 것처럼 dind로 빌드하는 두 단계의 예입니다. https://github.com/BenoitNorrin/docker-build-with-secrets

자유롭게 댓글을...

흥미로운. OpenShift가 빌드하는 방식을 생각나게 합니다.

명령줄에서 암호를 전달하는 것 같습니다. 그 방법이 있습니까?

여기에 빌드 시간 비밀에 대한 진행 중인 PR이 있습니다. https://github.com/docker/docker/pull/28079 (서비스에 대한 런타임 비밀은 docker 1.13에 있습니다. https://github.com/docker/docker/pull/27794 참조)

@thaJeztah :
#28079에 대해, 지난 2년 동안 이 주제에 대한 많은 홍보가 실패하는 것을 보았을 때 약간 비관적이었습니다 ...
Swarm을 종속성으로 사용하고 싶지 않습니다. 일부 고객은 다른 클러스터 오케스트레이터를 사용합니다.

@cassiussa :
무슨 말인지 이해가 안가요?
1/ 비밀번호가 최종 이미지가 아닌 "컨테이너 빌더"에 전달되었습니다. 이 빌더는 도커 빌드를 수행하고 Dockerfile.realease를 기반으로 이미지를 생성합니다. 이 최종 이미지의 기록에는 비밀이 저장되어 있지 않습니다.
2/ 명령줄에 암호를 전달하지 않으려면 docker-compose( example )를 자유롭게 사용하세요.

@BenoitNorrin 앞으로 non-swarm으로 확장될 수 있다고 생각하지만 @diogomonica 는 그것에 대해 더 많이 알고 있을 것입니다.

그런 소리:

이것은 백업 저장소가 Swarm이고 Linux 전용이므로 현재 Swarm 모드 전용입니다. 이것은 Windows 지원, 다양한 백업 저장소 등과 같은 잠재적인 개선 사항과 함께 Docker에서 미래의 비밀 지원을 위한 기반입니다.

로커와 같은 방식으로 구현된다면 좋을텐데,
간단하고 '기업'일 필요는 없습니다.

2016년 11월 29일 화요일, 15:53 ​​Michael Warkentin, 알림 @github.com
썼다:

그런 소리:

백업 저장소가 Swarm이고 다음과 같이 현재 Swarm 모드에만 해당됩니다.
Linux에만 해당됩니다. 이것은 미래의 비밀 지원을 위한 기반입니다.
Windows 지원과 같은 잠재적인 개선 사항이 있는 Docker, 다양한
백업 스토어 등


당신이 댓글을 달았기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/docker/docker/issues/13490#issuecomment-263608915 ,
또는 스레드 음소거
https://github.com/notifications/unsubscribe-auth/AAZk5vlLwsBHHTTbUS_vvx-qTuwnkp6Oks5rDEpjgaJpZM4Eq021
.

해결책은 docker-compose 파일에서 전달된 정보의 일부를 암호화하는 것입니다.

예를 들어 docker inspect 를 실행하면 암호화된 정보가 _encrypted_로 표시/표시되어야 합니다. 그런 다음 docker inspect --encryption-key some_key_file 는 암호화되지 않은 모든 암호화된 정보를 표시합니다.

반면에 컨테이너 내부에서 앱은 사용을 위해 이 암호화된 정보에 액세스하고 암호를 해독하는 다른 메커니즘을 구현할 수 있어야 합니다.

저는 암호화가 _핵심_이라고 생각합니다. :)

목적은 내 (정말, 정말, 정말 일반적인) 사용 사례를 빌드하는 것입니다.
인증이 필요한 git 서버의 소프트웨어 프로젝트
프로젝트 및 해당 종속성. Rocker는 마운트를 허용하여 못을 박았습니다.
빌드 중 파일 또는 디렉토리(이 경우 SSH 에이전트 소켓)

2017년 1월 3일 화요일 04:14 Hisa, [email protected] 작성:

솔루션은 전달된 정보의 일부를 암호화하는 것이라고 생각합니다.
도커 작성 파일에서.

예를 들어 docker inspect를 실행하면 암호화된 정보가 다음과 같아야 합니다.
암호화된 것으로 표시/표시됩니다. 그런 다음 docker inspect --encryption-key
some_key_file은 암호화되지 않은 모든 암호화된 정보를 표시합니다.

반면에 컨테이너 내부 앱은 다음을 구현할 수 있어야 합니다.
사용을 위해 이 암호화된 정보에 액세스하고 암호를 해독하는 다른 메커니즘.

암호화 가 핵심인 것 같아요 :)


당신이 댓글을 달았기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/docker/docker/issues/13490#issuecomment-270049742 ,
또는 스레드 음소거
https://github.com/notifications/unsubscribe-auth/AAZk5qEphZo5SR9vOWVL5dck50EPadpVks5rOcsUgaJpZM4Eq021
.

언급된 것을 보지 못했기 때문에 AWS ECS에서 비밀을 처리하는 방법에 대한 또 다른 좋은 기사가 있습니다. https://aws.amazon.com/blogs/security/how-to-manage-secrets-for-amazon-ec2-container- amazon-s3-and-docker를 사용하여 서비스 기반 애플리케이션/

Docker 1.13에는 새로운 "docker secret" 명령이 있습니다. 이 문제는 해당 기능에 대한 문서가 여기에 언급된 사용 사례에 적합할 때 닫을 수 있어야 합니다.

docker secret 명령은 현재 Docker Swarm(즉, docker 서비스)에만 적용되는 것으로 보이므로 현재 일반 Docker 컨테이너에는 실행 가능하지 않습니다.

또한 docker secret 는 런타임 비밀만 관리하고 빌드 시간 비밀은 관리하지 않습니다.

우와. 제품 관리 팀의 누구도 고려하지 않은 것과 같습니다.
인증되지 않은 오픈 소스 소프트웨어가 아닌 모든 것을 얻는 사용 사례
docker 컨테이너 또는 golang 이외의 모든 언어로 구축
종속성은 복사하여 Git 리포지토리에 '버전 관리'하여 붙여넣습니다.

사람들이 어떻게 그렇게 믿을 수 없을 정도로 둔감했는지 이해할 수 없습니다. 오직
내가 생각할 수있는 설명은 제품 관리 팀이
실무자이며 제품을 사용한 적이 없습니다. 나는 종종 이것을 본다.
특성은 조직이 기반으로 고용할 때 나타납니다.
지라/애자일 스킬.

나는 2019년까지 또는 누군가가 그 때 의미를 볼 때까지 로커를 계속 사용할 것입니다.

2017년 1월 22일 일요일 23:47 Shane StClair, [email protected] 다음과 같이 썼습니다.

또한 도커 비밀은 빌드 시간 비밀이 아닌 런타임 비밀만 관리합니다.


당신이 댓글을 달았기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/docker/docker/issues/13490#issuecomment-274370450 ,
또는 스레드 음소거
https://github.com/notifications/unsubscribe-auth/AAZk5vJVJe4OeypWd1Cwqmh8Gzyn8P-mks5rU-qqgaJpZM4Eq021
.

나는 그 마지막 의견을 되돌려 놓을 것입니다. 그냥 좌절
단순한 엣지 케이스는 종종 무언가를 움켜잡을 기회처럼 보입니다.
영사처럼 만들거나 단순히
빌드 시간 마운트와 같은 간단한 것을 구현하십시오.

2017년 1월 23일 월요일, 09:31 Bryan Hunt,

우와. 제품 관리 팀의 누구도 고려하지 않은 것과 같습니다.
인증되지 않은 오픈 소스 소프트웨어가 아닌 모든 것을 얻는 사용 사례
docker 컨테이너 또는 golang 이외의 모든 언어로 구축
종속성은 복사하여 Git 리포지토리에 '버전 관리'하여 붙여넣습니다.

사람들이 어떻게 그렇게 믿을 수 없을 정도로 둔감했는지 이해할 수 없습니다. 오직
내가 생각할 수있는 설명은 제품 관리 팀이
실무자이며 제품을 사용한 적이 없습니다. 나는 종종 이것을 본다.
특성은 조직이 기반으로 고용할 때 나타납니다.
지라/애자일 스킬.

나는 2019년까지 또는 누군가가 의미가 있다고 생각할 때까지 로커를 계속 사용할 것입니다.
그 다음에.

2017년 1월 22일 일요일 23:47 Shane StClair, 알림 @github.com
썼다:

또한 도커 비밀은 빌드 시간 비밀이 아닌 런타임 비밀만 관리합니다.


당신이 댓글을 달았기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/docker/docker/issues/13490#issuecomment-274370450 ,
또는 스레드 음소거
https://github.com/notifications/unsubscribe-auth/AAZk5vJVJe4OeypWd1Cwqmh8Gzyn8P-mks5rU-qqgaJpZM4Eq021
.

@binarytemple 모든 사람들은 지금 모든 기능을 원합니다. 물건이 준비되지 않았다면 그것은 준비되지 않은 것입니다. 새로운 기능의 범위를 제한하는 것은 제한된 범위에도 항상 개선의 여지가 있기 때문에 확실히 나쁜 것은 아닙니다.

누군가가 기능을 얻는 것에 대해 정말로 열성적이라면 유지 관리자와 그 작업에 기여할 수 있는 방법에 대해 이야기해야 합니다.

secret 명령이 스웜 사용자에게만 도움이 된다는 점에서 @mixja 와 같은 생각을 했습니다. (영구 볼륨을 연결할 때와 마찬가지로) 더 일반적인 솔루션이 아닙니다. 비밀을 관리하는 방법(정보가 무엇인지, 비밀에 액세스할 수 있는 사람)은 시스템에 따라 매우 다르며 "플랫폼"을 만들기 위해 함께 짜맞춰진 유료 및/또는 OSS 비트에 따라 다릅니다. Docker 회사가 플랫폼을 제공하기 시작하면서 Hashicorp가 Vault를 Atlas에 통합하는 것처럼 첫 번째 구현이 Swarm 기반이라는 사실이 놀랍지 않습니다.

실제로 비밀이 전달되는 방식은 docker run 공간을 벗어납니다. AWS는 권한과 SDK를 부여/거부하는 역할 및 정책으로 이러한 작업을 수행합니다. Chef는 암호화된 데이터백과 암호화 "부트스트래핑"을 사용하여 인증합니다. K8S에는 1.13에서 방금 출시된 자체 버전 이 있습니다. 나는 mesos가 비슷한 구현을 제때 추가할 것이라고 확신합니다.

이러한 구현은 2가지 진영으로 나뉩니다.
1) "플랫폼"이 제공하는 볼륨 마운트를 통해 비밀을 전달하거나 (chef/docker secret/k8s
2) 부팅 시 정보를 얻기 위해 외부 서비스와 통신하기 위해 자격 증명을 전달합니다(iam/credstash/etc).

나는 두 번째 옵션의 라인을 따라 더 많은 것을 볼 수 있기를 바랐다고 생각합니다. 첫 번째 옵션에서는 우려 사항을 충분히 분리하지 않았다고 생각합니다(런칭을 하는 것도 모든 키에 액세스할 수 있음). 하지만 이것은 선호 사항이며 시스템 구축의 다른 모든 것과 마찬가지로 모두가 다르게 하는 것을 좋아합니다. .

이 첫 번째 단계가 docker에 의해 수행되었으며 docker run 대한 보다 일반적인 메커니즘이 (캠프 #2를 지원하기 위해) 나오기를 희망합니다. 이는 슬프게도 이 스레드가 초기 임무를 완료했으며 아직 종료하면 안 됩니다.

처럼!
정말 간단하면서도 매우 효과적인 디자인

@bacoboy , @mixja - 단일 노드 스웜 및 단일 컨테이너 서비스는 그렇게 나쁘지 않습니다
도커 떼 초기화, 도커 서비스 생성 복제본=1

나에게 docker swarm이 지금부터 컨테이너/서비스를 실행하기 위한 기본값이 될 것이라는 것이 논리적입니다.

이 새로운 떼 기반 제안이 런타임 비밀 에만 영향을 미친다고 생각하는 것이 맞습니까? 실행 중인 컨테이너에 비밀을 가져오는 방법이 이미 너무 많기 때문에 런타임 비밀을 특별히 처리할 필요가 없다고 생각합니다.

빌드 시간 비밀은 중요하며 내가 아는 한 이 제안에서는 이를 다루지 않습니다.

빌드 시간 비밀을 주입하기 위해 이제 docker build --squash 를 사용하여 다음을 안전하게 수행할 수 있습니다.

COPY ssh_private_key_rsa /root/.ssh/id_rsa
RUN git pull ...
RUN rm -rf /root/.ssh/id_rsa

--squash 플래그는 전체 Dockerfile에 대해 단일 계층을 생성합니다. 비밀 추적은 없습니다.

--squash 는 docker-1.13에서 실험용 플래그로 사용할 수 있습니다.

@hmalphettes 이는 빌드 간에 하위 계층을 공유하는 이점을 놓치게 됨을 의미합니다.

이것은 확실히 스쿼시의 의도가 아닙니다. 이드는 여전히 이런 비밀을 추가하는 것을 매우 조심스럽게 여긴다.

@zoidbergwill 하위 레이어는 여전히 공유됩니다.

@cpuguy83님 말씀에 100% 동의합니다. 비밀을 숨기기 위해 빌드 시간 플래그에 의존하는 것은 꽤 위험합니다. 빌드 시간에 대한 제안 PR이 있었습니다(https://github.com/docker/docker/pull/30637). 더 많은 피드백을 얻기 위해 rebase 작업을 할 것입니다.

@wpalmer 자동화된 이미지 빌드가 있는 경우 도구는 빌드 시간 비밀을 얻는 방법을 알고 있어야 합니다.

예를 들어, 빌드 시간 비밀을 이미지로 구운 Ansible 암호화 볼트에 보관하고 해당 이미지에서 실행되는 컨테이너에 볼트 암호를 유지하는 런타임 비밀에 대한 액세스 권한을 부여할 수 있습니다.

어떻게 생각하십니까?

왜 빌드 타임 비밀과 런타임 비밀을 혼동하는가? docker(또는 kubernetes와 같은 관련 도구)가 런타임 비밀을 제공하는 좋은 방법이 이미 많이 있습니다. 정말 누락된 유일한 것은 빌드 시간 비밀입니다. 이러한 비밀은 런타임 중에는 사용되지 않고 설치 중에 사용되며 예를 들어 내부 리포지토리가 될 수 있습니다. 이 주제와 관련 주제에서 본 유일한 작동 방식은 빌드 시간 동안 컨테이너에 http 서버를 노출하는 것입니다. http 서버 접근 방식은 실제로 이러한 비밀에 접근하기 위해 복잡하게 만듭니다.

+1 빌드 시간 비밀 != 런타임 비밀

바울이 지적했듯이. 내부 저장소를 굽는 것은 바람직하지 않습니다.
이미지에 자격 증명을 입력합니다.

이게 왜 이렇게 이해하기 힘든 걸까요?

2017년 2월 16일 목요일, 14:42 Paul van der Linden, [email protected]
썼다:

왜 빌드 타임 비밀과 런타임 비밀을 혼동하는가? 거기
docker(또는 kubernetes와 같은 관련 도구)에 이미 많은 좋은 방법이 있습니다.
런타임 비밀을 제공합니다. 정말 누락된 유일한 것은 빌드 시간입니다.
비밀. 이러한 비밀은 런타임 중에는 사용되지 않으며, 실행 중에 사용됩니다.
예를 들어 내부 리포지토리가 될 수 있습니다. 유일한
이 주제 및 관련 주제에서 본 작업 방식(또한
이에 대해) 빌드 시간 동안 컨테이너에 http 서버를 노출하고 있습니다.
http 서버 접근 방식은 실제로 액세스하기가 복잡합니다.
그 비밀들.


당신이 언급되었기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/docker/docker/issues/13490#issuecomment-280348116 ,
또는 스레드 음소거
https://github.com/notifications/unsubscribe-auth/AAZk5h0Z2OGwApVnLNEFWKRdOfGxLOmRks5rdGBagaJpZM4Eq021
.

@pvanderlinden 2단계 건물로도 그렇게 할 수 있습니다.
예: https://github.com/BenoitNorrin/docker-build-with-secrets

@timka 가 언급했듯이 보안 위험이 있으므로 자격 증명을 이미지에 굽는 것은 바람직하지 않습니다. 다음은 빌드 시간 비밀에 대한 제안입니다. https://github.com/docker/docker/pull/30637

@BenoitNorrin 내 (및 다른 사람들) 사용 사례에서 그것이 어떻게
설치해야 할 패키지는 docker 빌드 프로세스를 시작할 때 이미 빌드되어 있습니다. 그러나 도커 빌드는 이러한 패키지를 설치해야 하며 내부 아나콘다 저장소 및/또는 pypi 서버(python)에 액세스해야 합니다. 위치와 비밀번호는 물론 비공개입니다.
#30637이 또 다른 시도인 것 같습니다. 이것이 도커에서 마무리되기를 바랍니다!

@timka 메시지의 전반부는 빌드 시간 비밀을 언급하는 것 같지만 후반부는 명시적으로 런타임 비밀에 대해 이야기합니다. 런타임 비밀은 간단합니다. 빌드 시간 비밀에 대한 나의 현재 "해결책"은 런타임 비밀을 사용하여 개인 데이터를 가져오는 컨테이너를 완전히 별도의 단계로 미리 실행하는 것입니다. 그런 다음 일반 docker build 명령을 실행하기 전에 다른 단계에서 이를 트리에 병합합니다.

빌드 시 비밀이 표준 기능인 경우 대안은 Dockerfile 내에서 이러한 단계를 실행하는 것입니다.

내 도구는 이러한 단계를 자동으로 실행하는 방법을 알고 있지만, 이것을 직접 구워야 했습니다. 이는 그러한 일반적인 욕망에 대해 다소 터무니 없는 일입니다.

참고로 저는 빌드 타임 비밀 문제를 해결하기 위해 https://github.com/abourget/secrets-bridge 를 작성했습니다.

빌드 프로세스 중에 인수로 전달할 수 있는 폐기 구성을 생성하고 호스트에 연결하여 비밀을 가져와 사용하고 호스트 브리지를 종료할 수 있습니다. build-args가 어딘가에 저장되어 있어도 서버가 종료되는 순간 쓸모가 없게 됩니다.

서버는 TLS 웹 소켓 통신을 통해 터널링된 SSH 에이전트 전달을 지원합니다. Windows에서도 작동합니다!

Alexandre, 당신이 한 일은 매우 창의적이고 기술이 뛰어납니다. 그냥
이 모든 단계를 건너뛰어야 한다는 사실이 저를 슬프게 합니다.
'도커 빌드'가 '마운트'를 지원하는 경우 수행할 수 있는 것과 동일하게 달성
모든 것이 복사된다는 맹목적인 주장보다는 명령
컨테이너.

저는 '도커 빌드'를 포기하고 대신 로커를 사용하거나
내 자신의 창조물이라면 무엇인가.

2017년 7월 13일 목요일 16:23 Alexandre Bourget, [email protected]
썼다:

참고로 저는 https://github.com/abourget/secrets-bridge 를 작성하여
빌드 시간 비밀 문제.

인수로 전달할 수 있는 폐기 구성을 생성합니다.
빌드 프로세스 중에 호스트에 연결하고 가져옵니다.
비밀을 사용하고 호스트 브리지를 죽일 수 있습니다. 경우에도
build-args는 어딘가에 저장되고 서버가
살해당한다.

서버는 TLS를 통해 터널링된 SSH 에이전트 전달을 지원합니다.
웹 소켓 통신. Windows에서도 작동합니다!


당신이 언급되었기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/moby/moby/issues/13490#issuecomment-315111388 또는 음소거
스레드
https://github.com/notifications/unsubscribe-auth/AAZk5hZqTAgPBjS9cFP_IsYNa9wv-yoAks5sNjaBgaJpZM4Eq021
.

최신 비밀 제안은 다음과 같습니다. https://github.com/moby/moby/issues/33343

마지막 Docker CE 릴리스에 포함된 새로운 "다단계 빌드" 기능이 우리 문제의 큰 부분을 해결한다고 생각합니다.

https://docs.docker.com/engine/userguide/eng-image/multistage-build/

Dockerfile 에서 명령을 실행하기 위해 생성된 컨테이너는 요리된 /dev 와 함께 제공되며 여기서 수행된 변경 사항은 레이어에 기록되어서는 안 됩니다. 도커가 해당 마운트 지점을 통해 사용자 비밀을 전달할 수 있습니까? 비슷한 방식으로 /dev/init ?

인수가 있는 다단계 빌드는 이미지에서 누출되지 않지만 여전히 실행 중인 시스템의 프로세스 목록의 일부로 비밀을 노출하므로 실제로 해결되지 않기 때문에 이것은 여전히 ​​매우 중요합니다.

2017년 8월입니다. 한편 원호의 "비밀 처리에 대한 이전 제안"은 2014년 문제에 대한 링크입니다.

빌드 시간 비밀에 대한 좋은 솔루션은 아직 없습니다. --build-time-secret 플래그를 제공한 PR은 설명 없이 닫혔습니다. "그래서 무엇이 필요합니까?" 섹션이 구현됩니다.

그 동안에

비즈니스 고객에 초점을 맞춘 새로 취임한 CEO Steve Singh
영업, 마케팅 팀을 구성하는 데 도움이 되는 7,500만 달러의 최근 라운드


UPD.: @cpuguy83이 아래에서 올바르게 지적했듯이 제안의 전체 요약은 #33343에 있습니다.

나는 그것이 내장되어 있지 않다는 것을 알고 있지만 secrets-bridge 현재로서는 꽤 잘 작동합니다.

@dmitriid 이 기능이 누락되었다는 불만을 이해합니다. 그러나 이것은 오픈 소스 커뮤니티(또는 모든 커뮤니티)를 다루는 방법이 아닙니다.

나는 위의 제안에 대한 링크를 게시했고 내 자신을 제외하고 정확히 0개의 댓글을 보았습니다.

최신 비밀 제안은 다음과 같습니다. #33343

@cpuguy83 굉장해 ! 이 토론의 마지막 3분의 1(및 기타 몇 가지)은 읽을 내용이 많기 때문에(동시에 솔루션을 찾는 동안) 건너뛰었습니다. 그래서 귀하의 의견을 정말 놓쳤습니다. 죄송합니다.

이 스레드는 2015년에 시작되었습니다.

2017년입니다.

해킹과 끔찍하지 않은 빌드 타임 비밀에 대한 솔루션이 아직 없는 이유는 무엇입니까? 많은 사람들에게 분명히 큰 문제지만 실제로 좋은 해결책은 아직 없습니다!

@mshape

해킹과 끔찍하지 않은 빌드 타임 비밀에 대한 솔루션이 아직 없는 이유는 무엇입니까?

올바르게 풀기 어려운 문제이고 말 그대로 수백만 명의 사람들이 사용하게 될 문제이기 때문입니다.

귀하의 바로 위에 있는 내 의견을 참조하십시오.

나는 위의 제안에 대한 링크를 게시했고 내 자신을 제외하고 정확히 0개의 댓글을 보았습니다.
최신 비밀 제안은 다음과 같습니다. #33343

구현된 것을 보고 싶다면 구현되지 않은 것에 대해 불평하는 것 이상을 해야 합니다. 제안에 댓글을 달아주세요!

해결하기 너무 쉽습니다. 그것은 단지 무언가가 필요합니다, 그렇지 않은 것은 무엇이든
이미지로 구워졌습니다. 그리고 실제로는 매우 쉽게 해결할 수 있습니다. 사용을 중지하세요.
'docker build'를 선택하고 python API, 로커 또는 기타 모든 것을 사용합니다.

2017년 8월 23일 수요일 오후 9시 42분, Brian Goff 알림 @github.com
썼다:

@mshappe https://github.com/mshapp

해킹이 아닌 빌드 타임 비밀에 대한 솔루션이 없는 이유는 무엇입니까?
끔찍하지만 아직?

제대로 풀고 해결하기 어려운 문제이기 때문에
말 그대로 수백만 명이 사용할 것입니다.

귀하의 바로 위에 있는 내 의견을 참조하십시오.

나는 위의 제안에 대한 링크를 게시했고 정확히 0개의 댓글을 보았습니다.
내 자신을 제외하고.
최신 비밀 제안은 다음과 같습니다. #33343
https://github.com/moby/moby/issues/33343

구현된 것을 보고 싶다면 그 이상을 수행해야 합니다.
무언가가 구현되지 않았다고 불평합니다. 제안에 댓글을 달아주세요!


당신이 언급되었기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/moby/moby/issues/13490#issuecomment-324441280 또는 음소거
스레드
https://github.com/notifications/unsubscribe-auth/AAZk5oEpcipmfCji1mXz6MOVt0p6-OA6ks5sbIC0gaJpZM4Eq021
.

@binarytemple 나는 Rocker를 대안으로 보기 시작했습니다. 사실... 하지만 이 이상한 멘탈 블록 때문에 도커는 빌드 타임 비밀에 대해 알고 있는 것 같습니다.

이상해 나는 사람들과 이야기하고 그들은 모든 종류의 어리석은 해킹을 하고 있습니다.
HTTP 서비스를 사용하는 것처럼 - 모든 것을 버리십시오(모니터링/세분화
권한/단순성) POSIX/SELinux 콤보가 제공합니다. 난 그냥하지 않습니다
이해하다. 거절은 나에게 비논리적으로 보인다.

2017년 8월 23일 수요일, 23:03 Michael Scott Shappe [email protected]
썼다:

@binarytemple https://github.com/binarytemple 내가 보기 시작한
로커를 대안으로, 사실...하지만 이 이상한 점 때문에
mental block docker에는 빌드 시간 비밀이 있는 것 같습니다.


당신이 언급되었기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/moby/moby/issues/13490#issuecomment-324461257 또는 음소거
스레드
https://github.com/notifications/unsubscribe-auth/AAZk5ppZYsOhdfvgotCUk5l41Truo_EEks5sbJOLgaJpZM4Eq021
.

다단계 도커 빌드는 이러한 문제를 많이 해결합니다.

가장 간단한 형태로 비밀을 빌드 인수로 주입할 수 있으며, 인수가 필요하다고 명시적으로 말하는 이미지 기록의 일부일 뿐입니다. neclimdul이 지적했듯이 빌드 중에 프로세스 목록에서 비밀을 사용할 수 있습니다. IMO는 큰 문제가 아니지만 다른 접근 방식을 취했습니다.

빌드 서버는 볼륨으로 마운트된 일부 비밀로 실행되므로 f.ex에 CI가 복사됩니다. /mnt/secrets/.npmrc를 현재 작업 디렉토리로 이동합니다. 그런 다음 아래와 유사한 Dockerfile을 사용합니다.

FROM node:latest
WORKDIR /usr/src/app
COPY .npmrc .
RUN echo '{ "dependencies": [ "lodash" ] }' > package.json
RUN npm install
RUN ls -lah

FROM alpine:latest
WORKDIR /usr/src/app
COPY --from=0 /usr/src/app/node_modules ./node_modules
RUN ls -lah
CMD ["ls", "./node_modules"]

결과 이미지에는 설치된 종속성이 있지만 .npmrc 또는 그 내용의 흔적은 없습니다.

다단계 빌드를 사용하면 빌드 프로세스에 빌드 시간 비밀을 노출하는 방법을 완전히 제어할 수 있습니다. 볼륨(Kubernetes의 Secrets 저장소에서 마운트)을 통해 Vault와 같은 외부 저장소에서 비밀을 가져와 저장소, Travis 비밀 등에서 gpg 암호화하도록 할 수 있습니다.

이 사용 사례에 대해 다단계 빌드를 사용할 때 이 데이터가 후속 빌드의 빌드 캐시에 사용될 수 있도록 해당 이미지가 삭제될 때까지 비밀 데이터가 로컬 데몬의 태그가 지정되지 않은 이미지 내부에 남아 있다는 것을 인지해야 합니다. 그러나 최종 태그 이미지를 푸시할 때 레지스트리에 푸시되지 않습니다.

@androa 그 솔루션이 마음에

이것은 끔찍합니다. 자칭 "세계 최고의 소프트웨어 컨테이너 플랫폼"은 지난 3년 동안 컨테이너에 빌드 시간 비밀을 안전하게 전달하는 데 방해가 되지 않습니다.

"우리가 더 잘 압니다" 및 "실수를 허용하는 소프트웨어를 만들지 마십시오" 접근 방식과 설계 단계에서 불행한 누락으로 가장 잘 설명될 수 있는 것은 DevOps 소프트웨어의 필수 기능 중 하나에 대한 지원 및 가시적인 진전이 없습니다. 병합 준비가 된 개선 사항이 제안되고 때로는 개발된 모든 커뮤니티는 누군가가 이를 남용할까봐 폐쇄됩니다. 이 클러스터... 실패의 결과로 도커 컨테이너의 빌드 단계에만 필요한 개인 키를 전달하는 모든 방법은 해당 비밀을 빌드 히스토리에 저장하거나 빌드 히스토리가 절대 떠나지 않기를 바라며 프로세스 목록에 표시되어야 합니다. 신뢰할 수 있는 기계 또는 프로세스 목록을 볼 수 없는 사람. 둘 다 가장 허용적인 보안 감사에도 실패합니다.

이 문제는 그 당시 문제에 대해 알려진 내용과 이에 대해 수행할 작업을 요약하기 위해 2년 넘게 열려 있습니다. 아직 해결책이 없습니다. 그렇다고 해서 가장 복잡한 비밀 관리 체계를 즉시 지원하는 포괄적인 솔루션을 의미하는 것은 아닙니다. 솔루션이 전혀 없고 호스트 환경 변수도 없고 빌드 컨텍스트 외부의 파일 경로에서 비밀을 로드하지도 않습니다. 가장 엄격한 조건에서도 안전하다고 간주될 수 있는 것은 없습니다.

@OJezu 문제에 여러 번 언급했듯이 기본적으로 0개의 의견이 있는 공개 제안이 있습니다.
추진된 비밀을 보고 싶다면 시간을 내어 제안에 대해 의견을 말하십시오.

매일 이 문제를 해결하는 사람들을 공격하는 총을 쏘는 대신 다음에는 질문을 하고 귀하가 논평하는 문제에 대한 최신 댓글을 읽어보십시오.

정말 열심히 일하는 사람들만 있을 때 상황이 멈춘 것처럼 보일 수 있습니다.
빌드에 대해서는 이 작업의 대부분이 오늘날 일어나고 있는 github.com/moby/buildkit을 참조하십시오.

감사 해요.

오늘은 특히 풀타임으로 진행되고 있으며 사실상 표준이자 필수 정신으로 자리 잡은 프로젝트에서 문제가 되지 않아야 할 문제에 대한 해결책을 찾기 위해 오늘 9시간을 보냈기 때문에 약간 취했습니다. . 이 댓글을 쓰면서 자해를 멈추고 욕을 하지 않으려고 많이 노력했습니다.

나는 그 문제를 살펴보고 두 가지 솔루션에 대한 참조를 보았습니다. 하나는 4월 이후 중단되었고 다른 하나는 이미 종료되었습니다. 0개의 댓글 제안에 4명의 참가자가 있고 동일한 수의 댓글이 있으며 명백한 내부 토론이 언급되어 있다는 것을 알 수 있습니다. 하지만 인바 프로그래밍을 하지 않는 사람의 추가 피드백을 원하신다면 이전 댓글에서 다루었던 문제에 대한 생각을 더 많이 제공할 수 있습니다.

@오제주

최소한 하나의 쉬운 솔루션이 있습니다. 전용 서비스(예: Jenkins에서 실행)를 사용하여 아티팩트를 빌드하십시오.
해당 서비스는 이미지가 의존하는 아티팩트에 액세스하는 데 필요한 모든 키를 안전하게 프로비저닝합니다.
완료 시 인공물은 안전한 위치(예: Jenkins)에 배치됩니다. 이러한 아티팩트에는 비밀이 포함되지 않고 binaries/sources/etc가 있는 디렉토리만 포함됩니다.
그런 다음 다른 서비스(예: 다른 Jenkins 작업)가 미리 빌드된 아티팩트에 액세스하여 이미지 레지스트리에 안전하게 푸시할 수 있는 이미지로 변환합니다. 이미지 레지스트리는 차례로 rbac/keys를 사용하여 안전하게 보호되어 개발자/프로덕션 머신에서 액세스할 수 있습니다.

즉, 도커 이미지 빌드 프로세스는 다른 빌드 시스템과 다르지 않습니다. 빌드 파이프라인이 있어야 합니다.

Build pipeline

@Vanuan 모든 언어가 아티팩트와 함께 단순히 설치하기 위해 패키징 및 설치가 간단

예?

Python 프로젝트는 빌드 시간이 아니라 설치 시간에 요구 사항을 가져옵니다. 우리의 경우 개인 pypi/conda 저장소(암호로 보호됨)에서

그래서? 설치를 빌드 프로세스의 일부로 만든 다음 설치된 패키지를 새 이미지로 복사합니다.

빌드 이미지와 프로덕션 이미지가 동일한 Python 기본 이미지를 기반으로 하는지 확인하기만 하면 됩니다.

실제로 모든 것을 새 이미지로 복사할 수 있습니다. 그것은 Dockerfile의 요점을 제거합니다. 사용할 수 있는 유일한 용도가 디렉터리 집합을 복사하는 것뿐이라면 왜 Dockerfile이 있습니까?

그래서 docker build . 어디에서나 실행하는 간단한 흐름을 가질 수 없습니다. dev 머신이든 CI이든 상관없이 패키지를 빌드하려면 CI에 의존해야 합니다. 그렇다면 도커를 사용하는 이유는 무엇입니까? 트래비스 파일을 작성하거나 대나무에서 흐름을 구성할 수 있습니다.

비공개 리포지토리에서 가져올 수 있는 비밀을 사용하여 첫 번째 단계 빌드에서 pip install requirements.txt 만 할 수 있습니까? 그런 다음 다음 단계 빌드는 첫 번째 단계에서 사이트 패키지를 복사합니다.

사용할 수 있는 유일한 용도가 디렉터리 집합을 복사하는 것뿐이라면 왜 Dockerfile이 있습니까?

왜 안 돼? Dockerfile을 사용하여 빌드하는 것은 일관성이 있습니다.

이미지 사양은 단순한 압축 파일 그 이상입니다. 환경 변수, 명령줄 인수, 볼륨 등이 있습니다.

Dockerfile 참조를 읽으십시오.
https://docs.docker.com/engine/reference/builder/

Dockerfile이 Makefile을 대체한다고 생각하면서 주로 RUN 명령에 집중한 것 같습니다. 그렇지 않다. Dockerfile은 한 가지 용도로만 사용됩니다. 일부 소스 자료에서 이미지를 빌드합니다. 소스 자료가 무엇인지 - http 또는 git 저장소를 통해 다운로드한 바이너리 -는 중요하지 않습니다. 특정 조건에서 Docker를 CI 시스템으로 사용할 수 있더라도 Docker가 CI 시스템일 필요는 없습니다.

트래비스 파일을 작성하거나 대나무에서 흐름을 구성할 수 있습니다.

빌드 프로세스의 결과를 얻은 다음 이미지와 컨테이너 없이 다른 환경에서 실행할 수 있다면 확실히 도커를 사용할 필요가 없습니다. 왜 당신은?

빌드 간에 재설정이 보장되지만 빌드 단계가 변경된 경우에만 엄격하게 제어되는 별도의 환경입니다. Travis와 같은 CI 서버에서 뿐만 아니라 빌드 지침을 코드와 연결하여 어디에서나 실행할 수 있는 기능입니다. 이는 다른 코드 분기에 대한 빌드 변경(예: 한 분기에서만 실행 환경 버전 변경)에 좋은 것으로 생각됩니다. 개발자 컴퓨터에서 빌드 컨테이너를 실행할 수 있는 가능성을 통해 자신의 시스템을 업그레이드하는 방법을 모르는 개발자에게 전체 환경을 제공할 수 있지만 다른 모든 사람과 동일한 환경에서 로컬로 변경 사항을 적용하여 애플리케이션을 빌드할 수 있습니다.

그 모든 것을 원하지 않는다면 lxc + ansible을 고수하고 docker가 필요하지 않습니다.

docker build 는 필요하지 않습니다.

docker build 는 필요하지 않습니다.

물론 단일 자급 자족 Dockerfile 대신 모든 프로젝트에 대해 사용자 정의 Makefile 또는 build_image.sh 스크립트를 제공할 수도 있지만 여러 가지 단점이 있습니다.

  • 플랫폼 간 호환성: Dockerfile을 제공하면 docker build 실행할 수 있는 모든 시스템에서 이미지를 빌드할 수 있다는 것을 알고 있습니다. 사용자 정의 Makefile 또는 build_image.sh 를 제공하면 지원하려는 모든 플랫폼에서 작동하는지 수동으로 확인해야 합니다.
  • 사용자를 위한 알려진 인터페이스: docker를 알고 있다면 Dockerfile을 보지 않고도(예: 캐싱 등과 관련하여) 모든 프로젝트에 대한 docker build 의 일부 동작을 알 수 있습니다. 각 프로젝트에 대해 사용자 정의 Makefile 또는 build_image.sh 가 있는 경우 먼저 빌드, 정리, 결과가 있는 위치 및 형식에 대한 명령이 무엇인지 찾아야 합니다. 일부 캐싱이며 어떤 형태로 ...

오, Dockerfile은 자급 자족과는 거리가 멀습니다. 특히 개발 환경의 경우.
이걸 고려하세요:

  • 대부분의 개발자는 docker build다양한 옵션 을 모두 알지 못하지만 거의 모든 사람이 bash 스크립트를 실행하는 방법을 알고 있습니다.
  • docker build컨텍스트 디렉토리 에 따라 다릅니다. 따라서 모든 단일 소스 라인 변경에 대해 기가바이트의 데이터(종속성이 있는 소스 코드)가 한 위치에서 다른 위치로 이동할 때까지 기다리지 않는 한 개발에 사용하지 않을 것입니다.
  • 처음부터 모든 것을 빌드하지 않는 한 도커 레지스트리 에 대한 종속성이
  • 정적으로 빌드된 바이너리로 바로 컨테이너를 부팅하지 않는 한 OS 리포지토리 (Debian 또는 Alpine 기반 이미지를 사용하는지 여부)에 의존할 가능성이 높습니다.
  • git에 모든 것을 커밋하지 않는 한 npm, python 패키지 인덱스, rubygems 또는 기타 프로젝트 수준 종속성이 있습니다. 따라서 일부 외부 패키지 레지스트리 또는 해당 미러에 의존하게 됩니다.
  • 대부분의 사람들이 여기에서 알아차린 것처럼 공개 저장소에 게시할 수 없는 비공개 종속성 을 위한 일부 비밀 패키지 위치에
  • 해당 보안 위치에 액세스하려면 비밀 프로비저닝이 필요하므로 개발자에게 비밀
  • Dockefile 외에도 docker-compose.yml이 필요하며 크로스 플랫폼이 아닙니다. 여전히 정방향 /백슬래시 차이 에 의존합니다.

플랫폼 간 호환성: Dockerfile을 제공함으로써 docker build를 실행할 수 있는 모든 시스템이 이미지를 빌드할 수 있다는 것을 알고 있습니다.

Dockerfile은 플랫폼 간 호환성을 보장하지 않습니다. 여전히 여러 플랫폼에 대해 여러 Dockerfile을 제공해야 합니다. "도커 빌드 실행 가능"은 더 이상 "Linux 사용"을 의미하지 않습니다. Docker는 Windows 기본 이미지도 지원합니다. Windows 호스트에서 특별히 Linux 머신을 대상으로 하는 것을 실행하려면 Cygwin + Linux VM을 사용해야 합니다.

아, 그리고 x86 대 ARM에 대해서는 언급조차 하지 않았습니다...

사용자를 위한 알려진 인터페이스: docker를 알고 있다면 Dockerfile을 보지 않고도 모든 프로젝트에 대한 docker 빌드 동작의 일부를 알고 있습니다.

당신이하지 않는 한. 매개변수나 단일 make 명령 없이 bash 스크립트를 실행하는 방법은 누구나 알고 있습니다. docker build , docker run 또는 docker-compose 대한 모든 다른 명령줄 옵션을 올바르게 지정하는 방법을 아는 사람은 거의 없습니다. 래퍼 bash 또는 cmd 스크립트가 있어야 하는 것은 불가피합니다.


Docker 사람들이 한 일에 대해 충분히 존중하면서 너무 많은 것을 요구하고 있다고 생각합니다. Mobyproject는 상상할 수 있는 모든 개발 워크플로를 지원할 만큼 광범위하지 않습니다.

나는 당신의 모든 요점을 개별적으로 반박하지 않을 것입니다. 첫째, 물론 "단일 Dockerfile" 접근 방식이 전혀 작동하지 않는 상황을 항상 찾을 수 있습니다. 그러나 나는 당신이 제기한 거의 모든 요점(모두 유효하고 관련성이 있음)에 대해 "사용자 정의 스크립트 또는 makefile" 접근 방식이 그만큼 나쁘거나 더 나쁘다고 주장합니다. 한 가지 예를 들면 다음과 같습니다.

대부분의 개발자는 도커 빌드의 다양한 옵션을 모두 알지 못하지만 거의 모든 사람이 bash 스크립트를 실행하는 방법을 알고 있습니다.

내가 10개의 프로젝트에 참여하고 있고 모두 Dockerfile을 사용하는 경우 docker에 대해 한 번만 배울 필요가 있지만 귀하의 제안에 따라 10개의 완전히 다른 빌드 스크립트를 배워야 합니다. 캐시를 지우고 프로젝트 Foo의 build_image.sh 대해 처음부터 다시 시작하려면 어떻게 해야 합니까? 분명하지 않아. 이미지 빌드가 docker build 되면 명확합니다(도커가 어떻게 작동하는지 알아야 하지만 build_image.sh 나오는 이미지를 사용하기 위해 그렇게 해야 합니다).

전반적으로, 나와 다른 사람들이 만들려고 하는 요점은 /many/ 시나리오의 경우 "단일 Dockerfile" 접근 방식이 사람들에게 정말 잘 작동하는 것 같다는 것입니다. 일반적으로 모든 리소스에 비밀 없이 액세스할 수 있는 오픈 소스 세계. 그러나 리소스의 일부에 액세스하려면 자격 증명이 필요한 컨텍스트에서 좋아하게 된 것과 동일한 패턴을 적용하려고 하면 접근 방식이 실패합니다. 기술적으로 너무 복잡하지 않은 작동 방식에 대한 여러 제안(및 구현)이 있었지만 오랜 시간 동안 아무 것도 실현되지 않았습니다(이는 위에서 여러 번 설명했습니다). 따라서 좌절.

예를 들어 #33343의 연결된 제안과 같이 사람들이 이에 노력을 기울이고 있다는 점에 감사드립니다. 내 게시물은 일부 사람들이 무엇을 그리고 왜 계속 여기에서 요구하는지 동기를 부여하는 것입니다.

Docker 사람들이 한 일에 대해 충분히 존중하면서 너무 많은 것을 요구하고 있다고 생각합니다. Mobyproject는 상상할 수 있는 모든 개발 워크플로를 지원할 만큼 광범위하지 않습니다.

대부분의 사람들이 여기서 요구하는 것은 아무 것도 아니지만 docker build 비밀을 사용자 정의 build_image.sh 에서 사용하는 것보다 덜 안전하지 않은 방식으로 비밀을 사용하는 간단한 방법일 뿐입니다

죄송하지만 이 티켓의 사람마다 사용 사례가 약간 다릅니다. 이는 코너 케이스이며 다른 솔루션이 필요합니다.

  1. 개발 머신에서 프로덕션 이미지를 실행하고 싶습니다. 도커 레지스트리 사용
  2. 각 개발자가 재현 가능한 빌드를 갖도록 분산 CI 시스템을 원합니다. docker run 를 사용하여 프로젝트를 빌드하고 docker prune 를 사용하여 정리하십시오.
  3. 배포할 수 있도록 도커 이미지를 만들고 싶습니다. 다단계 빌드를 실행할 수 있는 전용 CI 서버를 사용합니다.

@Vanuan , 그래서 귀하의 접근 방식은 기본적으로 다음과 같습니다. 기본 환경 이상을 위해 도커 빌드를 사용하지 마십시오. 이것을 바꾸기 위해 만든 문제입니다. "다르게 해야 한다"는 것이 해결책이 아니라 문제입니다.

문제를 제기하는 사람들은 도커 제한 사항을 해킹할 필요 없이 도커 이미지를 사용하여 더 간단하고 직접적인 접근 방식을 원합니다.

관심 있는 모든 사람을 위해: FTP_PROXY와 같은 "masked-by-default" 빌드 인수를 활용하여 컨텍스트를 구축하려고 했습니다. docker-build가 마스크된 인수를 이미지 메타데이터나 이미지 레이어에 노출하지 않는다는 사실과 관련하여 안전합니다.

36443은 SECRET 와 같은 빌드 인수로 확장하려는 시도였습니다. 따라서 사용자가 이를 비밀 관리 문제에 대한 간단한 해결 방법으로 사용하도록 권장할 수 있습니다.

그러나 해당 빌드 인수의 마스킹된 특성이 미래에 보장되지 않기 때문에 작업은 합리적으로 거부되었습니다.

그 후 가장 좋은 방법은 @AkihiroSuda조언 을 따르고 docker build --network 또는 habitus 와 같은 도구를 사용하여 임시 TCP 서버를 통해 비밀을 저장/전달하는 것입니다.

부분적으로 댓글을 달기 때문에 5년 후 Docker가 마침내 적절한 자격 증명 관리 방향으로 작은 단계를 제공하기로 결정할 때 알림을 받습니다. 또한 현재 사용 중인 해킹의 개요를 제공합니다. , 다른 사람을 돕거나 내가 알지 못하는 구멍을 뚫습니다.

@mumoshu 문제 다음에서 마침내 빌드 비밀에 대해 미리 정의된 인수를 사용하는 힌트를 얻었습니다.

따라서 본질적으로 다음과 같은 매핑과 함께 docker-compose를 사용할 수 있습니다.

  myProject:
    build:
      context: ../myProject/
      args: 
        - HTTPS_PROXY=${NEXUS_USERNAME}
        - NO_PROXY=${NEXUS_PASSWORD}

그런 다음 docker-compose.yml 파일이 있는 폴더에 NEXUS_USERNAME 및 NEXUS_PASSWORD의 키-값 쌍과 적절한 값이 있는 ".env"라는 파일을 만듭니다.

마지막으로 Dockerfile 자체에서 다음과 같이 실행 명령을 지정합니다.
실행 wget --user $HTTPS_PROXY --암호 $NO_PROXY

그리고 DockerFile에서 ARG로 선언하지 마십시오.

아직 결과 빌드에 내 자격 증명이 떠 있는 것을 찾지 못했습니다... 하지만 여기저기를 찾고 있는지 모르겠습니다..... 그리고 내 프로젝트의 나머지 개발자들은 각각 다음을 수행해야 합니다. 적절한 값으로 .env 파일을 만듭니다.

@darmbrust 귀하의 솔루션을 시도했지만 작동하지 못했습니다.
내 작성 yml은 다음과 같습니다.
버전: "3.3"
서비스:

  buildToolsImage:
    image: vsbuildtools2017:web-v6

    build:
      context: .
      dockerfile: ./vsbuild-web-v6-optimized.dockerfile
      args:
        - CONTAINER_USER_PWD=${CONTAINER_USER_CREDS}

다음은 yml 파일 옆에 있는 .env 파일입니다.

CONTAINER_USER_CREDS=secretpassword

그리고 여기 내 dockerfile이 있습니다.

# escape=`
FROM microsoft/dotnet-framework:4.7.2-sdk
# Add non-root user
CMD ["sh", "-c", "echo ${CONTAINER_USER_PWD}"] 
RUN net user userone ${CONTAINER_USER_PWD} /add /Y

마지막으로 이것을 시작하는 명령은 다음과 같습니다.

docker-compose -f docker-compose.buildImage.yml build

.env 파일에 저장된 비밀번호를 사용하지 않고 이미지를 빌드합니다.

[경고] 하나 이상의 빌드 인수 [CONTAINER_USER_PWD]가 사용되지 않았습니다.

여기서 내가 놓치고 있는 것이 무엇입니까?
감사 해요!

도커 파일에서 https://docs.docker.com/engine/reference/builder/#predefined -args 중 하나를 사용해야 합니다. CONTAINER_USER_PWD와 같은 고유한 인수 이름을 사용할 수 없습니다.

이것이 트릭이 작동하는 방식입니다. docker는 선언하지 않고 사용할 수 있다는 점에서 미리 정의된 인수에 대한 특별한 동작을 가지고 있기 때문입니다. 그리고 선언하지 않고 사용하면 어디에도 기록되지 않는 것 같습니다.

docker-compose 파일을 사용하면 미리 정의된 인수를 보다 합리적인 이름으로 매핑할 수 있습니다.

@darmbrust 예, 트릭을 수행했습니다.
그러나 냄새가 나는 것 같지 않습니까? 더 나은 권장 사항이 있습니까?
감사 해요!

tcp를 통해 ssh-agent 자격 증명을 노출하는 것만큼 냄새가 나지 않을 것입니다.
모든 로컬 프로세스가 훔칠 수 있도록 socat을 통해
비밀과 관련하여 '도커 빌드'는 실제로 꽤 냄새가납니다.

사실 나는 Mac용 Docker가 Unix 도메인을 노출할 수 없다는 것을 잊어버렸습니다.
osx 호스트의 소켓을 컨테이너에 연결하여
벌레 캔.

내 현재 솔루션, Centos VM, GitHub 머신 사용자 계정 실행
자격 증명을 입력하고 "로커"(더 이상 사용되지 않음) 도구를 사용하여 빌드합니다.

2018년 7월 26일 목요일 21:49 Sameer Kumar, [email protected] 작성:

@darmbrust https://github.com/darmbrust 예, 그 트릭을 했습니다.
그러나 냄새가 나는 것 같지 않습니까? 더 나은 권장 사항이 있습니까?
감사 해요!


당신이 언급되었기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/moby/moby/issues/13490#issuecomment-408230125 또는 음소거
스레드
https://github.com/notifications/unsubscribe-auth/AAZk5iz1kvCpZ0s65ng4TwL7LmHa9zZvks5uKitDgaJpZM4Eq021
.

이 전체 버그는 냄새가납니다. 더 나은 방법을 찾지 못했습니다... 위에 몇 가지 다른 접근 방식이 있지만 다른 모든 보안 방법은 이미지에 정보를 제공하기 위해 약간의 http 서버를 세워야 한다고 생각합니다. 냄새는 덜할 수 있지만 더 복잡하고 더 많은 도구와 더 많은 움직이는 부품이 있습니다.

"좋은" 솔루션을 찾은 사람이 있는지 확신할 수 없습니다... 우리는 모두 도커 사람들이 그것에 대해 조치를 취하기를 기다리고 있습니다... 숨을 참지 마세요. 이 버그는 2015년에 작성되었으며 그들은 ' t는 아직 로드맵을 제안했지만 솔루션은 훨씬 적습니다.

너무 간단하고 명확하여 볼륨(파일 또는
디렉토리)를 빌드하는 동안 컨테이너에 넣습니다.

이것은 기술적인 제한이 아니라 비밀을 허용하지 않기로 한 결정입니다.
동작을 유지하기 위해 - 체크 아웃, 빌드 실행, 동일한 입력, 동일한
출력, 캐시를 무효화하려면 빌드 인수를 변경하십시오...

문제는 추상화가 점점 누수되고 있다는 것입니다.
"비밀"을 얻기 위해 모든 종류의 서투르고 안전하지 않은 해킹을 사용하는 사람들과 함께
컨테이너에.

localhost에서도 TCP를 통해 SSH 키링을 노출하는 Newsflash는
보안, 둘 다 환경 변수를 통해 자격 증명을 전달하지 않습니다(힌트, 실행
ps 또는 /proc 파일 시스템에서 엿보기), 명령 인수 및 환경 변수는 모두 세상에 알몸으로 존재합니다.

golang 코드 개발자에게 이것은 전통적으로 복사하여 붙여넣기할 때 문제가 되지 않았습니다.
종속성 관리 도구를 사용하는 대신 프로젝트에 종속성을 부여하기 위해 golang 개발자는 이 관행을 '벤더링'이라고 부릅니다.

빌드 시스템이 있는 다른 생태계에서 일하는 모든 사람을 위해
Git 또는 인증이 필요한 저장소에서 종속성을 가져오는 것은 큰 문제입니다.

어딘가에 시작 규칙이 있다고 확신합니다.
"사용자가 제품을 사용하는 방법 또는 이유를 알고 있다고 가정하지 마십시오."

2018년 7월 26일 목요일 22:00 Dan Armbrust, [email protected] 쓴:

이 전체 버그는 냄새가납니다. 나는 더 나은 방법을 찾지 못했습니다 ... 있습니다
위의 몇 가지 다른 접근 방식이 있지만 다른 모든 안전한 접근 방식은
에 정보를 제공하기 위해 약간의 http 서버를 세워야 합니다.
영상. 덜 냄새가 날 수 있지만 더 복잡하고 더 많은 도구와 더 많은 움직임
부속.

"좋은" 솔루션을 찾은 사람이 있는지 확신할 수 없습니다... 우리는 모두 막혔습니다.
docker 사람들이 그것에 대해 뭔가를 할 때까지 기다리십시오 ... 당신의 손을 잡지 마십시오
숨, 이 버그가 2015년에 작성된 이후로 그들은 제안조차 하지 않았습니다.
아직 로드맵은 아니지만 솔루션은 훨씬 적습니다.


당신이 언급되었기 때문에 이것을 받는 것입니다.
이 이메일에 직접 답장하고 GitHub에서 확인하세요.
https://github.com/moby/moby/issues/13490#issuecomment-408233258 또는 음소거
스레드
https://github.com/notifications/unsubscribe-auth/AAZk5nvbBTj4BAv5TtELNIHhJN8mU0Ctks5uKi38gaJpZM4Eq021
.

@binarytemple Docker/moby에 대해 작업한 적이 있는 모든 사람들(뒤에 있는 엔지니어들과 마찬가지로)은 문제가 무엇인지 정확히 알고 있으며 심지어 문제에 직면했습니다.

Volumes는 그 자체로 믿을 수 없을 정도로 새는 솔루션입니다.
합리적인 방식으로 이것을 해결하려고 시도하는 제안이 댓글 스트림에서 약간 언급되었습니다(https://github.com/moby/moby/issues/33343).

여기서 가장 중요한 것은 "일어나는 추상화"보다 "올바른" 추상화를 제공하는 것입니다. 물론 이것이 이 경우 뿐만 아니라 많은 사람들에게 고통스럽다는 것을 알고 있습니다.

최근에 건축업자에 대해 많은 작업이 수행되었으며 아직 반드시 볼 수는 없지만 이러한 노력의 결과는 앞으로 몇 달 안에 나타나기 시작할 것입니다.
먼저 Docker 18.06은 https://github.com/moby/buildkit에서 지원하는 대체 빌더 구현과 함께 제공됩니다
"이것이 어떻게 도움이 될까요?"라고 생각할 수 있습니다. Buildkit은 Docker 빌더에서 훨씬 더 유연하게 사용할 수 있도록 하는 많은 저수준 기본 요소를 제공합니다. 자체 빌드 파서(향상된 Dockerfile 파서에서 완전히 다른 것까지 무엇이든 될 수 있음)를 제공할 수 있을 만큼. 파서는 "Dockerfile" 상단에 지정되며 파일을 구문 분석하는 데 사용하려는 이미지일 뿐입니다.

지금 당장 보고 싶은 것이 있다면 지금 바로 buildkit 자체를 가져와 함께 실행할 수 있습니다. 이는 containerd 위에 있으며 사용자 정의 통합을 매우 빠르게 구축할 수 있습니다.

비밀 마운트 지원이 https://github.com/moby/buildkit/pull/522 의 buildkit에 추가되었습니다. tmpfs에 엄격하게 표시되고 빌드 캐시에서 제외되며 구성 가능한 데이터 소스를 사용할 수 있습니다. dockerfile 구문으로 노출하는 PR은 아직 없지만 간단한 추가 사항이어야 합니다.

비밀이 있는 이미지를 구축하는 2가지 솔루션이 있습니다.

다단계 빌드:

FROM ubuntu as intermediate
ARG USERNAME
ARG PASSWORD
RUN git clone https://${USERNAME}:${PASSWORD}@github.com/username/repository.git

FROM ubuntu
# copy the repository form the previous image
COPY --from=intermediate /your-repo /srv/your-repo

그런 다음: docker build --build-arg USERNAME=username --build-arg PASSWORD=password my-image .

이미지 빌더 사용: docker-build-with-secrets

@BenoitNorrin 죄송합니다. 하지만 해당 비밀번호를 호스트 시스템의 모든 프로세스에 노출시켰습니다. Unix security 101 - 명령 인수로 비밀을 넣지 마십시오.

예, 하지만 보안이 조금 덜 중요한 용도가 있습니다.

  • 당신은 당신의 자신의 컴퓨터에 구축하고 싶어
  • 엔터프라이즈 CI 서버(예: 젠킨스)를 기반으로 구축합니다. 대부분의 경우 개인 저장소(nexus, git, npm 등)에 대한 액세스 권한이 있으므로 CI에 이에 대한 자체 자격 증명이 있을 수 있습니다.
  • docker-machine에서 만든 VM을 사용하고 나중에 제거할 수 있습니다.

그것이 유일한 문제인 @binarytemple 인 경우 docker image build --args-file ./my-secret-file 플래그를 추가하는 것만으로도 이 전체 문제를 쉽게 해결할 수 있습니다. 그렇죠? :생각:

@yajo 는 될 수 있습니다. 예, 빌드킷이 비밀 마운트와 함께 제공될 때까지 최소한 해결 방법입니다. 좋은 제안입니다. 감사 해요. NS

불행하게도 이러한 티켓과 다른 많은 티켓에서 언급된 대부분의 해결 방법은 여전히 ​​결과 이미지에 비밀을 노출하거나 설치 중에는 종속성이 아닌 컴파일 시간에만 종속성이 필요한 특정 언어에서만 작동합니다.

절대 일어나지 않을 @binarytemple , 도커 유지 관리자는 이미 완전히 문서화되고 안전한 비밀 기능이 완전히 구현된 하나 이상의 PR을 종료했습니다. 나머지 역사를 감안할 때(이 3년 된 티켓은 가장 오래된 것이 아니며 확실히 이 주제에 대한 유일한 티켓/PR도 아닙니다) 도커 유지 관리자가 보안의 필요성을 이해하지 못한다고 말하는 것이 안전하다고 생각합니다. 문제.

나에게 가장 큰 고충은 은밀한 로테이션

서비스 종속성에 대한 비밀 그래프를 유지 관리하고 각 서비스를 두 번 업데이트해야 합니다(원래 비밀 이름으로 돌아가기 위해)

서비스의 비밀을 나열하는 것은 쉬운 일이 아닌 것 같습니다( docker service inspect --format='{{.Spec.TaskTemplate.ContainerSpec.Secrets}}' <some_service> 주변에서 몇 번의 시도 끝에 포기했습니다). docker secret inspect <secret_name> 서비스 종속성을 나열하는 것도 유용할 것입니다. 그래서 지금은 (대략적인) 그래프를 수동으로 유지합니다.

또한 docker service update 명령에서 기본 /run/secrets/<secret_name> 가 아닌 경우 비밀 대상을 지정해야 합니다.

비밀을 회전하는 더 간단한 방법을 바랍니다.

@caub는 다음과 같은 CLI 도움말입니다.

서식 지정을 위한 Docker 문서 는 나머지 검사 형식에

docker service inspect --format='{{range .Spec.TaskTemplate.ContainerSpec.Secrets}}{{println .SecretName}}{{end}}'

그러면 서비스의 모든 비밀 이름이 나열됩니다. 이름과 ID를 모두 원하는 경우 다음을 수행할 수 있습니다.

docker service inspect --format='{{range .Spec.TaskTemplate.ContainerSpec.Secrets}}{{println .SecretName .SecretID}}{{end}}' nginx

나는 항상 내 CI/CD(서비스 업데이트 명령) 또는 스택 파일이 경로를 하드코딩하므로 순환 시 해당 문제가 발생하지 않습니다.

레이블을 사용하면 스택 파일을 사용하지 않는 경우 CI/CD 자동화가 올바른 비밀을 식별하도록 할 수 있습니다(비밀 이름이 필요하지 않으며 매번 다를 수 있음).

docker build --secret 는 Docker 18.09에서 마침내 사용할 수 있습니다. https://medium.com/@tonistiigi/build -secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

@thaJeztah 이 문제를 종료할 준비가 되었습니까?

이전 버전의 docker의 경우 빌드 명령 전에 비밀 복사와 함께 다단계 빌드를 사용하는 것이 가능한 옵션입니까?

```
빌드로 데비안에서
복사 ./secret.conf /경로/온/이미지/
RUN 빌드.sh
...

데비안에서
복사 --from=빌드 ...

@andriy-f 예, 작동하는 한 작동합니다.

  • (분명히) 비밀을 마지막 단계에 복사하지 마세요 😉, 또는:
  • build 단계/비밀이 최종 이미지의 "부모"로 존재하는 단계 사용
  • 빌드 단계를 레지스트리로 _push_하지 마십시오.
  • 데몬이 실행되는 호스트를 신뢰하십시오. 즉, "빌드" 단계가 이미지로 보존된다는 점을 고려합니다. 해당 이미지에 대한 액세스 권한이 있는 사람이 귀하의 비밀에 액세스할 수 있습니다.

이제 빌드킷을 빌더로 사용할 때 빌드 시간 비밀이 가능합니다. 여기에서 블로그 게시물을 참조하십시오. https://medium.com/@tonistiigi/build -secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066

그리고 문서; https://docs.docker.com/develop/develop-images/build_enhancements/

비밀에 사용되는 RUN --mount 옵션은 곧 기본(안정적인) Dockerfile 구문으로 전환됩니다.

@thaJeztah 감사합니다. 조금 더 파고 들어 게시 직후 해당 기사를 찾았습니다(이전 게시물은 현재 삭제됨). 다시 한번 감사합니다!

멋있는. 그러면 빌드 시간 비밀 질문이 닫힙니다. 런타임/개발 시간(OS X의 ssh)을 위한 것이 있습니까?

이 페이지가 도움이 되었나요?
0 / 5 - 0 등급