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

BCDA-471: Refactor BCDA http server to handle https connections #72

Merged
merged 14 commits into from Nov 16, 2018

Conversation

em1
Copy link
Contributor

@em1 em1 commented Nov 14, 2018

Fixes BCDA-471

The BCDA http server must be refactored in order to accept https connections.

Proposed changes:

  • Add ability to connect over HTTPS

Change Details

  • New environment variables BCDA_TLS_CERT, BCDA_TLS_KEY, HTTP_ONLY
  • servicemux.go checks the env vars in Serve() and routes to serveHTTPS() or serveHTTP() depending on whether HTTP_ONLY is true. Defaults to using HTTPS and panics if certificate and key paths are not provided.
  • serveHTTPS() loads the certificate and key and creates a TLS listener, and adds TLSConfig with Certificates to each server to enable new IsHTTPS() function
  • Note that tests are not included in this PR, but there is a separate ticket (BCDA-509) to create them in the next sprint

Security Implications

More secure with TLS!

Acceptance Validation

Able to connect via https with self-signed certificate locally.
screen shot 2018-11-14 at 9 50 43 am

Feedback Requested

Any. Do we need to test in dev or sbx to validate before approval?

@msnook
Copy link
Contributor

msnook commented Nov 14, 2018

Do we need a follow-on ticket to this to (1) disable http within the app altogether, and (2) update ops scripts to close down 80 and open up 443 ?

@em1
Copy link
Contributor Author

em1 commented Nov 14, 2018

For local development, I think we want to keep the http option. As far as I know, we don't have certificates for any environments right now, so not sure how soon there would need to be ops changes.

@msnook
Copy link
Contributor

msnook commented Nov 14, 2018

Good point on the local development. Maybe we need a FORCE_HTTPS feature flag which defaults to false, and we can configure it to TRUE in AWS when we are ready?

@StewGoin
Copy link
Collaborator

Similar to the encryption flags, I don't mind at all having this be an environment variable / flag, but default it to the Prod requirement if possible and make the explicit exception be required for Dev (you want to avoid https? you have to do it on purpose, otherwise you get https).

Copy link
Contributor

@tbellj tbellj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me, but is there a way to test this locally?

rnagle
rnagle previously requested changes Nov 15, 2018
Copy link
Contributor

@rnagle rnagle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good start, though it doesn't quite work front-to-back.

The problem I'm seeing is that a request for bulk data sends back the Content-Location header with an http URL. This happens because http.Request.TLS is not available here. This is a noted limitation of cmux.

Consider our test client, which uses the api's responses to step through the data request workflow automagically. When it tries to use the http URL from the Content-Location header, it will be unable to continue. 😞

So, I did a little experimenting and have an idea for you --

Consider this helper func:

func IsHTTPS(r *http.Request) bool {
	srv := r.Context().Value(http.ServerContextKey).(*http.Server)
	return srv.TLSConfig.Certificates != nil
}

This works based on the assumption that a populated http.Server.TLSConfig.Certificates field is fundamentally required in order to handle https requests.

With it, you can replace instances of this:

scheme := "http"
if r.TLS != nil {
  scheme = "https"
}

With:

scheme := "http"
if IsHTTPS(r) == true {
  scheme = "https"
}

Caveat is that you must set http.Server.TLSConfig on each of your ServiceMux.Servers using the tls.Config you set up here.

In the comments below, I mention adding a catch-all handler to redirect any http requests to their https equivalents. I think it'd be smart to add this if it's not a crazy change of scope. It should help in cases where bad/ill-informed clients mix http and https protocols in their requests.

log.Panic(err)
}

config := &tls.Config{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice if we could set PreferServerCipherSuites and CurvePreferences in the tls.Config per the recommendations here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Side note: with this configuration, when https is enabled, we only support https. Should we also accept http requests and simply redirect them to their https equivalent? My instincts are telling me yes, it would be smart to add this in. This is another question that comes straight from link in my previous comment.

@em1 em1 dismissed rnagle’s stale review November 15, 2018 19:44

Made requested changes and created ticket for http -> https redirect.

@em1 em1 requested review from StewGoin and DeirdreHolub and removed request for PatriciaAnong November 15, 2018 19:44
Copy link
Contributor

@rnagle rnagle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally and both http and https configurations work as expected. One minor change, one question in PR comments.

Before merging, we'll need to set HTTP_ONLY=true for our deployment environments so that the app functions properly until we get our DNS and certificates set up. Let me know when you're ready to merge and I can help with that.

@@ -14,6 +14,7 @@ RUN dep ensure
ENV BB_CLIENT_CERT_FILE ../shared_files/bb-dev-test-cert.pem
ENV BB_CLIENT_KEY_FILE ../shared_files/bb-dev-test-key.pem
ENV BB_SERVER_LOCATION https://fhir.backend.bluebutton.hhsdevcloud.us
ENV HTTP_ONLY true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this to docker-compose.yml.

match = m.Match(URLPrefixMatcher(path))
}

srv.TLSConfig = &tls.Config{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to set srv.TLSConfig = config?

Copy link
Contributor

@rnagle rnagle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work. 👍

@em1 em1 merged commit 5628000 into master Nov 16, 2018
@em1 em1 deleted the eh/bcda-471 branch November 16, 2018 00:03
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

Successfully merging this pull request may close these issues.

None yet

5 participants