- Nếu đặt bí mật ở dạng văn bản thuần trong cấu hình Nix, kho Git riêng tư hoặc
git-crypt trên NixOS thì Nix store có thể bị bất kỳ ai đọc được, nên người có quyền truy cập máy có thể đọc bí mật
- sops-nix mã hóa tệp bí mật bằng các quy tắc trong
.sops.yaml và quy trình chỉnh sửa của sops, rồi khi kích hoạt sẽ giải mã bằng khóa SSH của máy chủ và đặt bản rõ trong tmpfs tại /run/secrets/<name>
- agenix chỉ định khóa công khai người nhận cho từng bí mật trong
secrets.nix và giải mã các tệp .age vào tmpfs tại /run/agenix/<name>; khi thêm máy chủ mới hoặc thay khóa thì cần rekey
- Cách đặt bí mật trực tiếp trên hệ thống tệp có thể chấp nhận được với máy chủ đơn lẻ hoặc laptop, nhưng nếu đọc tại thời điểm đánh giá như
builtins.readFile "/var/lib/myservice/token" thì giá trị sẽ đi vào Nix store, nên cần tránh
- Nếu mới bắt đầu và chỉ có vài token độc lập thì agenix có ít bước hơn; còn với máy chủ có nhiều bí mật liên quan như mail server thì sops-nix, vốn có thể gộp nhiều giá trị vào một tệp, sẽ phù hợp hơn
Rủi ro cơ bản khi xử lý bí mật trong NixOS
- Quản lý bí mật trên NixOS thường được chia thành các cách như
sops-nix, agenix/ragenix, tận dụng hệ thống tệp, kho Git riêng tư, git-crypt, hoặc viết trực tiếp vào cấu hình Nix
- Không nên dùng kho Git riêng tư,
git-crypt, hay viết trực tiếp vào cấu hình Nix nếu bạn chia sẻ máy hoặc dự định công khai cấu hình
- Đã từng có ít nhất hai lần bí mật bị lộ trong cấu hình công khai; ví dụ vẫn còn ở 1, 2
sops-nix
- sops-nix có thể khiến người mới thấy khó cấu hình lúc ban đầu, nhưng tài liệu đã được cải thiện đáng kể, và việc
sops nay mặc định hỗ trợ mã hóa/giải mã bí mật bằng khóa SSH là một cải tiến lớn
- Tuy vậy,
sops-nix hiện vẫn chưa theo kịp phần hỗ trợ khóa SSH này; công việc liên quan đang được thực hiện tại sops-nix#779, sops-nix#922
- Quy trình sử dụng là tạo quy tắc mã hóa/giải mã trong
.sops.yaml, rồi chỉnh sửa tệp bí mật bằng lệnh sops
- Ví dụ là chỉ định khóa công khai SSH làm người nhận
age cho đường dẫn secrets/*.yaml
- Khi chạy
sops secrets/shush.yaml, trình soạn thảo đã chọn sẽ mở ra và bạn có thể viết các giá trị YAML như hello: sops
- Khi thoát trình soạn thảo, giá trị sẽ được mã hóa thành dạng
ENC[AES256_GCM,...], và có thể chỉnh sửa lại bằng cùng lệnh đó
- Trong cấu hình NixOS, module
sops-nix xử lý hầu hết công việc
defaultSopsFile = ./secrets/shush.yaml; chỉ định tệp bí mật mặc định
age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; chỉ định khóa SSH của máy chủ
- Trong
secrets."hello", có thể chỉ định owner, group, mode để đặt quyền tệp
- Tại thời điểm kích hoạt,
sops-nix giải mã tệp bằng khóa SSH của máy chủ và đặt bản rõ vào /run/secrets/<name>
- Đường dẫn này nằm trên tmpfs, nên bí mật không chạm vào đĩa
- Dịch vụ cần giá trị chỉ việc đọc đường dẫn đó
- Tính năng template hữu ích trong cấu hình dùng chung hoặc cấu hình được người dùng khác tham chiếu
- Khi tệp cấu hình dịch vụ cần cả phần văn bản thuần lẫn một số bí mật, bạn không cần mã hóa toàn bộ tệp
- Ví dụ có thể để
SMTP_USER=isabel ở dạng văn bản thuần, rồi chèn chỗ giữ bí mật như SMTP_PASSWORD=${config.sops.placeholder."mailserver/smtp_password"}
agenix
- agenix, khác với
sops-nix, cấu hình bí mật và các khóa có quyền truy cập trong secrets.nix, nên mang lại cảm giác gần với Nix hơn
- Trong
secrets.nix, bạn gán các khóa SSH công khai của người dùng và máy chủ, rồi chỉ định khóa công khai nào có thể truy cập từng tệp .age
- Ví dụ, có thể đặt
"secret1.age".publicKeys = [ isabel host1 ];, "secret2.age".publicKeys = [ isabel host2 ]; để mỗi bí mật có danh sách người nhận khác nhau
- Tệp bí mật phải được tạo bằng CLI của
agenix
- Có thể tạo
secret1.age hoặc chỉnh sửa lại sau này bằng lệnh agenix -e secret1.age
- Cách nối vào cấu hình máy chủ tương tự
sops-nix, nhưng vì mỗi bí mật là một tệp riêng nên bề mặt hiển lộ nhỏ hơn
age.secrets.secret1.file = ./secrets/secret1.age; chỉ định tệp
- Có thể dùng
owner, group, mode để đặt chủ sở hữu và quyền
- Khi khởi động, mỗi tệp
.age được giải mã bằng khóa SSH của máy chủ và đặt vào /run/agenix/<name>
- Đường dẫn này cũng nằm trên tmpfs
- Điểm hay gây vướng nhất là rekeying
- Khi thêm máy chủ mới hoặc thay khóa, bạn phải mã hóa lại mọi bí mật có danh sách
publicKeys thay đổi trong secrets.nix
agenix --rekey xử lý việc này, nhưng để đọc bản mã hiện có thì cần khóa riêng của một trong các người nhận hiện tại
- Trên thực tế, việc rekey thường được thực hiện trên máy bạn tin cậy nhất, chứ không phải trên máy chủ mới định đưa lên
Cách chỉ dùng hệ thống tệp
- Cách đặt bí mật trực tiếp trên hệ thống tệp phải trả giá bằng việc cấu hình không còn mô tả máy một cách hoàn chỉnh nữa
- Khi cài lại, bạn phải đặt lại tất cả tệp vào đúng vị trí và đúng quyền sở hữu
- Trong các tình huống khôi phục như sửa máy chủ lúc 2 giờ sáng, điều này có thể trở thành thảm họa lớn
- Mẫu cần tránh là dạng như
builtins.readFile "/var/lib/myservice/token"
- Cách này đọc tệp tại thời điểm đánh giá và đưa nội dung vào Nix store
- Vì Nix store ai cũng đọc được, nó trở thành đúng kiểu thất bại đã cảnh báo lúc đầu
- Thay vào đó, với dịch vụ bạn nên truyền đường dẫn chứ không phải chính giá trị
- Với một máy chủ đơn lẻ hoặc laptop thì cách này có thể ổn, nhưng nếu là cả một fleet hoặc môi trường muốn dựng lại hoàn toàn chỉ từ cấu hình thì
sops-nix hoặc agenix phù hợp hơn
- Nếu trên mỗi máy chỉ có một hai giá trị thực sự không nên đưa vào kho lưu trữ thì cách này vẫn chấp nhận được, nhưng trách nhiệm chèn lại chúng sau này sẽ chuyển cho chính bạn trong tương lai
So sánh sops-nix và agenix
- Lý do chính để chọn
sops-nix là có thể gom càng nhiều dữ liệu càng tốt vào một tệp
- Với trường hợp có nhiều bí mật liên quan như mail server, bạn có thể giữ nhiều bí mật hơn trong một tệp thay vì chia thành khoảng 5 tệp như
agenix
- Đây là công cụ mạnh, phù hợp để tiếp tục dùng lâu dài, và đáng để ưu tiên trước trên những máy chủ có rất nhiều bí mật như mail server
agenix mạnh ở sự đơn giản
- Không có schema YAML phải học
- Không có
.sops.yaml cần đồng bộ
secrets.nix chỉ đơn thuần là Nix, nên có thể dùng lại nguyên các binding let ... in vốn dùng cho máy chủ và người dùng cả với khóa
- Mô hình tư duy là “một bí mật, một tệp, một danh sách người nhận”, rất khớp với cách kiểm soát truy cập
- Đây là lựa chọn có ít bộ phận chuyển động nhất mà vẫn cung cấp kiểm soát truy cập khóa theo từng máy chủ, nên rất phù hợp để khuyên cho người lần đầu hỏi về quản lý bí mật trên máy NixOS
- Cả hai công cụ đều giải quyết được bài toán; khác biệt hiện tại phần lớn nghiêng về tính tiện dụng
- Nếu mới bắt đầu và có nhiều dịch vụ cần chung các nhóm bí mật liên quan,
sops-nix sẽ mở rộng tốt hơn
- Nếu mới bắt đầu và chủ yếu chỉ có vài token độc lập,
agenix sẽ giúp đạt mục tiêu với ít bước hơn
- Nếu đang chọn công cụ bí mật đầu tiên, nên làm quen luồng làm việc với
agenix trước, rồi khi thực sự cảm thấy bất tiện với cách “một bí mật một tệp” thì chuyển sang sops-nix
- Phần liên quan đến khả năng chống lượng tử đã được đính chính
age và sops hỗ trợ các khóa mã hóa an toàn trước lượng tử
- age#578 đã được đóng và v1.3.0 đã phát hành
- Khi tạo khóa
age, chỉ cần thêm -pq; ví dụ: age-keygen -pq -o key.txt
1 bình luận
Ý kiến trên Lobste.rs
Chẳng phải cả bí mật đã mã hóa lẫn khóa của nó đều nằm trên đĩa sao? Hay một trong hai được lưu ở đâu đó như TPM?
Tôi mới bắt đầu dùng Nix, và với các triển khai tự host nhỏ thì đang dùng cách đơn giản là chép vào filesystem bằng
scpTìm thêm một chút thì có vẻ có thể bảo vệ khóa riêng SSH bằng TPM, và tôi cũng tự hỏi liệu VM có làm được không, nhưng thấy có thể có hỗ trợ vTPM nên coi như tự tìm ra câu trả lời rồi
Còn phía máy chủ thì cũng có thể dùng NixOps. Bạn có thể xem cách Colmena làm: https://colmena.cli.rs/0.4/features/keys.html
Ý chính là một máy đáng tin cậy đang giữ bí mật sẽ đẩy chúng sang máy chủ từ xa. Tương tự như việc bạn đang làm với
scp, nhưng vận hành quy trình đó theo kiểu Nix hơnTôi vừa dành mấy đêm gần đây để thiết lập lại hệ agenix cho flake hệ thống của mình, nên chỉ có thể nói về agenix. Với ai quan tâm thì tôi chọn agenix-rekey, vì không cần phải giữ các file
.ymlchứa bí mật và có thể cấu hình toàn bộ bí mật ngay trong Nix như tôi vốn đã làmBí mật đã mã hóa nằm trong Nix store, và giống như mọi thứ khác trong Nix store, chúng có thể được đọc công khai trên toàn hệ thống. Khóa riêng SSH để giải mã chúng thường là khóa riêng của chính máy chủ SSH thật, dù cũng có thể không làm vậy. Bí mật được giải mã vào lúc kích hoạt, đại khái là khi khởi động, rồi đặt tại
/run/agenix/<user>Công cụ secrix còn đi xa hơn khi gắn bí mật vào các dịch vụ systemd, rồi lại gắn các dịch vụ đó vào những dịch vụ cần bí mật. Vì thế bí mật chỉ được giải mã khi dịch vụ tương ứng đang chạy. Tuy nhiên trên thực tế, người dùng NixOS hiếm khi bật tắt dịch vụ thường xuyên, nên điều đó thường vẫn có nghĩa là chúng cứ chạy mãi. Nó có thể phù hợp với các bí mật dùng cho kích hoạt hệ thống như tạo người dùng
agenix-rekey giúp việc rekey bớt phiền toái hơn, và thay
secrets.nixbằng đầu ra của flake. Nó dùng ID tách đôi của YubiKey cho một nửa của khóa. Việc rekey là quá trình dùng khóa đó cùng với nửa còn lại để xác thực, giải mã bí mật, rồi mã hóa khóa lại bằng khóa công khai SSH của máy chủ. Khóa công khai được tạo tại thời điểm cài hệ thống, và tôi dùng--copy-host-keysvới nixos-anywhere để lấy các khóa được tạo trong installation closure. Tôi để các bí mật đã mã hóa trong repository, nhưng trong một submodule riêng mà chỉ các builder đáng tin cậy mới truy cập đượcNhân tiện, vTPM thường không dựa trên phần cứng, và nhiều nhà cung cấp dù có cung cấp TPM thì phần lớn cũng chỉ là TPM v1.2 chứ không phải TPM v2. Nhà cung cấp của tôi là BinaryLane cũng vậy. Đúng là nó thêm một lớp bảo mật nữa, nhưng nó không phải kiểu HSM thần kỳ như TPM thật, và cũng không bảo vệ được bạn khỏi việc nhà cung cấp hay node host bị xâm nhập. Nếu muốn cho phép vTPM dựa trên HSM thật thì có lẽ chi phí với nhà cung cấp sẽ rất lớn, còn AWS chắc là có cung cấp theo đúng kiểu giá AWS
agenix+agenix-rekey+age-plugin-1pKhóa master nằm trong 1Password, nên tôi có thể chỉnh sửa, xem và rekey mật khẩu của bất kỳ máy chủ nào mà không cần lưu bất kỳ thông tin xác thực nào trên đĩa laptop
Tôi có thể cấp quyền cho các máy chủ cần truy cập khóa khi đang chạy. Chỉ cần nói với agenix-rekey máy chủ nào được xem khóa nào rồi chạy
agenix rekey, một phiên bản khóa đã mã hóa mà máy chủ đó có thể giải mã sẽ được ghi vào Nix store. Khóa riêng SSH của máy chủ đó chỉ nằm trên chính máy chủ đó và không bao giờ rời ra ngoài. agenix-rekey chỉ cần khóa công khai để rekeyVì vậy các trường hợp bí mật bị lộ sẽ là tài khoản 1Password của tôi bị hack, hoặc máy chủ đang dùng bí mật đó bị hack
/etc/ssh/ssh_host_ed25519_key, rồi đặt vào ramfs được mount tại/run/agenix.dNên đúng vậy. Nội dung đã mã hóa, khóa mã hóa và nội dung đã giải mã đều có thể được truy cập từ filesystem
https://github.com/oddlama/agenix-rekey
Hơn nữa, số thông tin xác thực tồn tại lâu dài cũng đang ngày càng ít đi. Tôi đang rời xa việc sao chép thông tin xác thực dài hạn để chuyển sang thông tin xác thực dựa trên phần cứng, dùng trực tiếp chúng hoặc đổi chúng lấy thông tin xác thực sống ngắn hơn