1 điểm bởi GN⁺ 3 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • 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
    • agesops 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
  • Tôi đã thấy giải thích rằng sops-nix và agenix không lưu bí mật đã giải mã xuống đĩa, nhưng vẫn thắc mắc lợi ích thực tế của điều đó là gì
    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 scp
    Tì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
    • Trên máy chủ của tôi thì tôi dùng sops-nix, và theo mô hình đe dọa của tôi thì nó là đủ và hoạt động tốt. Giờ tôi lại tò mò về cách lưu khóa riêng SSH trong TPM
      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ơn
    • Đến lúc lôi câu cửa miệng yêu thích ra rồi đây. “Còn tùy tình huống!” Quản lý bí mật ở đây xử lý đồng thời hai vấn đề: bảo vệ các file bí mật trên đĩa, và bảo vệ các bí mật nằm trong cấu hình dùng để build hệ thống. Rốt cuộc thì các giá trị đó phải tồn tại ở đâu đó
      Tô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 .yml chứ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àm
      Bí 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.nix bằ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-keys vớ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 được
      Nhâ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
    • Tôi dùng agenix + agenix-rekey + age-plugin-1p
      Khó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 để rekey
      Vì 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
    • Trong Agenix, theo mặc định, bí mật đã mã hóa được giải mã bằng /etc/ssh/ssh_host_ed25519_key, rồi đặt vào ramfs được mount tại /run/agenix.d
      Nê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
    • Làm vậy cũng cho phép chia sẻ toàn bộ cấu hình NixOS của bạn ở chế độ công khai. Không nhiều người làm vậy, nhưng tôi thấy một nửa lời hứa của Nix là người khác cũng có thể cùng debug vấn đề hệ thống của tôi
  • Tôi vẫn mới chỉ nghĩ đến chuyện thử agenix và agenix-rekey. Có vẻ chúng sẽ giảm khá nhiều những điểm đau mà nhiều người nhắc tới, nhưng tôi vẫn chưa thử
    https://github.com/oddlama/agenix-rekey
  • Tôi từng quản lý thông tin xác thực bằng agenix, nhưng rồi chuyển sang cách cứ để chúng trên filesystem. Đơn giản hơn, và việc cài lại với tôi cũng hiếm khi xảy ra
    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