AWS SSL Healthcheck

Hi,

I have my phoenix application running in a docker container hosted on AWS behind an application load balancer. The loadbalancer handles ssl for me. The application however handles the force ssl and redirects http requests to https based on the x-forwarded-proto header (this header is set by the loadbalancer). Below my endpoint configuration for my staging environment:

config :foo_endpoint, FooEndpoint.Endpoint,
  load_from_system_env: true,
  url: [host: "staging-foo.org"],
  cache_static_manifest: "priv/static/cache_manifest.json",
  check_origin: false,
  force_ssl: [rewrite_on: [:x_forwarded_proto], hsts: true, host: nil]

The target group in AWS that handles the dynamic port mapping from docker to docker-host, also handles a healthcheck. However this healthcheck does not have any headers and AWS does not allow me to set them. Since ssl is handled before the target group (in the loadbalancer) the protocol used for the healthcheck is http, this results in a 301 redirect from the ssl plug. The healthcheck does not follow the 301, this means the controller isn’t reached and the healthcheck functionality is not actually executed.

Is there a possibility to exclude one endpoint from the redirect? Or does anyone have a different solution or approach to this handle this situation. I think the same situation can occur while using nginx, or an other kind of loadbalancer, that handles ssl for you.

Thanks in advance.

1 Like

The easiest way to do this is to set your success code to 200-399 on the health check in the load balancer.

You can also use Plug.SSL manually in your endpoint instead of setting it in your config. Something like this in your endpoint (untested):

  plug :respond_to_ping, "/ping"
  plug Plug.SSL, rewrite_on: [:x_forwarded_proto], hsts: true, host: nil

  defp respond_to_ping(%{halted: true} = conn, _), do: conn

  defp respond_to_ping(%{request_path: path} = conn, path) do
    conn
    |> Plug.Conn.put_resp_header("content-type", "text/html")
    |> Plug.Conn.send_resp(200, "pong")
    |> Plug.Conn.halt()
  end

  defp respond_to_ping(conn, _), do: conn
7 Likes

Thanks for your response.

Setting the success code to 200-399 on the health check is not sufficient in our case since we also check for database connection in our health check, and the health check doesn’t follow a 301. The second options however does allow for this to happen.

Thanks again for your advice.

1 Like

I would just have nginx specialize on the specific healthcheck path and then perform whatever test it itself wants (including an internal, not external, redirect if wanted).

1 Like