Open-Sourcing OpenIDC-Proxy

Lukas Karlsson
4 min readNov 3, 2018

Several years ago, when we started building Firecloud (“an open platform for secure and scalable analysis on the cloud”) we quickly discovered a need for a general purpose authentication and authorization proxy that we could deploy in front of each of our micro services.

Rather than having each of the engineering teams build auth and security features into their respective applications, we wanted to provide those features as a self-contained component that could be deployed along-side each micro service.

The key features we wanted to externalize included:

  • Authentication of user requests
  • Authorization of user requests based on groups
  • Logging requests to an external service
  • HTTPS encryption for all requests

Each of our services is deployed as a Docker container. So it made sense to start with Docker as the core technology for this solution. If we could provide a container that offered all of the desired features, we could deploy that in front of each service as a proxy. That way, the micro service doesn’t have to know about SSL or how to authenticate users, for example. Instead, it just receives authenticated, authorized and unencrypted requests from the proxy and processes them.

The proxy is based on the following technologies:

How It Works

The proxy container is deployed as the front-end of the service, with the application container(s) sitting behind it on the back-end. The proxy exposes ports 80 (HTTP) and 443 (HTTPS) and automatically redirects (301 Moved Permanently) any un-encrypted requests to the SSL-encrypted port. None of the back-end application ports are exposed, so the only way to access the application is through the proxy.

Logging

By default, we set the proxy and the application containers to log all their output to syslog. That way, we just need to configure the host to send its logs to an external service (such as Loggly or Stackdriver) and we will successfully capture everything from our service as well as from the host itself. Alternatively, you could use the gcplogs driver to send the container’s output directly to Stackdriver, skipping syslog entirely (but you may want a way to capture host-level logs, depending on where your service is deployed, which is why we currently use syslog).

Authentication

We generally authenticate users via Google, which is well-supported by mod_auth_openidc, but you could also use another service such as Auth0. For endpoints that accept browser-based traffic from actual users, we support the full OpenID Connect flow for authenticating, requesting scopes, and generating access tokens with a clientid and secret. For API endpoints, we support the OAuth 2.0 protocol and accept a Authorization header with a Bearer token.

Out of the box, a single instance proxy can support three distinct endpoints with three different auth configs, so a common setup is to have:

  • /: Unauthenticated users, welcome page
  • /login: Browser based user logins authenticated via OpenIDC
  • /api : API traffic authenticated via OAuth2

With custom configs, you can support as many different endpoints with as many different auth configurations as you wish.

Authorization

For authorization, our preference would have been to use Google Groups. However, at the time that the proxy was originally developed, APIs that would have allowed us to build a “mod_auth_googlegroups” plugin were not yet available. Instead, we relied on support for mod_authnz_ldap built into mod_auth_openidc.

We deploy an instance of OpenLDAP as one of the micro services within the larger application. That way, all of the other services can use that LDAP service to do authorization. We populate LDAP groups with the correct membership for various endpoints and then we can control access at proxy based on those groups. If a user doesn’t have access to a URL based on LDAP group membership then their traffic will never reach the back-end services.

If we were building this today, we would either use Google’s new Secure LDAP service, or we would create a Google Groups auth module for Apache based on the hasMember endpoint in the G Suite Admin SDK Members API. Either approach would remove the reliance on the OpenLDAP instance.

Contributors

This project has been the result of work by several different folks in the organization, including but not limited to:

Read more about the proxy on Andrew’s Medium post announcing the public release: “Wrap HTTPS and OAuth around your container”.

Images and Source Code

Source code for the proxy is available on GitHub in two separate repos. There is a base image, that includes Apache with mod_auth_openidc:

and then the proxy image adds in all of the authentication and authorization features on top of that:

Both projects are also available as Docker images from DockerHub or Quay:

For bugs or questions, create GitHub Issues for the appropriate project. Contributions are welcome, so feel free to fork the repos and create pull requests.

Conclusion

After several years of using this technology internally and in the cloud for dozens of different applications, we’re excited to make it available to the community.

If you’re looking for something similar maintained by Google, check out the Extensible Service Proxy.

--

--

Lukas Karlsson

Google Developer Expert, Cloud Platform; Google Certified Cloud Architect. Somerville, MA.