I updated my Rails app from 5.1.6 to 5.2.1 and we were using secrets before. We'd like to switch to credentials since it was supposed to replace secrets. There are a couple of things I'm wondering:
1) Is there a "Railsy" way to do this? I'm aware I can just edit the secrets and copy the contents over to the credentials but I'm not sure if that's the right way to do it since I couldn't find anything that talks about this. Also, I tried copy the encrypted content from secrets.yml.enc and paste it to credentials.yml.enc but that didn't work, ran into some issues with the encryption.
2) Related to the first point, am I supposed to still be able to use secrets in 5.2.1? I thought credentials was supposed to replace secrets so I was surprised I could still use secrets and all my tests are passing.
Thanks for any info or help on this!
Backup your config/secrets.yml. Scaffold a temporary vanilla Rails 5.2.1 project via rails new. Copy config/master.key and config/credentials.yml.enc from it to your existing Rails project. Edit these credentials e.g in Ubuntu via:
EDITOR="gedit --wait" bin/rails credentials:edit
Replace the secret_key_base (new flat format prefered, optional for all environments) from the old secrets.yml and / or paste whatever else you need as a secret into it and save it. Delete config/secrets.yml and the temporary Rails project. Access the secrets in your code e.g. via:
Rails.application.credentials.secret_key_base
Ensure that your upgraded Rails 5.1.6 project use the master key in config/environments/*.rb:
Rails.application.configure do
...
config.require_master_key = true
...
end
Restart the Rails server. Do'nt forget to .gitignore and .dockerignore the config/master.key!
Related
I am encoding and decoding JSON web tokens using Rails secret_key_base, my secret_key_base is in the credentials.yml.enc file. In one of the test, I am using this function to decode JWT,locally the tests are running fine but on github action it is failing, I found out the the value of Rails.application.crendentials.secret_key_base is nil when running the test on github action. I fixed those tests by mocking like this
allow(Rails.application.credentials).to receive(:secret_key_base).
and_return("secret")
Is there a way I don't have to do this on github action for other credentials. Also since the master.key was not committed I hoped that I would see this error
ActiveSupport::MessageEncryptor::InvalidMessage
while reading from the credentials file but that also didn't happen.
This is a link to my project if that clears things up.
In Rails 6, you can create credentials.yml.enc file per environment.
In vscode:
EDITOR="code --wait" rails credentials:edit --environment production
EDITOR="code --wait" rails credentials:edit --environment test
it gives you production.key, production.yml.enc, test.key, test.yml.enc.
You can then commit test.key to github for testing or even better, set this key in RAILS_TEST_KEY env.
Though it gets a little bit tricky to maintain both env files. You can create credenetials.yml.example file with empty envs for reference
I think 'the cleanest/right way' to do this is to add master key(value from config/master.key) into github secrets.
Go to repository settings->secrets(left side menu)->new repository secret.
It makes sense to name it RAILS_MASTER_KEY.
And then in your workflow file add
env:
RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
And that's it, Rails will be smart enough to use that variable in credentials decryption.
No need to make additional credentials files. For me it's working with only one credentials.yml.enc
EDIT: Even better, if you can skip using credentials, add heroku config variable SECRET_KEY_BASE and in config/application.rb add
config.secret_key_base = ENV['SECRET_KEY_BASE']
and for production use Rails.configuration.secret_key_base,
for test/development Rails.application.secrest.secret_key_base that's set by rails
ex.
SECRET_KEY = Rails.env.production? ? Rails.configuration.secret_key_base : Rails.application.secrets.secret_key_base
This way you don't have to store master key on every machine that's running your app. ex. coworkers, github actions, staging, production.
I'm am working as a part of a team for a school project. We are using Ruby 2.6.5 and Rails 6.0.2.1. I have pulled the master branch from GitHub, but when I try to run the application I get this error:
ArgumentError: Missing secret_key_base for 'production' environment
I have looked online and found that the old solution was to change the config/secrets.yml file, but rails 6 no longer has that file, and instead has an encoded credentials.yml.enc file that has the same functionality. How do I fix this issue?
Rails > 5.2 introduced a new feature for securing credentials. For this rails uses a master.key in config folder which is usually added to .gitignore so that it stays secure and doesn't get pushed to git.
This master.key is used to encrypt or decrypt content from the credentials.yml.enc file which you found.
If you are working on a team then the project creator will have to share this master.key file to you personally or you have to create a new credentials.yml.enc. You can do it using the below command -
EDITOR=vim rails credentials:edit
This will create a new master.key and credentials.yml.enc in your machine but the changes made by your teammates in the credentials.yml.enc will be lost. To avoid that hassle just get the master.key from your teammate and put it in the config. folder.
You can try changing the config.require_master_key = true #in config/environments/production.rb
You can go to this link to check this in detail:- https://blog.engineyard.com/rails-encrypted-credentials-on-rails-5.2
I hope this will work for you.
This topic has a SOLUTION embeded at the end.
PROBLEM
I'm deploying for the first time a Rails app on a VPS on Ubuntu 18.04. with Nginx.
I followed the good tutorial of Gorails "Deploy Ruby on Rails To Production in 2019".
Everything worked, until I had the "Incomplete response received from application" page.
I checked the nginx logs on /var/log/nginx/error.logand saw the typical message "Missing secret_key_base for 'production' environment, set this string with rails credentials:edit"
As the method of Gorails didn't seems to work (after a bundle exec rails secret on his console app-side, he add a file /my_website/.rbenv-vars with a SECRET_KEY_BASE line, filled with the generated secret key), I decided to follow the multiples topics answering to this question.
Here is the thing, I'm not sure if the followings steps are the goods one.
I run bundle exec rails secreton my console, server-side, as deploy user. So I have my GENERATED_KEY_1
I add to ~/.bashrc : export SECRET_KEY_BASE="GENERATED_KEY_1"
I source ~/.bashrc
I check my key with echo $SECRET_KEY_BASE, and I have the good key displayed (GENERATED_KEY_1)
I edited my credential file as
development:
secret_key_base: ORIGINAL_KEY
test:
secret_key_base: ORIGINAL_KEY
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
and added Dotenv to my Gemfile, required it in application.rb
But none of this worked, after restarted nginx server.
So I restarted the previous step, with the root-user.
But again, it failed.
My questions are:
what I am missing ?
How can I know, if it's searching the key in the good place, as I have always the same error message ?
Which key am I suppose to generate ? App-side ? Server-side ? As root or deploy user ?
Do I have something else to configure in /etc/nginx/sites-available/default ? (I saw on this topic that this guys changed a rails_env production; to rails_env development; but I haven't any rails line)
Thank you, I'm a little bit desperate ^^
SOLUTION
During my many tests, I logged with the root user, and run EDITOR="vim" rails credentials:edit. This command had generated a master.key, which doesn't exist on your Github repo.
But first, I didn't modified it. I think that was the main problem, as the application use it to decrypt your credentials.yml.enc file. When I understood it, I edited the master.key with the content of the master.key on my computer app.
Even after editing credentials.yml.encwith <%= ENV["SECRET_KEY_BASE"] %>, this solution works. This corresponds to the answer of Lyzard Kyng, even if it's a bit different.
I can't run EDITOR="vim" rails credentials:editwith the deploy user, it doesn't work.
Rails 5.2 and later uses encrypted credentials for storing sensitive app's information, which includes secret_key_base by default. These credentials are encrypted with the key stored in master.key file. Git repository, generated by default Rails application setup, includes credentials.yml.enc but ignores master.key. After the deployment, which usually involves git push, Rails production environment should be augmented with this key some way.
So you have two options. You can securely upload master.key to production host via scp or sftp. Or you can establish shell environment variable RAILS_MASTER_KEY within the context of a user that runs rails server process. The former option is preferred, but as you have dotenv-rails gem installed, you'd create .env.production file under app's root and put there a line
RAILS_MASTER_KEY="your_master-key_content"
Don't forget to ensure that gem dotenv-rails isn't restricted within Gemfile by development and test Rails environments.
By the way since passenger module ver. 5.0.0 you can set shell environment variables right from nginx.conf
run rake secret in your local machine and this will generate a key for you
make config/secrets.yml file
add the generated secret key here
production:
secret_key_base: asdja1234sdbjah1234sdbjhasdbj1234ahds…
and redeploy the application after commiting
i had the same issue and resolved by this method.
It would be more secure to generate your key on the server and use it there, rather than push it to your repo from a local machine.
Instead of ~/.bashrc do this for using environment variables;
As root user, navigate to the # directory (can probably just use cd ..)
Enter nano home/<yourAppUser>/.bash_profile to navigate to (and create) the file to store the ENV
As you have already, just write this in the file: export SECRET_KEY_BASE="GENERATED_KEY_1"
You can store your database password here as well.
1_ Set credentials with
rails credentials:edit
2_ Upload master.key file to your production server.
If deploy with capistrano, copy master.key to shared folder (shared_path) and then add this to deploy.rb:
namespace :config do
task :symlink do
on roles(:app) do
execute :ln, "-s #{shared_path}/master.key #{release_path}/config/master.key"
end
end
end
after 'deploy:symlink:shared', 'config:symlink'
In my case, on rails credentials:edit, the file indentation were not accurate which gave the error on deployment. So make sure the indentation is correct on your local before deploying.
I've just created a new Rails project, and it came with this credentials.yml.enc file.
Is it safe to commit it publicly?
What David Heinemeier Hansson said here:
These secrets are not supposed to withstand any sort of attack in test or development.
As far I understood you should not keep damn secret credentials here, and then it's good to publish in public.
It's only in production (and derivative environments, like exposed betas) where the secret actually needs to be secret. So we can simply insert this secret into the new flat credentials.yml.enc file.
And at the end he mentioned:
Note: We should just keep Rails.secrets and friends around. The Rails.credentials setup would be a new, concurrent approach. All new apps would use it, but we wouldn't need to screw existing apps.
Hope it would help. For more, follow this.
I finally understood it.
Read this https://blog.saeloun.com/2019/10/10/rails-6-adds-support-for-multi-environment-credentials.html first.
For test and development env, you can simply remove the master.key and you will find that rails s works well.
You can run rails console, then run Rails.application.credentials.config to see that the value.
But if you have a wrong master.key there and run rails s, you will get an error.
But if you removed master.key, you will find that rails s -e production doesn't work.
If you have the correct value of master.key, you can run EDITOR=vim rails credentials:edit to edit it.
If you don't have the correct value of master.key, when you run EDITOR=vim rails credentials:edit,
it will generate a new master.key for you but unfortunately that master.key is a wrong one.
This is reasonable because it makes the credentials.yml.enc unable to be decrypt unless you have already got a correct master.key.
So you can remove the credentials.yml.enc and master.key and run EDITOR=vim rails credentials:edit to generate a new pair.
But before you do that, you should remove master.key and run rails console, then run Rails.application.credentials.config to
understand what values you need to set when running EDITOR=vim rails credentials:edit.
All the Rails instance in production env should have the same credentials.yml.enc and master.key.
So you should keep credentials.yml.enc in your sources code.
credentials.yml.enc why not? This is encrypted file and it doesn't have any information without a key.
But master.key you must keep in secret!!! It may decrypt your file.
You can push the credentials.yml.enc file to production. Just remove the master.key. They are meant to be pushed to production. However, if you are skeptical about this then save it to some local server, and when you are deploying make code to pull the file and master.key. This can be done using Capistrano tasks if you prefer this.
When installing Figaro gem, an application.yml is automatically created. And inside this file I planned on storing login credentials for SendGrid.
But by default in the rails application, there is another secrets.yml file, with the secret_key_base.
I'm little confused on their relationship.
My question: Is it necessary to have both? Can I combine them? Should both be added to gitignore ?
You can leave it there as it is, just put the new variables to the application.yml and make sure you gitignore both files since you need those only for localhost. For production you have to put the keys to a different place based on the service. I'm using heroku and have to save production variables from terminal.