Sử dụng local SSH keys bên trong docker container

Sử dụng local SSH keys bên trong docker container

Một trong những khách hàng của chúng tôi cung cấp cho chúng tôi quyền truy cập của từng người dùng vào hệ thống của họ thông qua VPN độc quyền mà chúng tôi không thể thiết lập trên cơ sở hạ tầng CI của mình.

Khi chúng tôi cần triển khai ứng dụng Rails của họ, chúng tôi dựa vào các tập lệnh mina kết nối với các máy triển khai bằng kết nối SSH (qua VPN). Để hoạt động bình thường, mina cần bạn trao đổi khóa SSH với máy chủ. Đây là các dự án kế thừa, vì vậy chúng tôi sử dụng Docker để điều hành môi trường phát triển địa phương của chúng tôi. Vì vậy, làm thế nào chúng ta có thể triển khai bằng Docker?

One key cho tất cả

Một tùy chọn sẽ là tạo một khóa triển khai chia sẻ mới cho dự án bằng ssh-keygen, trao đổi phần công khai với máy chủ và sử dụng nó trong Dockerfile của chúng tôi.

Hãy tạo một khóa và trao đổi nó với máy chủ mục tiêu:

$ ssh-keygen -t rsa -b 4096 -f ./id_rsa_shared
$ ssh-copy-id -i ./id_rsa_shared remoteuser@remotehost

Build test:

 

Testing ...

$ docker build -t ssh-test .
$ docker run -it --rm ssh-test remoteuser@remotehost

Bây giờ bạn sẽ được đăng nhập vào remotehost với tư cách remoteuser.

Lưu ý rằng chúng tôi đã vô hiệu hóa tính năng Kiểm tra nghiêm ngặt để tự động thêm máy chủ từ xa vào known_hosts của hình ảnh. Trong kịch bản của chúng tôi, chúng tôi có thể tin tưởng vào danh tính máy chủ từ xa. Số dặm của bạn có thể thay đổi và bạn có thể phải thêm vân tay máy chủ từ xa bằng tay.

Mặc dù giải pháp này hoạt động, nhưng nó không tốt. Chia sẻ một khóa có nghĩa là nếu bạn muốn thu hồi quyền truy cập đối với một người dùng, bạn sẽ thu hồi quyền truy cập của mọi người khác. Mỗi thay đổi trong khóa SSH sẽ liên quan đến việc xây dựng và chia sẻ một hình ảnh mới. Có thể tốt hơn nếu sử dụng từng khóa cục bộ của người dùng và quản lý từng người dùng được phép trong máy chủ từ xa.

Sử dụng  mounting volumes

Easy. Sửa đổi một chút Dockerfile và gắn kết thư mục .ssh cục bộ của bạn.

Start container trực tiếp và mount volume:

$ docker run -it --rm -v ~/.ssh:/home/user/.ssh:ro \
ssh-test remoteuser@remotehost

Hoặc sử dụng Docker Compose để mount volume:

$ docker-compose run test ssh remoteuser@remotehost

Done!

Lợi ích là gì?

Bạn đoán xem. Có một điểm hấp dẫn (và do đó, thêm câu chuyện bên dưới 😉).


Trong một số môi trường nhất định (như WSL trong Windows, các phiên bản docker cũ hơn trên Mac, v.v.), việc gắn ổ đĩa không hoạt động do các vấn đề khác nhau. Vì vậy, chúng ta hãy cố gắng tìm ra một số cách giải quyết trong trường hợp bạn tình cờ gặp một trong những môi trường này.

Sử dụng local keys khi build

Luôn có thể sử dụng khóa cục bộ của người dùng khi xây dựng hình ảnh. Tuy nhiên, bạn không thể viết điều này trong Dockerfile của mình:

Vì lý do bảo mật, Docker sẽ không sao chép bất kỳ tệp nào từ bên ngoài thư mục nơi bạn đang tạo hình ảnh. Bạn luôn có thể sao chép các khóa SSH của mình vào thư mục dự án trước khi SAO CHÉP chúng.

Mặc dù hiện tại chúng tôi đang sử dụng các khóa cục bộ, nhưng điều này buộc mỗi người dùng phải xây dựng hình ảnh của riêng họ và di chuyển xung quanh các khóa SSH. Nếu có thể, chúng tôi muốn xuất bản một hình ảnh được chia sẻ lên sổ đăng ký Docker riêng để dễ lấy và sử dụng. Điều này cũng đảm bảo rằng mỗi nhà phát triển sử dụng cùng một hình ảnh.

Docker secrets

Bằng cách sử dụng các bí mật Docker, chúng ta có thể có một hình ảnh chung sử dụng các khóa SSH cục bộ.

Bí mật là một khối dữ liệu, chẳng hạn như mật khẩu, khóa cá nhân SSH, chứng chỉ SSL hoặc một phần dữ liệu khác không được truyền qua mạng hoặc được lưu trữ không được mã hóa trong Dockerfile hoặc trong mã nguồn ứng dụng của bạn. Trong Docker 1.13 trở lên, bạn có thể sử dụng các bí mật Docker để quản lý tập trung dữ liệu này và truyền dữ liệu một cách an toàn đến chỉ những vùng chứa cần quyền truy cập vào nó. Các bí mật được mã hóa trong quá trình chuyển tiếp và ở trạng thái nghỉ trong một bầy Docker. Một bí mật nhất định chỉ có thể truy cập được đối với những dịch vụ đã được cấp quyền truy cập rõ ràng vào nó và chỉ khi các tác vụ dịch vụ đó đang chạy.

Các bí mật được cung cấp cho vùng chứa sẽ có sẵn dưới dạng tệp tại /run/secret/. Hãy sửa đổi Dockerfile của chúng tôi để sử dụng một trong những bí mật này làm khóa SSH:

Nhưng bây giờ… làm thế nào chúng ta có thể thiết lập bí mật khi sử dụng docker run? Chà, chúng ta không thể 😅. Docker bí mật được sử dụng với Docker Swarm, không phải với các vùng chứa độc lập. Đừng sợ. Docker compile không hỗ trợ các bí mật, vì vậy sử dụng một tệp soạn thảo tương tự như thế này sẽ thực hiện thủ thuật:

Run image của bạn thông qua docker compose và bạn đã sẵn sàng:

$ docker-compose run test ssh remoteuser@remotehost

Tổng hợp

Như chúng ta đã thấy, cách đơn giản nhất để sử dụng các phím SSH cục bộ là gắn một ổ đĩa. Để giải quyết vấn đề, trong trường hợp bạn có môi trường phát triển có vấn đề, bạn có thể sử dụng bí mật Docker. Chúng tôi đã gặp phải tình huống đó trước đây và sử dụng bí mật là cách để đi cho chúng tôi.

Sử dụng bí mật thay vì gắn khối lượng cũng có thể tăng thêm giá trị nếu bạn đang sử dụng Docker Swarm (như chúng tôi làm) và hình ảnh sản xuất của bạn rất giống với hình ảnh phát triển.