วิธีใดเป็นวิธีที่ดีที่สุดในการส่งข้อมูลรับรอง AWS ไปยัง Docker container


110

ฉันใช้งาน Docker-container บน Amazon EC2 ขณะนี้ฉันได้เพิ่ม AWS Credentials ไปยัง Dockerfile แล้ว โปรดแจ้งให้เราทราบวิธีที่ดีที่สุดในการดำเนินการนี้ได้ไหม


2
แล้วถ้าฉันใช้ Docker container บนแล็ปท็อปของฉันซึ่งควรจะใช้งานได้อย่างน่าอัศจรรย์ใน ECS เมื่อฉันดันไปที่นั่น? ฉันจะเดาว่าฉันใช้ธง - ระดับเสียง ... ต้องมีคนตอบอยู่แล้ว ...
Randy L

คำตอบ:


114

วิธีที่ดีที่สุดคือใช้ IAM Role และอย่าจัดการกับข้อมูลรับรองเลย (ดูhttp://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html )

สามารถดึงข้อมูลรับรองได้จากhttp://169.254.169.254..... เนื่องจากนี่เป็นที่อยู่ IP ส่วนตัวจึงสามารถเข้าถึงได้จากอินสแตนซ์ EC2 เท่านั้น

ไลบรารีไคลเอ็นต์ AWS สมัยใหม่ทั้งหมด "รู้" วิธีดึงรีเฟรชและใช้ข้อมูลรับรองจากที่นั่น ดังนั้นในกรณีส่วนใหญ่คุณไม่จำเป็นต้องรู้เรื่องนี้ด้วยซ้ำ เพียงเรียกใช้ ec2 ด้วยบทบาท IAM ที่ถูกต้องคุณก็พร้อมใช้งาน

เป็นตัวเลือกที่คุณสามารถส่งผ่านไปที่รันไทม์เป็นตัวแปรสภาพแวดล้อม (เช่นdocker run -e AWS_ACCESS_KEY_ID=xyz -e AWS_SECRET_ACCESS_KEY=aaa myimage)

คุณสามารถเข้าถึงตัวแปรสภาพแวดล้อมเหล่านี้ได้โดยเรียกใช้ printenv ที่เทอร์มินัล


41
มีวิธีที่ดีในการดำเนินการระหว่างการพัฒนา / การทดสอบในท้องถิ่นที่ไม่กระทบต่อความปลอดภัยในการผลิตหรือไม่ ฉันต้องการตรวจสอบให้แน่ใจว่ารูปภาพใช้งานได้โดยไม่ต้องปรับใช้อย่างเต็มที่
honktronic

3
ทางเลือกอื่นที่ฉันโพสต์ด้วยตัวแปรสภาพแวดล้อมทำงานได้ดีในสภาพแวดล้อม dev / local
Vor

5
ฉันสงสัยว่านี่เป็นการพิมพ์ผิด แต่ฉันต้องป้อนAWS_SECRET_ACCESS_KEYไม่ใช่AWS_SECRET_KEYอย่างไรก็ตามคำตอบของคุณมีประโยชน์มาก ขอขอบคุณ.
Akavall

14
พูดง่ายๆ (สำหรับผู้ที่ได้รับคำตอบแบบเดียวกับที่ฉันทำ); คอนเทนเนอร์นักเทียบท่าที่ทำงานบน EC2 จะสืบทอดบทบาทเดียวกันกับอินสแตนซ์ของโฮสต์ (ฉันต้องการ "ELI5" แบบนี้เมื่อคำสั่ง AWS CLI ในคอนเทนเนอร์ของฉันทำงานอย่างลึกลับแม้ว่าจะไม่มีการส่งข้อมูลรับรองให้ก็ตาม!)
Adam Westbrook

9
วิธีง่ายๆในการรับค่าคีย์จากโปรไฟล์ในเครื่องของคุณเพื่อกำหนดให้กับตัวแปรสภาพแวดล้อมสำหรับวัตถุประสงค์ในการพัฒนา (ตามที่แนะนำในcameroneckelberry.co/words/… ): "aws --profile default configuration get aws_access_key_id"
Altair7852

106

มีการเปลี่ยนแปลงมากมายใน Docker ตั้งแต่คำถามนี้ถูกถามดังนั้นนี่คือความพยายามในการตอบคำถามที่อัปเดต

ประการแรกโดยเฉพาะกับข้อมูลรับรอง AWS บนคอนเทนเนอร์ที่ทำงานอยู่ภายในระบบคลาวด์แล้วการใช้บทบาท IAM ตามที่Vor แนะนำเป็นตัวเลือกที่ดีมาก ถ้าทำได้ก็ให้บวกอีกหนึ่งคำตอบแล้วข้ามส่วนที่เหลือไป


เมื่อคุณเริ่มใช้งานสิ่งต่างๆนอกระบบคลาวด์หรือมีความลับประเภทอื่นมีสองสถานที่สำคัญที่ฉันแนะนำให้ไม่เก็บความลับ:

  1. ตัวแปรสภาพแวดล้อม: เมื่อกำหนดสิ่งเหล่านี้บนคอนเทนเนอร์ทุกกระบวนการภายในคอนเทนเนอร์สามารถเข้าถึงได้พวกเขาสามารถมองเห็นได้ผ่าน / proc แอปอาจถ่ายโอนสภาพแวดล้อมไปยัง stdout ที่เก็บไว้ในบันทึกและที่สำคัญที่สุดคือปรากฏใน ล้างข้อความเมื่อคุณตรวจสอบคอนเทนเนอร์

  2. ในตัวรูปภาพเอง: รูปภาพมักจะถูกผลักไปที่รีจิสเตอร์ที่มีผู้ใช้จำนวนมากสามารถดึงการเข้าถึงได้บางครั้งก็ไม่มีข้อมูลรับรองที่จำเป็นในการดึงรูปภาพ แม้ว่าคุณจะลบความลับออกจากเลเยอร์เดียวภาพก็สามารถถอดประกอบได้ด้วยยูทิลิตี้ Linux ทั่วไปเช่นtarและสามารถดูความลับได้จากขั้นตอนที่เพิ่มลงในภาพครั้งแรก


แล้วตัวเลือกอื่น ๆ สำหรับความลับในคอนเทนเนอร์ Docker มีอะไรบ้าง?

ตัวเลือก A:หากคุณต้องการความลับนี้ในระหว่างการสร้างอิมเมจของคุณเท่านั้นไม่สามารถใช้ความลับนี้ได้ก่อนที่การสร้างจะเริ่มต้นและยังไม่มีสิทธิ์เข้าถึง BuildKit การสร้างแบบหลายขั้นตอนเป็นตัวเลือกที่ไม่ดีที่สุด คุณจะต้องเพิ่มความลับในขั้นตอนเริ่มต้นของการสร้างใช้ที่นั่นจากนั้นคัดลอกผลลัพธ์ของขั้นตอนนั้นโดยไม่มีความลับไปยังขั้นตอนการเผยแพร่ของคุณและผลักขั้นตอนการเผยแพร่นั้นไปยังเซิร์ฟเวอร์รีจิสทรีเท่านั้น ความลับนี้ยังคงอยู่ในแคชรูปภาพบนบิลด์เซิร์ฟเวอร์ดังนั้นฉันมักจะใช้สิ่งนี้เป็นทางเลือกสุดท้ายเท่านั้น

ตัวเลือก B:นอกจากนี้ในช่วงเวลาสร้างหากคุณสามารถใช้ BuildKit ซึ่งเปิดตัวใน 18.09 ขณะนี้มีคุณลักษณะทดลองที่อนุญาตให้ใส่ข้อมูลลับเป็นตัวกำหนดโวลุ่มสำหรับบรรทัด 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 Mode หรือการควบคุมอื่น ๆ คุณสามารถเมานต์หนังสือรับรองเป็นโวลุ่มอ่านอย่างเดียว การเข้าถึงข้อมูลประจำตัวนี้ต้องการการเข้าถึงแบบเดียวกับที่คุณมีภายนอกนักเทียบท่าในไฟล์ข้อมูลรับรองเดียวกันดังนั้นจึงไม่ดีหรือแย่ไปกว่าสถานการณ์ที่ไม่มีนักเทียบท่า สิ่งสำคัญที่สุดคือไม่ควรมองเห็นเนื้อหาของไฟล์นี้เมื่อคุณตรวจสอบคอนเทนเนอร์ดูบันทึกหรือพุชอิมเมจไปยังเซิร์ฟเวอร์รีจิสทรีเนื่องจากโวลุ่มอยู่นอกนั้นในทุกสถานการณ์ สิ่งนี้ต้องการให้คุณคัดลอกข้อมูลประจำตัวของคุณบนโฮสต์นักเทียบท่าแยกต่างหากจากการปรับใช้คอนเทนเนอร์ (หมายเหตุทุกคนที่มีความสามารถในการเรียกใช้คอนเทนเนอร์บนโฮสต์นั้นสามารถดูข้อมูลประจำตัวของคุณได้เนื่องจากการเข้าถึง 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 ตอนนี้เรามีการสนับสนุนลับที่ดีกว่า Volume ด้วยโหมด Swarm ไฟล์จะถูกเข้ารหัสบนระบบไฟล์ตัวจัดการ (แม้ว่าคีย์ถอดรหัสมักจะอยู่ที่นั่นด้วยทำให้ตัวจัดการสามารถเริ่มต้นใหม่ได้โดยที่ผู้ดูแลระบบไม่ต้องป้อนคีย์ถอดรหัส) ที่สำคัญกว่านั้นความลับจะถูกส่งไปยังคนงานที่ต้องการความลับเท่านั้น (ใช้งานคอนเทนเนอร์ที่มีความลับนั้น) มันจะถูกเก็บไว้ในหน่วยความจำบนคนงานเท่านั้นไม่เคยใส่ดิสก์และจะถูกฉีดเป็นไฟล์ลงในคอนเทนเนอร์ด้วย tmpfs เมานต์ ผู้ใช้บนโฮสต์นอกฝูงไม่สามารถเชื่อมต่อความลับนั้นลงในคอนเทนเนอร์ของตนเองได้โดยตรงอย่างไรก็ตามด้วยการเข้าถึง 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สำหรับโหนดเดียวจากนั้นทำตามคำแนะนำในการเพิ่มโหนดเพิ่มเติม 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:มีเครื่องมืออื่น ๆ ในการจัดการความลับและที่ฉันชอบคือห้องนิรภัยเพราะให้ความสามารถในการสร้างความลับแบบ จำกัด เวลาซึ่งจะหมดอายุโดยอัตโนมัติ จากนั้นทุกแอปพลิเคชันจะได้รับชุดโทเค็นของตัวเองเพื่อขอความลับและโทเค็นเหล่านั้นทำให้พวกเขาสามารถขอความลับที่ จำกัด เวลาเหล่านั้นได้ตราบเท่าที่พวกเขาสามารถเข้าถึงเซิร์ฟเวอร์ห้องนิรภัย ซึ่งจะช่วยลดความเสี่ยงหากความลับถูกนำออกจากเครือข่ายของคุณเนื่องจากจะใช้งานไม่ได้หรือหมดอายุอย่างรวดเร็ว ฟังก์ชันเฉพาะสำหรับ AWS สำหรับห้องนิรภัยมีการบันทึกไว้ที่https://www.vaultproject.io/docs/secrets/aws/index.html


24

อีกวิธีหนึ่งคือการส่งผ่านคีย์จากเครื่องโฮสต์ไปยังคอนเทนเนอร์นักเทียบท่า คุณสามารถเพิ่มบรรทัดต่อไปนี้ลงใน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}

3
ตัวแปรสภาพแวดล้อมของภูมิภาคที่ถูกต้องคือ AWS_REGION ดูstackoverflow.com/questions/44151982/…
John Camerin

3
โปรดตรวจสอบเอกสารอย่างเป็นทางการซึ่งกล่าวถึงAWS_DEFAULT_REGION docs.aws.amazon.com/cli/latest/userguide/…
prafi

7
เมื่อฉันใช้ AWS_DEFAULT_REGION ฉันได้รับข้อยกเว้นว่าไม่พบภูมิภาคเริ่มต้น การค้นหาของฉันนำไปสู่docs.aws.amazon.com/sdk-for-java/v1/developer-guide/…ซึ่งระบุตัวแปรสภาพแวดล้อม AWS_REGION และนั่นก็เหมาะกับฉัน
John Camerin

หากคุณใช้ข้อมูลรับรองชั่วคราวคุณอาจต้องใช้AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
ดาวอส

18

อีกวิธีหนึ่งคือการสร้างไดรฟ์ข้อมูลแบบอ่านอย่างเดียวชั่วคราวใน docker-compose.yaml AWS CLI และ SDK (เช่น boto3 หรือ AWS SDK สำหรับ Java เป็นต้น) กำลังมองหาdefaultโปรไฟล์ใน~/.aws/credentialsไฟล์

หากคุณต้องการใช้โปรไฟล์อื่นคุณต้องส่งออกตัวแปร AWS_PROFILE ก่อนที่จะรันdocker-composeคำสั่ง

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 ด้วย นอกจากนี้ยังมีประโยชน์เมื่อคุณต้องการทดสอบ Docker-container ในพื้นที่ก่อนที่จะปรับใช้กับ ECS ที่คุณมีบทบาท IAM แต่ในเครื่องคุณไม่ทำ


แคตตาล็อกหน้าต่าง .aws` "%UserProfile%\.aws"ตั้งอยู่ ผมคิดว่าคุณต้องเปลี่ยน - ~/.aws/:/root/.aws:roเป็น- %UserProfile%\.aws:/root/.aws:ro
Artur Siepietowski

1
สิ่งนี้จะใช้ได้เฉพาะกับกระบวนการสร้างเดียวไม่ใช่หลายขั้นตอน
wlarcheveque

@wlarcheveque ดูแลให้ละเอียด?
ErikE

โปรดใช้ความระมัดระวังอย่างมากในการใช้- host:containerไวยากรณ์หากไฟล์ / โฟลเดอร์ไม่มีอยู่ในโฮสต์ที่สร้างขึ้น (เป็นรูท) และ awscli จะไม่ขอบคุณที่ป้อนไฟล์เป็นศูนย์ไบต์ คุณควรใช้ "แบบยาว" ที่ระบุประเภทคือการผูกพา ​​ธ โฮสต์และพา ธ คอนเทนเนอร์ในบรรทัดแยกกันซึ่งจะล้มเหลวหากไม่มีไฟล์ซึ่งเป็นสิ่งที่คุณต้องการใน docker-compose.dev ของคุณ yml แต่ไม่อยู่ใน docker-compose.yml ของคุณ (ใช้งาน prod / AWS)
dragon788

0

คุณสามารถสร้าง~/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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.