How to setup service mesh in IBM cloud with Istio and Kubernetes - Part 3

Published On: 2020/04/23

In the third and final article of this series, we will be looking into the details of configuring Istio mesh for the secure communication among components in the mesh.

Istio’s Citadel component manages all the parts and pieces of securing the services in a service mesh. Citadel provides strong service-to-service and end-user authentication using mutual TLS, with built-in identity and credential management. It manages the lifecycle of keys and certificates issued for services. Istio uses these keys and certificates when establishing a mTLS connection between client and server components.

What is mutual TLS

The mutual TLS (mTLS) protocol is used in the Server-to-Server communication. When a mTLS connection is being established, the server originating the message (Server A) and the server which recieves it (Server B) exchange certificate from a mutually trusted Certificate Authority (CA). The certificates prove the identity of each server to the other and ensures that the traffic is both secure and trusted in both directions.

Configure mutual TLS

In Istio we could enable the mutual TLS for a specific service, for a specific namespace or for the mesh itself using authentication policies. These authentication policies, which are ditributed to the Envoy Proxy by the Pilot component, define the kind of requests that a service receives, whether it is encrypted using mutual TLS or plain text.

Create a namespace scoped policy - In this setup we will be creating the policy which is applicable to all services in the namespace “cloud-cargo”. This configuration instruct the target service in the Istio mesh to recieve mutual TLS traffic.

apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "default"
  namespace: "cloud-cargo"
spec:
   peers:
   - mtls: {}
There can be only one namespace-scoped definition for a namespace, with no targets key specified. Since no targets key is specified, the name must be default. You could specify the mode of traffic to let the proxy know what kind of traffic the service could accept, Strict Or Permissive. In the strict mode only an encrypted traffic is allowed but in permissive mode it could allow both encrypted and plain text.

Create destination rules - Destination rule, a core part of Istio routing, is an instruction for the client service to make mutual TLS communication with the target services.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: freight-rating-server
spec:
  host: freight-rating-server
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v1
    labels:
      version: v1

In the above configuration any client which wants to communicate with the freight-rating-server (spec.host configuration) service must use the certificates created by the Citadel component for authentication as mutual TLS (tls.mode = ISTIO_MUTUAL) is the mode of traffic.

Automatic mTLS configuration - In Istio version 1.4 a feature Automatic mutual TLS is added so that user could avoid configuring the destination rules. This feature can be enabled by setting the global.mtls.enabled option set to false and global.mtls.auto set to true while installting Istio. When this option is set, Istio send mutual TLS traffic to those workloads with istio sidecar (istio-proxy), and send plain text traffic to workloads without sidecars.

Configure Ingress controller with Secure Gateway (SDS)

By default the SDS feature of Istio is disabled. You need to enable the istio-ingressgateway.sds.enabled installation option and generate the istio-ingressgateway.yaml file.

istioctl manifest generate \
--set values.gateways.istio-egressgateway.enabled=false \
--set values.gateways.istio-ingressgateway.sds.enabled=true > \
$HOME/istio-ingressgateway.yaml

kubectl apply -f $HOME/istio-ingressgateway.yaml

I have enabled this by editing the istio-ingressgateway deployment which is already running in the kubernetes environment. Search for the sds flag in the deployment config and put the value “true”.

Create new certifcates to configure the ingress gateway using the below commands.

**1** openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=Cargo Inc./CN=cargo.com' -keyout ca.key -out ca.crt

**2** openssl req -out ingressgateway.csr -newkey rsa:2048 -nodes -keyout ingressgateway.key -subj "/CN=poc.cargo.com/O=poc organization"

**3** openssl x509 -req -days 365 -CA ca.crt -CAkey ca.key -set_serial 0 -in ingressgateway.csr -out ingressgateway.crt

**4** kubectl create -n istio-system secret generic cargo-gateway-certs \
--from-file=key=ingressgateway.key \
--from-file=cert=ingressgateway.crt

You could now create the Gateway object, which accepts the https traffic, with the secret “cargo-gateway-certs” created in the above step.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: cargo-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
        mode: SIMPLE
        credentialName: cargo-gateway-certs
    hosts:
    - "*"

Create a VirtualService object which instruct the istio system to do the routing based on the incoming url pattern.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: cargo-vs
spec:
  hosts:
  - "*"
  gateways:
  - cargo-gateway
  http:
  - match:
    - uri: 
        prefix: /api/freight-rating
    route:
    - destination:
        host: freight-rating-server
        port:
          number: 8080
  - match:
    - uri:
        prefix: /api/freight-tariff
    route:  
    - destination:
        host: freight-tariff-server
        port:
          number: 8080
  - match:
    - uri:
        prefix: /    
    route:
    - destination:
        host: cargo-webapp
        port:
          number: 80 

Create DNS entry for the cluster

Use the below commands to create the DNS entry for your cluster

1 - Obtain the Istio ingress gateway’s external IP

kubectl get service istio-ingressgateway -n istio-system
2 - Create the NLB host with the Istio ingress gateway’s public IP address (External IP)
ibmcloud ks nlb-dns-create --cluster <name of the cluster> --ip <External IP address>
3 - List the NLB host names for your cluster
ibmcloud ks nlb-dnss --cluster <name of the cluster>

Setup Kiali

Kiali is an observability console for Istio with service mesh configuration capabilities. This helps you view how the apps are interconnected in the mesh and provides the health of your mesh.

KIALI_USERNAME=$(read '?Username: ' uval && echo -n $uval | base64)
KIALI_PASSPHRASE=$(read -s "?Password: " pval && echo -n $pval | base64)

Once the username , password varibles are created use it to create secret to access kiali dashboard.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: kiali
  namespace: istio-system
  labels:
    app: kiali
type: Opaque
data:
  username: $KIALI_USERNAME
  passphrase: $KIALI_PASSPHRASE
EOF

Use the istioctl tool to start kiali dashboard using the command given below.

istioctl dashboard kiali

Conclusion

In the final part of this series we have gone through the settings required to create a secure gateway by enabling sds feature of Istio. Use Kiali to, Jager and Grafana which comes along with the Istio addon to monitor your mesh once the setup of your mesh is completed. Thank you for reading this series.

comments powered by Disqus