Why are rails development credentials gitignored by default? - ruby-on-rails

I'm generating credentials using the following command:
rails credentials:edit --environment development
I notice that rails puts this in the gitignore:
+/config/credentials/development.key
I dont understand why, based on the following reasons:
The development credential file is encrypted by default, hence harmless to check in as long as the master key isnt checked in.
It's essential for a fresh environment setup (eg. on a new dev environment)
If the original file is lost, all the data in the dev environment will have to be reseeded.
I'm inclined to check it in but figured, given Chesterton's fence and all, I'm likely missing something.

I figured it out. I was confused between the development.key and the config/credentials/development.yml.enc. The latter is the encrypted credential file.

Related

Rails credential values are nil while running tests on github actions

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.

Rails new credentials generate greater risk in case of master.key corruption?

Until now I was handling my app secrets the usual way :
In development: my secrets are stored unencrypted in my secrets.yml file. The secrets.yml file is not commited to Github and
stays on my computer.
As per AWS reccomendations I have roles that allow me to have development specific keys. This allows to restrain my development keys to certain functions that have a different scope than production keys.
In production: My keys are stored on Heroku and called like ENV["AWS_SES_KEY"] inconfig/environments/production.rb.
I quite liked it because in case my computer is stolen, the development keys which then become corrupt can be erased at AWS without having to touch the production keys. And because the development keys can be limited to a certain scope of actions at AWS, it prevents any dangerous alterations (full bucket erasing ...)
Now we have credentials, if I am not mistaken, all keys (development and production) are inside the same encrypted file. The master key is the only environment key that is now seeded to Heroku. Though I still need this key locally to access the credentials. Then if my computer is stolen both development and production keys are corrupt and can generate a higher risk for my production app.
Is there something I am missing on the new credentials feature ? any way to avoid the above issue ?
What would be great is still using secrets.yml for dev keys and credentials.yml.enc for production keys, is it how it is intended ?
As the release notes for Rails 5.2.0 states, the future intent is to replace secrets.yml and secrets.yml.enc with credentials.yml.enc:
This will eventually replace Rails.application.secrets and the encrypted secrets introduced in Rails 5.1.
There's a very clear sense that credentials.yml.enc is meant to contain production credentials only because the Rails recommendation is to not have environment specific keys in it; i.e.,
# don't do this
development:
# ...
production:
# ...
As for the config/master.key "corruption" risk, I'm not sure how to answer that. The master key is only required when running in production mode. You can also store the master key in the RAILS_MASTER_KEY environment variable. In development, you'd only need the master key if you wanted to edit credentials.yml.enc.

Is it safe to commit Rails' credentials.yml.enc file?

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.

Missing secret token, secret key base when running my application in production

I work with Rails 4 and Ruby 2.1 and sorry but I am working on Windows
I have read a lot about this topic "Missing secret token, secret key base" but actually I do not understang anything.
I do not use Heroku, Git, Puma, Passenger or everything else I've read. I just thought I could instead of running rails s as usual run rails s -e production and see what is the version of my web application in production.
But I have the error "Missing secret_token and secret_key_base for production environment, set these values in config/secrets.yml"
I read about solutions using openSSL, export SECRET_KEY_BASE=<the long string> but I do understand the solutions.
I thought it was a problem related to the system of connection by password I settled thanks to Rails tutorial of Micheal Hartl. So disabled SSL connection. But nothing change.
This is my config/secrets.yml :
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
Can someone explain how to concretely solve this issue ?
GDMN I am sorry that everyone gave you such poor explanations and instructions. Ok onto it then, shall we......
First everyone is right you no longer need "secret_token", you do however need "secret_key_base". What this does is it secures your visitors connection and keeps your system and app more secure. That is a simple explanation but all you need to worry about at the beginners level.
Second the ENV stands for "Environment Variable" they are used in all operating systems and they refer to variables on the OS level that hold information that you do not want to be accessible t someone trying to gain access to your site. For instance in Ruby On Rails if you HARD CODE the secrety_token_base string/hash then I hacker can gain access by using your security_token against you. I have seen this happen and it is not pretty, if the individual is skilled enough then they can gain access to even your root/admin account.
Now on to setting it all up. I only know the linux way and I know you are looking for the windows method but this should at least give you an understanding to seek out the information relevant to your operating system.
First thing you would need to do is generate your secret_token_base by running
bundle exec rake secret
To my knowlege this is the way you do it in all Operating Systems. After you run the above command the console will return a string and you would need to copy it. Once copied you would run the following command:
export SECRET_KEY_BASE=WhatYouJustCopied
Then we would check to make sure the Environment Variable SECRET_KEY_BASE is set by running:
env | grep -E "SECRET_TOKEN|SECRET_KEY_BASE"
If you do not have SECRET_TOKEN set you will only get the KEY_BASE.
If you want to learn more in depth information please visit this link it may be a little dated but most of it is still relevant and conceptually it is the same.
I wish you luck on your new found ROR Adventure! It is fun once you get the hang of it!
From your command prompt, run:
bundle exec rake secret
It will generate a long string of characters. Copy this string and paste it into config/secrets.yml as follows:
production:
secret_key_base: <paste the string here>
Note: only do this if you are not using a public repository. This key should not be accessible to anyone else. An alternate, and more secure way of doing this is using an environment variable. See this: http://daniel.fone.net.nz/blog/2013/05/20/a-better-way-to-manage-the-rails-secret-token/
So, if you look inside the secrets.yml file, you will see where your secret_key_base is set for each of your environments. When you look at the production setting, it wants an env variable to initialize your secret_key_base. Normally, in production, you would want your app server to fetch the value from a general place in case you need to spin multiple servers up, you wouldn't have to hard-code your secret_key_base everywhere since that is not a secure way of setting that variable.
Basically, you will have to have that env variable set up on the machine that will run your rails app in production. There are so many different ways to set this.
What I have set up to initialize my ENV variables for production is have a separate yml file that is constructed like this
# config/env_provider.yml
production:
SECRET_KEY_BASE: "KEY GOES HERE"
other_production_variables: #...etc
Then my separate servers will be told where to find this file before initializing the variables (This is not checked into version control). After the file is in place it will know to initialize the variables from the following code in environment.rb before your app initializes
#config/environment.rb
YAML.load_file("#{::Rails.root}/config/env_provider.yml")[::Rails.env].each {|k,v| ENV[k] = v }
# This is before Rails.application.initialize!
The thing with this set up is to make sure that you do not have this file accessible to everyone to see, only allow your application servers to use it. Anyway, this is how I deal with ENV variables and deploy them to production. I hope this helps you.

Does Rails 4.2 use secret_token?

Are both secret_key_base and secret_token needed for production in Rails 4.2? Setting neither causes the following exception message:
Missing secret_token and secret_key_base for 'production'
environment, set these values in config/secrets.yml
The 4.2 upgrade guide (http://railsapps.github.io/updating-rails.html) says this:
When you create a new Rails application using the rails new command, a
unique secret key is generated and written to the
config/initializers/secret_token.rb file.
But no such file was created when I generated my app, and there is no reference to secret_token in config/secrets.yml
I'm assuming that the error message is wrong, and that only secret_key_base is needed. When I run my app in production on my dev machine, it starts with just secret_key_base, but in Engineyard, setting secret_key_base (via an environment variable) isn't working. I still get the error.
The problem you're seeing on Engine Yard is because the secret_key_base environment variable doesn't (yet) exist by default. That's something we're working on. You can put that in place on your own using custom chef; I suggest talking to our support team for more info on that.
As for the actual error you're getting, I just tested a brand new Rails 4.2 app ("rails new foo") to see if it's generating secret_token.rb, which it's not. I think what you need here is to create config/secrets.yml, and that file should look like this:
development:
secret_key_base: somekey
test:
secret_key_base: someotherkey
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
Now, when you see ENV["SECRET_KEY_BASE"], that's where Engine Yard has a bit of a twist - we don't provide that out of the box yet. As long as your repo is private, you can hard-code something in there on your own. Otherwise, using custom chef could get you squared away by creating a secret key base and putting it in the wrapper script responsible for launching your app worker processes (so config/env.custom on our platform, for example).
Hope this helps.
4.2 does use the secret key and the link you posted has the solution you are looking for.
In an environment that doesn't end up with the secret key active, you need to generate it using rake secret then place the output from the console into your config/initializers/secret_token.rb file (you can make one if there isn't one).
You have the option to avoid using secrets.yml. Many people prefer to use another gem/procedure (e.g. figaro) for handling secret info. To simplify your life you could just put this information into the secret_token.rb file and move on - or you can learn the various other idiomatic ways of handling the situation.
At least Rails 4.2.2 gave me the same error, but setting the environment variable SECRET_KEY_BASE in the rails user's .bash_profile file solved the problem for me, so the bit about secret_token seems to be bogus -- a holdover from earlier versions, probably.
Generate the secret by commanding rake secret, then use the generated string in file .bash_profile like this:
export SECRET_KEY_BASE='the_output_of_the_rake_secret_command'
I'd suggest re-generating a new app with the latest version of Rails installed.
This file was auto-generated in my last project:
# config/secrets.yml
# Be sure to restart your server when you modify this file.
# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rake secret` to generate a secure secret key.
# Make sure the secrets in this file are kept private
# if you're sharing your code publicly.
development:
secret_key_base: fooooo
test:
secret_key_base: fooooo
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
I'd also recommend that you compare the generated files via the railsdiff site (example: http://railsdiff.org/4.1.10.rc2/4.2.1.rc2) as it sounds like you're upgrading from an older version.

Resources