Question

I have a chef server running on a machine (listening on port 4000), and I'd like to access it over SSL. I've set up an Apache reverse proxy to do so (listening on port 4001). The Apache setup looks like (with my machine name replaced with www.example.com)

Listen 4001

<VirtualHost *:4001>

   SSLEngine on
   SSLCertificateFile    /etc/ssl/certs/ssl-cert-snakeoil.pem
   SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

   ProxyRequests     Off
   ProxyPreserveHost On

   <Proxy http://localhost:4000*>
     Order deny,allow
     Allow from all
   </Proxy>

   ProxyPass         /  http://localhost:4000/
   ProxyPassReverse  /  http://localhost:4000/
   ProxyPassReverse  /  http://www.example.com:4000/
   ProxyPassReverse  /  http://www.example.com:4001/

   CustomLog ${APACHE_LOG_DIR}/chef.access.log common
   ErrorLog ${APACHE_LOG_DIR}/chef.error.log

</VirtualHost> 

The problem is that the URLs in the JSON returned by chef API calls have http instead of https. For example, they look like:

http://www.example.com:4001/sandboxes/a25fa2615d3d4dbd91e91a5e3a76c0ea

Instead of:

https://www.example.com:4001/sandboxes/a25fa2615d3d4dbd91e91a5e3a76c0ea

One example is when doing a POST to /sandboxes to create a new sandbox, which created the link above. This breaks things like trying to use knife to upload cookbooks.

From what I can tell, the chef server create method which is invoked by the /sandboxes POST calls the Merb absolute_url helper method to generate the URL.

At this point, I'm stumped about how to fix this problem. Do I need to make a change my Apache reverse proxy configuration somehow? Is it a configuration option in the chef server? Or something else?

Was it helpful?

Solution

I think you just need to add:

RequestHeader set X-Forwarded-Proto "https"

to your Apache configuration.

This makes Apache add the X-Forwarder-Proto: https header to all requests to the Chef/Merb server. Merb checks for this header when deciding whether the request should be treated as secure (you can follow the requests from options[:protocol] ||= request.protocol in absolute_url to request#protocol to request#ssl?).

The ProxyPassReverse directive only changes headers from the backend, it doesn't alter any content (that would require parsing and recognising urls in the content). Passing this header allows Merb to know that it should act as if the request is using SSL, and create links as appropriate.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top