Installation and Integrating Istio Istio is a completely open source service mesh that layers transparently onto existing distributed applications. It is also a platform, including APIs that let it integrate into any logging platform, or telemetry or policy system. Istio addresses the challenges developers and operators face as monolithic applications transition towards a distributed microservice architecture. To see how, it helps to take a more detailed look at Istio’s service mesh The term service mesh is used to describe the network of microservices that make up such applications and the interactions between them. As a service mesh grows in size and complexity, it can become harder to understand and manage. I ts requirements can include discovery, load balancing, failure recovery, metrics, and monitoring. Istio provides behavioral insights and operational control over the service mesh as a whole, offering a complete solution to satisfy the diverse requirements of microservice applications. Why use istio?? It makes it easy to create a network of deployed services with load balancing, service-to-service authentication, monitoring , and more, with few or no code changes in service code. Architecture An Istio service mesh is logically split into a data plane and a control plane The data plane is composed of a set of intelligent proxies (Envoy) deployed as sidecars. These proxies mediate and control all network communication between microservices. They also collect and report telemetry on all mesh traffic. The control plane manages and configures the proxies to route traffic. For further information, please refer to https://istio.io/latest/docs/ops/deployment/architecture Core Features 1. Traffic management 2. Security 3. Observability For further information, please refer to https://istio.io/latest/docs/concepts/what-is-istio/#core-features Fig 1 : Architecture Installation 1. Download and extract the latest release automatically (Linux or macOS): curl -L https://istio.io/downloadIstio | sh - 2. Move to the Istio package directory. For example, if the package is istio-1.8.1 cd istio-1.8.1 The installation directory contains: i) Sample applications in samples/ ii) The istioctl client binary in the bin/ directory. 3. Add the istioctl client to your path sudo mv /bin/istioctl /usr/local/bin/ [OR] export PATH=$PWD/bin:$PATH 4. For this installation, we use the demo configuration profile. It’s selected to have a good set of defaults for testing, but there are other profiles for production or performance testing. istioctl install --set profile=demo -y Fig 2: Profile setting 5. Add a namespace label to instruct Istio to automatically inject Envoy sidecar proxies when you deploy your application later: kubectl label namespace default istio-injection=enabled Fig 3: Labelling the namespace Integrating with Cluster [Sample App] 1. Deploy the sample-app.yaml [your app’s deployment file ] to the same labelled namespace.[i.e default] kubectl create -f sample-app.yml 2. Check the services and pods. 3. Now in order to open the traffic to outside, we can use the Istio Ingress Gateway kubectl create -f sa-gateway.yml 4. In this sa-gateway.yml, we have two sections. First one is Gateway and second one is the Virtual service. We are connecting the ingress gateway and our application through Gateway apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: sa-gateway spec: selector: istio: ingressgateway # use Istio default gateway implementation servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" In Virtual service, we are giving the above created gateway’s name in its parameters to integrate them together. apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: sample-app spec: hosts: - "*" gateways: - sa-gateway http: - match: - uri: exact: /SampleApp/AppTest1 - uri: exact: /SampleApp/AppTest2 route: - destination: host: sample-app port: number: 9575 Under http, we should give the adapters we need to hit with the full path in match uri and the application’s http port in the route section 5. Ensure that there are no issues with the configuration. istioctl analyze 6. Now Determine the INGRESS_HOST and INGRESS_PORT variables for accessing the gateway to expose our service. export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}') echo "$INGRESS_PORT" export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}') echo "$INGRESS_HOST" 7. Now set the gateway url, export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT echo "$GATEWAY_URL" 8. Now hit the URL in the cluster through curl or browser or postman. echo "http://$GATEWAY_URL/SampleApp/AppTest1" We can use the external public ip when the INGRESS_HOST is the Cluster IP. For further information, please refer to the https://istio.io/latest/docs/setup/getting-started/ End-user Authentication To experiment with this feature, you need a valid JWT. The JWT must correspond to the JWKS endpoint you want to use for the demo. Also, for convenience, expose our application via ingress gateway , which we have already done. Fig 4: End user authentication architecture 1. Now, add a request authentication policy that requires end-user JWT for the ingress gateway. kubectl apply -f - <<EOF apiVersion: "security.istio.io/v1beta1" kind: " RequestAuthentication " metadata: name: "jwt-example" namespace: istio-system spec: selector: matchLabels: istio: ingressgateway jwtRules: - issuer: "testing@secure.istio.io" jwksUri: " https://raw.githubusercontent.com/istio/istio/release-1.8/sec urity/tools/jwt/samples/jwks.json " EOF 2. Apply the policy to the namespace of the workload it selects, ingress gateway in this case. The namespace you need to specify is then istio-system 3. If you provide a token in the authorization header , its implicitly default location, Istio validates the token using the public key set, and rejects requests if the bearer token is invalid . However, requests without tokens are accepted . To observe this behavior, retry the request without a token, with a bad token, and with a valid token: TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.8/sec urity/tools/jwt/samples/demo.jwt -s) curl --header "Authorization: Bearer $TOKEN" "$INGRESS_HOST:$INGRESS_PORT/SampleApp/AppTest1" 4. To reject requests without valid tokens , add an authorization policy with a rule specifying a DENY action for requests without request principals , shown as notRequestPrincipals: ["*"] in the following example. Request principals are available only when valid JWT tokens are provided . The rule therefore denies requests without valid tokens. kubectl apply -f - <<EOF apiVersion: "security.istio.io/v1beta1" kind: " AuthorizationPolicy " metadata: name: "frontend-ingress" namespace: istio-system spec: selector: matchLabels: istio: ingressgateway action: DENY rules: - from: - source: notRequestPrincipals: ["*"] EOF For further information, please refer to the https://istio.io/latest/docs/tasks/security/authentication/authn-policy/#end-user-authentication Keycloak Authentication Just like Auth0 , Istio also supports the JWT token from Keycloak . The default JWT token provided by the Istio was less secure since it was hardcoded . Auth0 at the sametime was a paid service. Keeping in mind that the Kubernetes cluster and Istio gateway is already running, we are moving to the End user authentication based on Keycloak. 1. From a terminal start Keycloak with the following command: docker run -p 8080:8080 --detach -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin --name re1.1 jboss/keycloak 2. Go to the Keycloak Admin Console and login with the username and password you created earlier. It will be available on <ip-address:8080> . 8080 is the port exposed by the docker image. [Optional] In case of https required , pls turn that off with the help of following commands: a. Go to the docker bash profile b. And execute the following commands cd keycloak/bin [/opt/jboss/keycloak/bin] ./kcadm.sh config credentials --server http://localhost:8080/auth --realm master --user admin ./kcadm.sh update realms/master -s sslRequired=NONE Now let’s move to the token generation part in keycloak and see how it gets verified by the Istio. 1. Create a new realm name istio and set it up like this. Select RS256 as the default signing algorithm 2. Create the client as following, take note the client ID and secret 3. Now generate the token using the above the credentials with a POST request to http:// <ip-address:8080> /auth/realms/Istio/protocol/openid-connect/token. Everytime we hit the URL, it gives a new token and token validation time can be changed from the keycloak settings. 4. We can now use this token to authenticate our exposed service. But for the verification of this token issued by the keycloak issuer, we need to modify the request authentication policy file. apiVersion: "security.istio.io/v1beta1" kind: " RequestAuthentication " metadata: name: "jwt-example" namespace: istio-system spec: selector: matchLabels: istio: ingressgateway jwtRules: - issuer: " http://<ip_address>:8080/auth/realms/Istio " jwksUri: " http://<ip_address>:8080/auth/realms/Istio/protocol/openid-co nnect/certs " For understanding the difference, compare this file with the initial configuration. 5. After updating this file, please deploy the authorization policy file to deny the requests without valid tokens. For further reference, please refer to the https://mymusictaste.github.io/end-user-auth-with-istio-keycloak-eks/