[amazon-web-services] AWS 자격 증명을 Docker 컨테이너에 전달하는 가장 좋은 방법은 무엇입니까?

Amazon EC2에서 docker-container를 실행하고 있습니다. 현재 Dockerfile에 AWS 자격 증명을 추가했습니다. 이 작업을 수행하는 가장 좋은 방법을 알려주시겠습니까?



답변

가장 좋은 방법은 IAM 역할을 사용하고 자격 증명을 전혀 처리하지 않는 것입니다. ( http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html 참조 )

자격 증명을 검색 할 수 있습니다. http://169.254.169.254..... 개인 IP 주소이므로 EC2 인스턴스에서만 액세스 할 수 있습니다.

모든 최신 AWS 클라이언트 라이브러리는 여기에서 자격 증명을 가져오고 새로 고치고 사용하는 방법을 “알고”있습니다. 따라서 대부분의 경우 그것에 대해 알 필요조차 없습니다. 올바른 IAM 역할로 ec2를 실행하기 만하면됩니다.

옵션으로 런타임에 환경 변수 (예 : docker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage )

터미널에서 printenv를 실행하여 이러한 환경 변수에 액세스 할 수 있습니다.


답변

이 질문을받은 이후 Docker에서 많은 것이 변경되었으므로 여기에 업데이트 된 답변을 시도해 보겠습니다.

첫째, 특히 클라우드 내부에서 이미 실행중인 컨테이너에 대한 AWS 자격 증명을 사용하면 Vor가 제안한 대로 IAM 역할을 사용 하는 것이 정말 좋은 옵션입니다. 그렇게 할 수 있다면 대답에 더하기 1을 더하고 나머지는 건너 뛰십시오.


클라우드 외부에서 작업을 시작하거나 다른 유형의 비밀이 있으면 비밀 저장 에 대해 권장 하는 두 가지 주요 장소가 있습니다 .

  1. 환경 변수 : 이러한 변수가 컨테이너에 정의되면 컨테이너 내부의 모든 프로세스가 액세스 할 수 있으며 / proc을 통해 볼 수 있으며 앱은 로그에 저장되는 stdout에 환경을 덤프 할 수 있으며 가장 중요한 것은 컨테이너를 검사 할 때 텍스트를 지 웁니다.

  2. 이미지 자체 : 이미지는 종종 이미지를 가져 오는 데 필요한 자격 증명없이 많은 사용자가 가져 오기 액세스 권한이있는 레지스트리로 푸시됩니다. 한 레이어에서 비밀을 삭제하더라도 다음과 같은 일반적인 Linux 유틸리티를 사용하여 이미지를 분해 할 수 있습니다.tar 에 처음 추가 된 단계에서 비밀을 찾을 수 있습니다.


그렇다면 Docker 컨테이너의 비밀에 대한 다른 옵션은 무엇입니까?

옵션 A : 이미지 빌드 중에 만이 시크릿이 필요하고 빌드가 시작되기 전에 시크릿을 사용할 수없고 아직 BuildKit에 대한 액세스 권한이없는 경우 다단계 빌드 가 나쁜 옵션 중 최고입니다. 빌드의 초기 단계에 비밀을 추가하고 거기에서 사용한 다음 비밀없이 해당 단계의 출력을 릴리스 단계에 복사하고 해당 릴리스 단계 만 레지스트리 서버로 푸시합니다. 이 비밀은 여전히 ​​빌드 서버의 이미지 캐시에 있으므로 마지막 수단으로 만 사용하는 경향이 있습니다.

옵션 B : 또한 빌드 시간 동안 18.09에서 출시 된 BuildKit을 사용할 수 있다면 현재 단일 RUN 라인에 대한 볼륨 마운트로 비밀을 주입 할 수있는 실험적 기능 이 있습니다 . 해당 마운트는 이미지 레이어에 기록되지 않으므로 공개 레지스트리 서버로 푸시 될 염려없이 빌드 중에 보안 비밀에 액세스 할 수 있습니다. 결과 Dockerfile은 다음과 같습니다.

# syntax = docker/dockerfile:experimental
FROM python:3
RUN pip install awscli
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials aws s3 cp s3://... ...

그리고 18.09 이상에서 다음과 같은 명령으로 빌드합니다.

DOCKER_BUILDKIT=1 docker build -t your_image --secret id=aws,src=$HOME/.aws/credentials .

옵션 C :Swarm 모드 또는 기타 오케스트레이션없이 단일 노드에서 런타임에 자격 증명을 읽기 전용 볼륨으로 마운트 할 수 있습니다. 이 자격 증명에 액세스하려면 docker 외부에서 동일한 자격 증명 파일에 대한 것과 동일한 액세스 권한이 필요하므로 docker가없는 시나리오보다 좋거나 나쁘지 않습니다. 가장 중요한 것은 컨테이너를 검사하거나 로그를 보거나 이미지를 레지스트리 서버로 푸시 할 때이 파일의 내용이 보이지 않아야한다는 것입니다. 이는 모든 시나리오에서 볼륨이 그 범위 밖에 있기 때문입니다. 컨테이너 배포와는 별도로 Docker 호스트에 자격 증명을 복사해야합니다. (참고로, Docker API에 대한 액세스는 호스트에서 루트이고 루트가 모든 사용자의 파일을 볼 수 있기 때문에 해당 호스트에서 컨테이너를 실행할 수있는 권한이있는 모든 사용자가 자격 증명을 볼 수 있습니다. 호스트에서 루트가있는 사용자를 신뢰하지 않는 경우 ,

의 경우 docker run다음과 같습니다.

docker run -v $HOME/.aws/credentials:/home/app/.aws/credentials:ro your_image

또는 작성 파일의 경우 다음이 필요합니다.

version: '3'
services:
  app:
    image: your_image
    volumes:
    - $HOME/.aws/credentials:/home/app/.aws/credentials:ro

옵션 D :Swarm Mode 및 Kubernetes와 같은 오케스트레이션 도구를 사용하여 이제 볼륨보다 더 나은 비밀 지원이 제공됩니다. Swarm 모드를 사용하면 파일이 관리자 파일 시스템에서 암호화됩니다 (복호화 키도있는 경우가 많으므로 관리자가 복호화 키를 입력하지 않고도 관리자를 다시 시작할 수 있음). 더 중요한 것은 비밀이 필요한 작업자에게만 전송되고 (해당 비밀을 사용하여 컨테이너를 실행하는) 작업자의 메모리에만 저장되고 디스크에는 저장되지 않으며 tmpfs를 사용하여 컨테이너에 파일로 주입됩니다. 산. swarm 외부의 호스트에있는 사용자는 해당 비밀을 자신의 컨테이너에 직접 마운트 할 수 없지만 docker API에 대한 개방형 액세스를 통해 노드의 실행중인 컨테이너에서 비밀을 추출 할 수 있으므로 다시 한 번이 액세스 권한을 가진 사용자를 제한합니다. API. 작성에서이 비밀 주입은 다음과 같습니다.

version: '3.7'

secrets:
  aws_creds:
    external: true

services:
  app:
    image: your_image
    secrets:
    - source: aws_creds
      target: /home/user/.aws/credentials
      uid: '1000'
      gid: '1000'
      mode: 0700

docker swarm init단일 노드에 대해 swarm 모드를 켠 다음 추가 노드 추가 지침을 따릅니다. 을 사용하여 외부에서 비밀을 만들 수 있습니다 docker secret create aws_creds $HOME/.aws/credentials. 그리고 docker stack deploy -c docker-compose.yml stack_name.

나는 종종 https://github.com/sudo-bmitch/docker-config-update 의 스크립트를 사용하여 내 비밀을 버전 화합니다.

옵션 E : 비밀을 관리하기위한 다른 도구가 있으며, 제가 가장 좋아하는 Vault 는 자동으로 만료되는 시간 제한 비밀을 생성 할 수있는 기능을 제공하기 때문입니다. 그런 다음 모든 애플리케이션은 비밀을 요청하기 위해 자체 토큰 세트를 가져오고 해당 토큰은 Vault 서버에 도달 할 수있는 한 시간 제한 비밀을 요청할 수있는 기능을 제공합니다. 이렇게하면 비밀이 작동하지 않거나 빨리 만료되기 때문에 네트워크에서 비밀이 유출되는 경우 위험이 줄어 듭니다. AWS for Vault와 관련된 기능은 https://www.vaultproject.io/docs/secrets/aws/index.html에 문서화되어 있습니다.


답변

또 다른 접근 방식은 호스트 컴퓨터에서 Docker 컨테이너로 키를 전달하는 것입니다. docker-compose파일 에 다음 줄을 추가 할 수 있습니다 .

services:
  web:
    build: .
    environment:
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}


답변

또 다른 접근 방식은 docker-compose.yaml에 임시 읽기 전용 볼륨을 만드는 것입니다. AWS CLI 및 SDK (예 : boto3 또는 Java 용 AWS SDK 등)가 파일 default에서 프로필을 찾고 ~/.aws/credentials있습니다.

다른 프로필을 사용하려면 docker-compose명령을 실행하기 전에 AWS_PROFILE 변수를 내 보내면됩니다.

export AWS_PROFILE=some_other_profile_name

version: '3'

services:
  service-name:
    image: docker-image-name:latest
    environment:
      - AWS_PROFILE=${AWS_PROFILE}
    volumes:
      - ~/.aws/:/root/.aws:ro

이 예에서는 도커에서 루트 사용자를 사용했습니다. 다른 사용자를 사용하는 경우 /root/.aws사용자 홈 디렉토리로 변경하십시오.

:ro -읽기 전용 도커 볼륨을 나타냅니다.

~/.aws/credentials파일에 여러 프로필이 있고 MFA도 사용 하는 경우 매우 유용합니다 . 또한 IAM 역할이있는 ECS에 배포하기 전에 Docker-container를 로컬에서 테스트하려는 경우에도 유용하지만 로컬에는 없습니다.


답변

~/aws_env_creds포함을 만들 수 있습니다.

touch ~/aws_env_creds
chmod 777 ~/aws_env_creds
vi ~/aws_env_creds

아래 값 추가 (귀하의 키 교체)

AWS_ACCESS_KEY_ID=AK_FAKE_KEY_88RD3PNY
AWS_SECRET_ACCESS_KEY=BividQsWW_FAKE_KEY_MuB5VAAsQNJtSxQQyDY2C

“esc”는 파일을 저장합니다.

컨테이너 실행 및 테스트

 my_service:
      build: .
      image: my_image
      env_file:
        - ~/aws_env_creds


답변