Why is secret_key_base blank on Heroku (Rails 5.2) - ruby-on-rails

I deleted secrets.yml and created credentials.yml.enc.
Locally I am using master.key, and in production I don't have any master key, only a RAILS_MASTER_KEY set as an environment variable.
On Heroku, if I run Rails.application.secrets I get:
{:secret_key_base=>nil, :secret_token=>nil}
and if I run Rails.application.credentials I do in fact see my secret_key_base.
However, locally... if I run the same commands, I DO see secret_key_base when calling Rails.application.secrets.
My main concern is that rails is going to have an empty secret_key_base in production which would be used to encrypt sessions and all kinds of critically important security things. I'm trying to verify that it actually does have the key set.
I'd love a way to 100% confirm that it's working in production, and that it's not blank. Is there some method I can call to check which doesn't rely on calling it via the methods above?

The SECRET_KEY_BASE is stored as an environment variable on Heroku. You can either view these in the interface by going to the settings for that dyno or you can do it in the terminal:
heroku run bash
then
env | grep SECRET_KEY_BASE
If you do not see it there may be an issue but you can generate a new one for Heroku and set it in the environment variables (see Rails.application.key_generator)

Related

Moving to credentials.yml.enc from ENV on production

In our old rails app we used ENV['AUTH0_ID'] to manage environment variables.
In our new app we're using Rails.application.credentials.auth0[:AUTH0_ID]
But now in deploying, how do we provide Heroku with the environment variables?
Is it the case that we give Heroku the key we use to decrypt development.yml.enc (in our development env) and that will decrypt the yml?
If that's the case, whats the syntax for giving Heroku the development.key?

Heroku sets SECRET_KEY_BASE when it's not defined

I want Heroku to not set SECRET_KEY_BASE so I can use the one from credentials, but despite me deleting it from the UI, verifying it doesn't exist by running heroku config, I still get it set as an environment variable on my dynos. And it's the same in all the dynos:
SECRET_KEY_BASE=d2753b472abb...
I also tried setting it to a blank string by running heroku config:set SECRET_KEY_BASE="" and Heroku insist on setting it up as I can see by running bash and then env within bash.
How can I prevent that from happening?
Unfortunately, the Heroku Ruby buildpack generates and sets SECRET_KEY_BASE via the shell if it doesn't exist in your Heroku config vars.
It currently doesn't seem possible to directly use the secret key set in credentials.yml. You could make credentials.yml and SECRET_KEY_BASE align though.
Source: https://github.com/heroku/heroku-buildpack-ruby/issues/1143
And here is a short extract from that issue:
If you set your own SECRET_KEY_BASE, we do nothing.
If you do not set a SECRET_KEY_BASE we generate and set one for you.
We recommend using our heroku config interface for storing secrets rather than using the encrypted file storage that ships with rails.
If you want to use encrypted file storage locally with rails you could copy our secret key base heroku run echo $SECRET_KEY_BASE or you can set your own
value manually locally and then again via heroku config.

"Missing `secret_key_base` for 'production' environment" error on Heroku

I received the error "An unhandled lowlevel error occurred" when deploying my app for the first time on Heroku, and heroku logs shows:
Missing secret_key_base for 'production' environment, set this value
in config/secrets.yml
1) The default secrets.yml specifies secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> for production
2) I generated a secret using rails secret, then added this to my app's Heroku config via heroku config:set SECRET_KEY_BASE='(the key)'
3) heroku config shows this value set for SECRET_KEY_BASE
4) Perhaps most importantly, based on older questions regarding this error, .gitignore does not include secrets.yml--it's the default .gitignore generated for a Rails 5 app. Therefore, secrets.yml should have been deployed with my app, which specifies that the secret be loaded via an environment variable in the production environment.
5) I've also run heroku ps:restart, in case the app needed some extra help for the environment variable setting to take effect
I read older posts, but the past answer seemed to be ensuring secrets.yml was not included in .gitignore, but as mentioned, this does not apply to the default Rails 5 .gitignore.
What else can I try? Thx.
Edit: When I set the config value at the command line, I also receive the Heroku message:
Setting SECRET_KEY_BASE and restarting (the app)... done
Okay, I see what happened. Running heroku run bash and checking which files were deployed has been enlightening.
It is true that secrets.yml was not in the .gitignore file for my local repo, but it seems that someone--possibly malicious hackers, possibly gremlins--had added secrets.yml to my global .gitignore (.gitignore_global), and so this file was in fact not being pushed to Heroku.
I've removed the secrets file from my global .gitignore, offloaded the dev and test environment secret keys to dotenv for management, and can run my deployed app successfully.
I thought about deleting the question, but will leave it in case others run into this problem, or even a similar one where using heroku run bash may be helpful when diagnosing issues with apps on Heroku.

getting error on production related to config.yml

I am trying to push a app on heroku, Its gets pushed but none of my assets gets uploaded on heroku.
Its works all good locally. So I check with rails s -e --production and It gives me error in secrets.yml
It says
Missing secret_token and secret_key_base for '--production' environment, set these values in config/secrets.yml
I am not sure what It is. Please help..
I believe that for a heroku app to run in production Rails expects the secret configuration to exist. Remove the line within your .gitignore that prevents secrets.yml from updating within version control and then make sure you use ENV variables for your secret tokens. If you don't have any secret tokens that aren't just tests then you shouldn't have to worry about it, but if you do you can use gems like figaro to configure your Environment variables that will keep your tokens off VCM.
Edit: If you look within your config directory you should see a secrets.yml that was generated with your app. Within the app you should see your secret_key_base variables within dev, test, and production. Within production though you should have:
# Do not keep production secrets in the repository,
# instead read values from the environment.
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> <- This being your Environment variable

Rails Production - How to set Secret Key Base?

So I am trying to get my rails app to deploy in production mode, but I get the error: Missing secret_token and secret_key_base for 'production' environment, set these values in config/secrets.yml
My secrets.yml file is as expected:
development:
secret_key_base: xxxxxxx
test:
secret_key_base: xxxxxxx
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
But even after google and research, I have no idea what to do with the production secret key base. Most of the info out there assumes I have certain background knowledge, but the reality is that I'm a noob.
Can anyone explain to me how to set my secret key and get this to work in production mode?
You can generate the key by using following commands
$ irb
>> require 'securerandom'
=> true
>> SecureRandom.hex(64)
=> "3fe397575565365108556c3e5549f139e8078a8ec8fd2675a83de96289b30550a266ac04488d7086322efbe573738e7b3ae005b2e3d9afd718aa337fa5e329cf"
>> exit
The errors you are getting just indicate that the environment variable for secret_key_base are not properly set on the server.
You can use various scripts like capistrano that automate the process of setting these before the application is run.
As for a quick fix try this:
export SECRET_KEY_BASE=YOUR SECRET BASE
Validate the environment variables and check if these have been set.
Command:
env | grep -E "SECRET_TOKEN|SECRET_KEY_BASE"
If your values pop up then these are set on the production server.
Also it is best practice to use ENV.fetch(SECRET_KEY) as this will raise an exception before the app even tries to start.
This answer helped me a lot. He indicates you how to config the secrets.yml file in production and how to read it from the environment:
original link:
https://stackoverflow.com/a/26172408/4962760
I had the same problem and I solved it by creating an environment
variable to be loaded every time that I logged in to the production
server and made a mini guide of the steps to configure it:
https://gist.github.com/pablosalgadom/4d75f30517edc6230a67
I was using Rails 4.1 with Unicorn v4.8.2, when I tried to deploy my
app it didn't start properly and in the unicorn.log file I found this
error message:
"app error: Missing secret_key_base for 'production' environment, set
this value in config/secrets.yml (RuntimeError)"
After some research I found out that Rails 4.1 changed the way to
manage the secret_key, so if you read the secrets.yml file located at
[exampleRailsProject]/config/secrets.yml you'll find something like
this:
Do not keep production secrets in the repository,
instead read values from the environment. production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> This means that rails
recommends you to use an environment variable for the secret_key_base
in your production server, in order to solve this error you should
follow this steps to create an environment variable for Linux (in my
case Ubuntu) in your production server:
1.- In the terminal of your production server execute the next command:
$ RAILS_ENV=production rake secret This returns a large string with
letters and numbers, copy that (we will refer to that code as
GENERATED_CODE).
2.1- Login as root user to your server, find this file and edit it: $ vi /etc/profile
Go to the bottom of the file ("SHIFT + G" for capital G in VI)
Write your environment variable with the GENERATED_CODE (Press "i" key
to write in VI), be sure to be in a new line at the end of the file:
export SECRET_KEY_BASE=GENERATED_CODE Save the changes and close the
file (we push "ESC" key and then write ":x" and "ENTER" key for save
and exit in VI)
2.2 But if you login as normal user, lets call it example_user for this gist, you will need to find one of this other files:
$ vi ~/.bash_profile $ vi ~/.bash_login $ vi ~/.profile These files
are in order of importance, that means that if you have the first
file, then you wouldn't need to write in the others. So if you found
this 2 files in your directory "~/.bash_profile" and "~/.profile" you
only will have to write in the first one "~/.bash_profile", because
Linux will read only this one and the other will be ignored.
Then we go to the bottom of the file ("SHIFT + G" for capital G in VI)
And we will write our environment variable with our GENERATED_CODE
(Press "i" key to write in VI), be sure to be in a new line at the end
of the file:
export SECRET_KEY_BASE=GENERATED_CODE Having written the code, save
the changes and close the file (we push "ESC" key and then write ":x"
and "ENTER" key for save and exit in VI)
3.- You can verify that our environment variable is properly set in Linux with this command:
$ printenv | grep SECRET_KEY_BASE or with:
$ echo $SECRET_KEY_BASE When you execute this command, if everything
went ok, it will show you the GENERATED_CODE from before. Finally with
all the configuration done you should be able to deploy without
problems your Rails app with Unicorn or other.
When you close your shell terminal and login again to the production
server you will have this environment variable set and ready to use
it.
And thats it!! I hope this mini guide help you to solve this error.
Disclaimer: I'm not a Linux or Rails guru, so if you find something
wrong or any error I will be glad to fix it!
nowadays (rails 6) rails generate a secret key base in tmp/development_secret.txt for you.
and in production environment the best is having SECRET_KEY_BASE as en env variable, it will get picked up by rails.
you can check with Rails.application.secret_key_base.
should give you a long string of numbers and characters from 'a' to 'f' (a 128 chars long hexadecimal encoded string)
As you can see, there is a hardcoded value for the development and test environments, but the one for production comes from a variable. First of all, why this way? It is a security feature. This way, if you check this file into version control such as git or svn, the development and test values get shared, which is fine, but the production one (the one that would be used on a real website) isn't, so no one can look at the source to get that secret.
As for the variable used, ENV["SECRET_KEY_BASE"], this is an environment variable from the environment Rails is run in (not to be confused with the Rails "environment", such as development, test, and production). These environment variables come from the shell. As mentioned in JensD's post, you can set this environment variable temporarily with:
export SECRET_TOKEN=YOUR SECRET TOKEN
export SECRET_KEY_TOKEN=YOUR SECRET BASE
To generate a new secret token, use the rake secret command in the command line.
That is temporary, however, and not a good final solution. For a final solution, check out this article which has a quick bit near the end on implementing dotenv to load configuration secrets. Remember, if you use version control, be sure to exclude your .env file from being checked in!
Setting dotenv up takes a little bit of work, but I highly recommend it over trying to manually configure these environment variables.

Resources