Lightweight Application Gateway for Envoy
Also known as application proxy or application-level proxy, an application gateway is an application program that runs between two networks. When a client program establishes a connection to a destination service, it connects to an application gateway, or proxy. The client then negotiates with the proxy in order to communicate with the destination service. In effect, the proxy establishes the connection with the destination behind the firewall and acts on behalf of the client, hiding and protecting individual applications on the network behind the app gateway. This creates two connections: one between the client and the proxy server and one between the proxy server and the destination. Once connected, the proxy makes all packet-forwarding decisions. Since all communication is conducted through the proxy server, applications behind the firewall are protected.
The application gateway will communicate the user information and other information which are deprived while authenticating the enduser as headers/JWT to the destination services. Destination service doesn’t have to worry about authentication since it’s been carried out by the app gateway in a safe manner. The services sitting behind can write their logic relying on headers/JWT passed by the application gateway.
Well, what about light weight application gateway to kubernetes environment ? Hope you have heard about Envoy Proxy. Out of different modes which Envoy can act as, Gateway mode is one of the main usages, Though it supports as a gateway it doesn’t have the capability to act as an application gateway to sit in front of services and do user authentication on be half of the application.
Let’s see how we can convert the Envoy gateway to an application gateway. Well, Envoy supports GRPC / HTTP filters which we can use to implement our own logic while the requests and responses passes through Envoy.
This application gateway is implemented as an Envoy Filter which will be invoked through GRPC. You can find the implementation of this Envoy Filter from here. Basically below is the request flow in overall.
- Client browser initiates a request to web application http://my-host/items/
- When the request passes through Envoy Filter which is acting as a gateway, it will trigger the hook to Envoy OIDC filter which we have written.
At this point the filter which we have written is checking whether authenticated cookies are existing or not in the request. If the cookies are there, we will validate the cookies and allow the user to access the webpage. If not,
3. OIDC filter will initiate an authentication flow to the OIDC provider using authorization grant type. From this point onwards, the end user authentication will be taken cared by the OIDC provider (Identity Server, Identity Provider)
4. IDP will respond back once the authentication completes. OIDC filter will validate the ID token to check whether it’s expired or not and whether the signature is valid.
5. Upon validation OIDC filter responds back issuing another JWT token issued by the key pair provided to it.
6. and 7. The request will reach the service / web application and will serve content.
This filter supports below environment variables. Note that you need to use OIDC well known discovery supported Identity Provider.
"IDP_DISCOVERY_URL" : OIDC discovery URL of the IDP. If you use Google as the IDP this will be https://accounts.google.com"SKIP_DISCOVERY_URL_CERT_VERIFY" : Whether you need to use SSL or not. Better to first try with true "CLIENT_ID" : Client ID of the registered app"CLIENT_SECRET" : Client Secret of the app"REDIRECT_URL" : Callback URL in OAuth2 authorization code grant."APP_BASE_URL" : The base URL which is used by the application to navigate."DCR_ENDPOINT" : In a case if you use Dynamic Client Registration supported IDP, you can use this. "DCR_USER" : Username for DCR invocation authentication."DCR_PASSWORD" : Password for DCR invocation authentication. "PRIVATE_KEY_FILE" : Key to sign JWT issued to the actual service / webapplication"CERTIFICATE_FILE" : Certificate of the above private key."JWT_ISSUER" : Issuer which you want in the JWT issued to actual backend"JWT_AUDIENCE" : Audience which you want in the JWT issued to actual backend"SUBJECT_CLAIM" : Claim which needs to be included as SUB attribute in the JWT issued to actual backend. (Out of claims you get from your OIDC provider)
We will not be going through how to apply this Envoy filter . For example in Istio you can use envoyfilters.networking.istio.io CRD to apply this filter. If you need help on applying this feel free to raise on this article to get some help.
Kudos to Mirage Abeysekara for Implementing OIDC filter using GoLang !!