What is the problem?¶
The traditional way of authenticating users is to include authentication code inside the application. However, in the microservice world, this approach becomes repetitive and prone to error, as similar logic has to be implemented over and over.
There is a need to consolidate authentication in one place. What if we could perform all common authentication logic in a proxy in front of the application and just let the application know the final result? For example, the proxy could use a standardized flow to authenticate users and propagate the authentication’s result to the application in HTTP headers. This allows for the authentication logic to be implemented once and reused across applications.
Modern proxies (e.g., Envoy) allow the user to extend their functionality. One common extension they allow is to call into an external service to ask if a request is allowed or denied. This is especially useful since it allows extending existing proxies of a Service Mesh (e.g., Istio) with the functionality described above. In Envoy, this extension interface is called the envoy.ext_authz filter. So instead of writing our own proxy, we can implement this interface and extend existing proxies, lowering the barrier-to-entry and improving efficiency.
The AuthService is an implementation of Envoy’s
ext_authz interface. For
every request that reaches Envoy, it will make a request to the AuthService to
ask if that request is allowed.
After understanding what the AuthService is, we will see a more practical
example of how it is integrated in our deployments, using the Istio Gateway.
The Istio Gateway is the point where external traffic enters the Istio Service
Mesh. It uses an Envoy Proxy, which we configure with an
ext_authz filter to
talk to the AuthService. Here is a diagram of what this looks like in Kubeflow:
This guide assumes that the end user has access to a local clone of Arrikto provided deployments repo.
In order to securely deploy our application, we need to configure our OIDC Client (AuthService) and OIDC Provider (Dex) accordingly.
- Change password of default user
- Change credentials of OIDC client
By default, Dex is installed with a single static user. To change the default user’s password or create new users, one has to modify Dex’s ConfigMap. To change the password of the default user:
Pick a password for the default user, with handle
user, and hash it using
$ python3 -c 'from passlib.hash import bcrypt; import getpass; print(bcrypt.using(rounds=12, ident="2y").hash(getpass.getpass()))'
rok/rok-external-services/dex/base/config-map.yamland fill the relevant field with the hash of the password you chose:
... staticPasswords: - email: user hash: <enter the generated hash here>
Generate OIDC Client credentials for the AuthService. These credentials are used by the AuthService to authenticate to Dex. The credentials must be filled in both Dex and AuthService kustomizations:
$ export OIDC_CLIENT_ID="authservice" $ export OIDC_CLIENT_SECRET="$(openssl rand -base64 32)" $ envsubst < rok/rok-external-services/dex/base/secret_params.env.in > rok/rok-external-services/dex/base/secret_params.env $ envsubst < rok/rok-external-services/authservice/base/secret_params.env.in > rok/rok-external-services/authservice/base/secret_params.env
Now that we know what the end result should look like, we can plan out our
installation. This section is about installing the AuthService at the Istio
Gateway and having your application live behind it. That application can be
Kubeflow, Rok, etc. In this guide, we assume you have already installed Rok and
Istio in your Kubernetes cluster and that both a
VirtualService exist to expose Rok to the outer world.
You should be able to access your application through the Istio Gateway. For
Rok, since we expose it under
should show the Rok UI.
For the AuthService you also need to install an OIDC Provider, which is Dex in our case.
Install an OIDC Provider. Dex is a good choice because it’s easy to get started and also supports statically defined users for demo purposes. To install Dex:
$ kubectl apply -k rok/rok-external-services/dex/overlays/istio
Deploy the AuthService. At this point we have everything working, except our application isn’t secure, because all requests are allowed. To mitigate that, will enable the AuthService on the Istio Gateway’s proxy. To install the AuthService:
$ kubectl apply -k rok/rok-external-services/authservice/base
The AuthService is configured through environment variables, defined in a
oidc-authservice-parameters. An exhaustive list of
configuration options along with their default values and explanations can be
found in the AuthService README.
Istio Gateway Integration¶
The Istio Gateway runs an Envoy proxy, which we configure with an
filter pointing to our AuthService. To do that, we use the
object of Istio. We include an example VirtualService below, with inline
comments to explain relevant parts of the configuration:
# EnvoyFilter is an Istio CRD for configuring the underlying Envoy proxy. # For configuration options, see Istio docs: # https://istio.io/docs/reference/config/networking/envoy-filter/ apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: authn-filter namespace: istio-system spec: filters: # Filled based on Envoy documentation: # https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/network/ext_authz/v3/ext_authz.proto#envoy-v3-api-msg-extensions-filters-network-ext-authz-v3-extauthz - filterConfig: httpService: authorizationRequest: allowedHeaders: patterns: - exact: cookie - exact: X-Auth-Token authorizationResponse: allowedUpstreamHeaders: patterns: - exact: kubeflow-userid serverUri: cluster: outbound|8080||authservice.istio-system.svc.cluster.local failureModeAllow: false timeout: 10s uri: http://authservice.istio-system.svc.cluster.local statusOnError: code: GatewayTimeout # Add the envoy.ext_authz filter filterName: envoy.ext_authz filterType: HTTP insertPosition: index: FIRST # Only match Gateway proxies listenerMatch: listenerType: GATEWAY # Match proxy pods with the following labels workloadLabels: istio: ingressgateway