Trang chủ Rails credentials

Rails credentials

  • 2024 May 15
  • 5 minutes read

Mặc định, khi tạo một project, global credentials credentials.yml.enc sẽ được tạo cùng với file master.key, trong đó file credentials.yml.enc đã được mã hoá. Để decrypt được file này và đọc các key-value bí mật bên trong file, ta cần có file master.key để giải mã, hai files này chứa trong folder config.

Nếu file này chưa có và ta muốn setup lại file credentials mới hoàn toàn, ta chạy lệnh sau:

# Path mặc định khi tạo credential là config/(*.yml | *.key)
EDITOR=VIM rails credentials:edit
# Path mặc định khi tạo credential là config/credentials/(*.yml | *.key)
EDITOR=VIM rails credentials:edit [-e env]

VIM editor xuất hiện và ta có thể add các key-value bí mật vào file này. Để save file và thoát ra, ta gõ :wq

Ví dụ:

# aws:
#   access_key_id: 123
#   secret_access_key: 345

key_test: value_test
~
~
:wq

Để decrypt xem được file crendentials đang chứa những key value nào, ta chạy lệnh sau:

rails credentials:show [-e env]

Ngoài ra, ta cũng nên add secret_key_base vào credentials để project dùng key này để encypted session cookie hoặc encrypt thông qua MessageVerifiers của Rails

Để generate ra 1 secret key mới ta chạy lệnh sau:

rake secret
#>af7d26e4e959aac010f0a9cd9ca863123678cba089f5e98eb1b0cfd4276b9be892db749e06cee5aa9b472ba1ef9ae9cfa44d8021893539920d76936c2737775

Lệnh này generate chuỗi key ngẫu nhiên, chuỗi này chưa được sử dụng ở bất cứ đâu, ở bất cứ file nào.

Copy chuỗi key này và add vào credential vào môi trường mà mình muốn

# aws:
#   access_key_id: 123
#   secret_access_key: 345

secret_key_base: af7d26e4e959aac010f0a9cd9ca863123678cba089f5e98eb1b0cfd4276b9be892db749e06cee5aa9b472ba1ef9ae9cfa44d8021893539920d76936c2737775
~
~

Để tạo crendentials cho nhiều môi trường, ví dụ môi trường staging hay production, ta làm như sau:

EDITOR=VIM rails credentials:edit -e production

Mặc định, file credentials.yml.enc cùng master.key khi run lệnh trên cùng biến môi trường sẽ được tổ chức trong folder config/credentials/*, file master.key là bí mật không nên để public trên repository nên ta sẽ bỏ vào .gitignore (mặc định khi generate credentials file key đã được tự động thêm vào .gitignore)

Để thay đổi thư mục tổ chức file credentials mặc định, ta có thể config như sau:

# Có thể set trong config/application.rb 
# hoặc config/environments/#{Rails.env}.rb

config.credentials.content_path = Rails.root.join("config/secret_files")

config.credentials.key_path = Rails.root.join("config/secret_files")

Xét về độ ưu tiên dùng file, thì file cục bộ trong config/credentials/* sẽ có độ ưu tiên cao hơn global credentials config/*

 

Chú ý:

Với môi trường production, bình thường ta hay dùng biến môi trường ENV['RAILS_MASTER_KEY'], nếu tồn tại biến này thì rails sẽ dùng value của key này để decrypt credentials, như vậy ta ko cần file *.key nữa. Còn nếu không tồn tại biến môi trường, ta mới cần dùng file *.key này, để file có hiệu lực, ta cần config theo môi trường như sau:

# config/environments/production.rb
config.require_master_key = true

 

Bonus:

1) Khi deploy production dùng capistrano, ta nên thêm config symlink như sau:

# config/deploy.rb
append :linked_files, 'config/master.key', 'config/credentials/production.key', '.env'

 

2) Ta có thể kết hợp credentials với config yml để dễ dàng thấy các key có sẵn mà ko cần decrypt file, mà value vẫn secret gọi đến file encrypt.

# config/application.rb
config.secret = config_for(:secret)
# config/secret.yml
default: &default
  aws_s3:
    folder: <%= Rails.application.credentials.dig(:s3, :folder) %>
    bucket: <%= Rails.application.credentials.dig(:s3, :bucket) %>
    region: <%= Rails.application.credentials.dig(:s3, :region) %> 

development:
  <<: *default

staging:
  <<: *default

airport:
  <<: *default

station:
  <<: *default
  
test:
  <<: *default

production:
  <<: *default

Cách gọi value của key:

Rails.configuration.secret.aws_s3.folder

 

3) Một tip để xem key-value thay đổi trước khi khi commit lên repository. Ta có thể chạy lệnh sau:

bin/rails credentials:diff --enroll

Lệnh này sẽ add config vào file .gitattributes

# .gitattributes
config/credentials/*.yml.enc diff=rails_credentials
config/credentials.yml.enc diff=rails_credentials

Ta có thể add file này vào .gitignore để lần sau không cần gọi lại bin/rails credentials:diff --enroll nữa, mà chỉ cần gọi một lệnh duy nhất git diff thôi.

git diff

diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc
index d27cc9e..f9439db 100644
--- a/config/credentials.yml.enc
+++ b/config/credentials.yml.enc
@@ -5,3 +5,5 @@ aws:

+
+key: value

 

4) Nếu quá trình làm gặp lỗi này thì có thể nguyên nhân do không decrypt được credentials, cần check lại key decrypt.

ActiveSupport::MessageEncryptor::InvalidMessage 
OpenSSL::Cipher::CipherError

0 Comments