Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secret key base is required during Docker build if credentials used in before_action #51772

Open
tsvallender opened this issue May 9, 2024 · 3 comments

Comments

@tsvallender
Copy link
Contributor

Steps to reproduce

  1. Add a before_action like the following to a controller:
http_basic_authenticate_with name: "admin", password: Rails.application.credentials.dig(:http_auth, :password)
  1. Attempt to build with the default Dockerfile (which contains RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile), and you receive the error:
19 [build 6/6] RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
#19 0.844 bin/rails aborted!
#19 0.844 ArgumentError: Expected password: to be a String, got NilClass (ArgumentError)
#19 0.844 
#19 0.844             raise ArgumentError, "Expected password: to be a String, got #{password.class}" unless password.is_a?(Str
ing)
#19 0.844                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#19 0.844 /rails/app/controllers/http_auth_controller.rb:3:in `<class:HttpAuthController>'
#19 0.844 /rails/app/controllers/http_auth_controller.rb:1:in `<main>'
#19 0.844 /rails/config/environment.rb:5:in `<main>'
#19 0.844 Tasks: TOP => environment
#19 0.844 (See full trace by running task with --trace)
#19 ERROR: process "/bin/sh -c SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile" did not complete successfully: exit code:
 1

Expected behavior

As far as I know precompiling assets need not depend on anything in the credentials, so ideally it shouldn’t even try (or the error could be silently ignored).

Actual behavior

The above error is raised, the build fails.

System configuration

Rails version: 7.1.3.2

Ruby version: 3.3.1

@pokonski
Copy link
Contributor

pokonski commented May 9, 2024

This is about missing credentials, which cannot be decrypted without the key. You are reading a password from credentrials at class level, which is evaluated as soon as the controller is loaded and interpreted.

To avoid this see the advanced example here: https://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Basic.html

that is define a custom method that checks the credentials. This way it won't be executed during loading of the code.

Alternatively you could do what http_basic_authenticate_with already does under the hood:

before_action :authenticate_with_basic

private

def authenticate_with_basic
   http_basic_authenticate_with name: "admin", password: Rails.application.credentials.dig(:http_auth, :password)
end

@tsvallender
Copy link
Contributor Author

Is there ever a reason you would need to decrypt credentials for the purpose of precompiling assets though? Is this not an error that could be caught and ignored?

@pokonski
Copy link
Contributor

pokonski commented May 9, 2024

Is there ever a reason you would need to decrypt credentials for the purpose of precompiling assets though? Is this not an error that could be caught and ignored?

This isn't a Rails issue. It's how Ruby works. You added a class level code that tries to read credentials when class is loaded. There's no way for Rails to catch and ignore

You can see this in IRB by defining a simple class with puts in it:

irb(main):001:1* class Test
irb(main):002:1*   puts "something at load time"
irb(main):006:0> end
something at load time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants