Project

General

Profile

Actions

Securing Sensitive Credentials in Redmine using Rails Encrypted Credentials

Managing sensitive information such as database credentials securely is crucial for any Redmine installation. This guide walks through the process of securing database passwords by leveraging the encrypted credentials feature in Rails.

Starting with Rails 5.2, sensitive data (like API keys, database passwords, etc.) can be stored in an encrypted format, ensuring that only your Redmine instance with access to the decryption key can read it.

Steps for Securing Credentials

Generate the Master Key
When you use Rails credentials for the first time, Rails will generate a master key. This key is critical to encrypt and decrypt your credentials. Run the following commands to edit the encrypted credentials file:

sudo su - redmine # Login on your SSH prompt as the Redmine user
cd /var/www/redmine/  # Change to the Redmine home directory
EDITOR="nano" bundle exec rails credentials:edit  # Start editing the credentials file using your favorite editor: nano

Add your database credentials inside the encrypted credentials file:

db:
  username: redmine
  password: super_secure_password

Securely Store the Master Key

The config/master.key file must be stored securely and excluded from your version control system.
Ensure it is added to .gitignore. Only environments that need to read the encrypted credentials should have access to the master key.
This step is already partialy taken care of by the previous rails credentials:edit command.

   echo 'config/master.key' >> .gitignore
   echo 'config/credentials.yml.enc' >> .gitignore

Verify config/credentials.yml.enc and onfig/master.key ownership and permissions.

Modify database.yml to Reference Encrypted Credentials

Now, reference your encrypted credentials in config/database.yml:

production:
  adapter: postgresql
  database: redmine
  host: db01.int.geoxyz.eu
  username: <%= Rails.application.credentials.dig(:db, :username) %>
  password: <%= Rails.application.credentials.dig(:db, :password) %>
  sslmode: require
  encoding: utf8
  schema_search_path: public
  pool: 20

This approach ensures that your database passwords are stored securely and can only be decrypted by systems with access to the master.key.

Patching the Gemfile

Refer to the Redmine Gemfile patch below that resolves issues when parsing the database.yml file using ERB: #41331

Index: Gemfile
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/Gemfile b/Gemfile
--- a/Gemfile    (revision 277728afc979a7123eef8d1a8ac54d74c235c5fc)
+++ b/Gemfile    (date 1727590462090)
@@ -61,7 +61,7 @@
 require 'yaml'
 database_file = File.join(File.dirname(__FILE__), "config/database.yml")
 if File.exist?(database_file)
-  yaml_config = ERB.new(IO.read(database_file)).result
+  yaml_config = ERB.new(IO.readlines(database_file).reject { |line| line =~ /<%.*%>/ }.join).result
   database_config = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(yaml_config) : YAML.load(yaml_config)
   adapters = database_config.values.filter_map {|c| c['adapter']}.uniq
   if adapters.any?

Updated by Jan Catrysse 3 months ago · 1 revisions