rack-ssl-enforcer icon indicating copy to clipboard operation
rack-ssl-enforcer copied to clipboard

Is there a way to combine only_hosts & only?

Open akashkamboj opened this issue 12 years ago • 18 comments

Hello

I have a site where I want SSL only on these routes:

https://api.example.com https://example.com/users/sign_in https://example.com/users/sign_up

and rest URLs should run without SSL. I am not able to figure out a way to combine only_hosts and only together. Tried these:

config.middleware.use Rack::SslEnforcer,
                          only_hosts: %r{api.example.com},
                          only: %r{/users},
                          ignore: %r{/assets},
                          strict: true

also tried with mutiple statements together:

    config.middleware.use Rack::SslEnforcer,
                          except_hosts: %r{api.example.com},
                          only: %r{/users},
                          ignore: %r{/assets},
                          strict: true

    config.middleware.use Rack::SslEnforcer,
                          only_hosts: %r{api.example.com}

but no luck. any suggestion on how I can achieve it?

Thanks

akashkamboj avatar Oct 10 '13 09:10 akashkamboj

Hi,

This is a tricky use-case, but maybe by setting the strict option only on the second statement might work:

config.middleware.use Rack::SslEnforcer,
  only_hosts: %r{api.example.com}

config.middleware.use Rack::SslEnforcer,
  except_hosts: %r{api.example.com},
  only: %r{/users},
  ignore: %r{/assets},
  strict: true

So the first statement ensures that all calls on api.example.com will be redirected to HTTPS, and then the second statement ensures that all calls matching /users will be redirected to HTTPS, and every other calls will be redirected to HTTP (ignoring calls matching /assets).

I haven't actually tried this case, I'll try to add this test cases of the projects to see if that actually works.

rymai avatar Oct 10 '13 09:10 rymai

nope it works the same way. /users paths works as https enabled but api.example.com ended in a redirect loop.

akashkamboj avatar Oct 10 '13 09:10 akashkamboj

Ok, is the strict option mandatory in your use-case then?

rymai avatar Oct 10 '13 09:10 rymai

yes

akashkamboj avatar Oct 10 '13 09:10 akashkamboj

Ok, I've added your use-case to our test suite and it works as expected...

What do you think?

rymai avatar Oct 10 '13 15:10 rymai

why is except_hosts set to api.example.com and only_hosts set to api.example.org?

akashkamboj avatar Oct 10 '13 16:10 akashkamboj

ok I forked and checked with api.example.org at both place and tests are passing fine. But in Rails app it's not working. Is there a way to define the both statements in one array (like in test case) rather than 2 different statements (like above). Something like

config.middleware.use Rack::SslEnforcer, [ { :only_hosts => %r{api.example.org} }, { :except_hosts => %r{api.example.org}, :only => %r{^/users}, :ignore => %r{^/assets}, :strict => true } ]

Just a silly thought.

akashkamboj avatar Oct 10 '13 17:10 akashkamboj

@rymai I guess above isn't silly thought :), if i define 2 statements in test case, rather than one array.

setup {
        mock_app :only_hosts => %r{api.example.org}
        mock_app :except_hosts => %r{api.example.org}, :only => %r{^/users}, :ignore => %r{^/assets}, :strict => true
}

One Test fails (api test). And that's exactly the same thing happening in rails app. Any suggestions?

akashkamboj avatar Oct 10 '13 17:10 akashkamboj

Sorry about the typo, but actually the :except_hosts is actually not needed at all (I've fixed the test)!

Re. the test following setup:

setup {
  mock_app :only_hosts => %r{api.example.org}
  mock_app :except_hosts => %r{api.example.org}, :only => %r{^/users}, :ignore => %r{^/assets}, :strict => true
}

some tests fail because the first statement is not part of the app that's used for the tests. In fact the last call to mock_app replaces the app you created with the first call. That's why I passed 2 hashes to mock_app in order to define two use Rack::SslEnforcer statements.

That all said, could you share your Rails config file where you use use Rack::SslEnforcer? Thanks!

rymai avatar Oct 10 '13 20:10 rymai

Here's my rack_ssl_config.rb from /config/initializers directory

Website::Application.configure do

  if AppConfig.ssl.enabled
    config.middleware.use Rack::SslEnforcer,
                          only_hosts: AppConfig.api.host

    config.middleware.use Rack::SslEnforcer,
                          except_hosts: AppConfig.api.host,
                          only: %r{/users},
                          ignore: %r{/assets},
                          strict: true
  end

end

I've no clue to pass both statements in one hash. what will be the code for it?

akashkamboj avatar Oct 11 '13 07:10 akashkamboj

oh now i studied the mock_app method. My bad. Sorry for above. But there is one problem with tests, you've to add one more test that when someone access the https://api.example.org it shouldn't redirect and that's failing

should 'stay on HTTPS for https://api.example.org' do
      get 'https://api.example.org'
      assert_equal 200, last_response.status
      assert_equal 'https://api.example.org/', last_response.location
end

and that's creating a redirect loop.

akashkamboj avatar Oct 11 '13 08:10 akashkamboj

ok this hasn't solved from long time. So I guess if there's another option where I can pass a Proc or a property called ignore_hosts so that I can ignore api.example.org and manage it manually. Is that possible. I was also thinking to override the call method for middleware, but thought if ignore_hosts is there, that will be better instead overriding the call. What do you think?

akashkamboj avatar Mar 17 '14 07:03 akashkamboj

@rymai, @thibaudgg would you take a look at branch issue62? 1c985f6c should fix this issue, but two other tests are broken now (both a comination of :strict and :except*). I believe the :except option should except specific paths, hosts or whatever from any modification - any other opinions on that?

tobmatth avatar Mar 28 '14 13:03 tobmatth

@rymai could you look at it, I'm in the middle of my move, thanks!

thibaudgg avatar Apr 01 '14 09:04 thibaudgg

I'll have a look this evening!

rymai avatar Apr 01 '14 09:04 rymai

Ok, I've had a chance to review this issue. I think :except* constraints + :strict option make sense. Why should it be different than for :only* constraints?

rymai avatar Apr 01 '14 21:04 rymai

I face the same situation with @akashkamboj. I got redirect loop when I go http://api.example.com

config.middleware.use Rack::SslEnforcer, only_hosts: 'api.example.com'
config.middleware.use Rack::SslEnforcer,
  only: ['/admin/login', %r{^/user/password}],
  ignore: %r{^/assets},
  strict: true

Even it still get redirect loop when I try with except_hosts

config.middleware.use Rack::SslEnforcer, only_hosts: 'api.example.com'
config.middleware.use Rack::SslEnforcer,
  except_hosts: 'api.example.com',
  only: ['/admin/login', %r{^/user/password}],
  ignore: %r{^/assets},
  strict: true

samnang avatar Nov 12 '14 15:11 samnang

I'll try to take a closer look before the weekend...

tobmatth avatar Nov 12 '14 18:11 tobmatth