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