Istio is a great addition on top of Kubernetes that enables powerful features for a regular set of micro services. Istio routing starts with ingress gateway that is exposed to the load balancer. It receives the requests and routes them to appropriate services based on the Gateway and VirtualService resources deployed.
End user authentication
Leaving basic auth and other development time authentication models aside, end user authentication boils down to token based authentication. This token typically is a JWT token.
Istio offers jwt token based authentication as follows:
How do I get that token?
Well, istio leaves that to the developers of the services. But in a typical web app, end user logs into it and the webapp seamlessly interact with underlying services. For this to happen the service need to interact with an Open ID provider and acquire the token on behalf of the current user. This requires performing OAuth 3-legged flow, where your service need to interact with OpenID resource server to
1. Request code
2. Exchange it with access token
This oauth flow can be extracted into a a dedicated service that coordinates with OpenID provider and fetches the token. OAuthProxy is one such implementation. It has the following interface
/p/login -- routes users to OpenID provider page
/p/callback -- invoked by OpenID server to send the code
/p/auth -- validates if the current request has valid token
How do I route requests?
The end user authentication that validates JWT tokens is not going to be sufficient here. There is no native declarative way to do this in Istio at the time of writing this. However istio allows us to configure the sidecar proxy, an Envoy proxy, using a kubernetes resource called EnvoyFilter.
Envoy filter allows us to customize or respond to http requests. Envoy filters are written in Lua. Such filters can be attached to any pods running in the cluster based on the pod labels. Unfortunately, the pod labels are globally searched by Envoy and they are not limited to the namespace in which they were installed. So, care must be taken to make sure the labels used to associate pods with filters are unique. A sample envoy filter that performs oauth flow with the help of oauthproxy look like this -
Putting all the pieces together
- Write Envoy filter that receives request and routes to OAuthProxy if the request is unauthenticated.
- Label the target pods to which this Filter should be installed for
- Deploy OAuthProxy to perform OAuth flows