Integrating Flex Gateway with Istio Service Mesh | MuleSoft Documentation
# Integrating Flex Gateway with Istio Service Mesh
To leverage Flex Gateway policies, logging, and metrics from the Anypoint Platform control plane, integrate Flex Gateway into your Istio Service Mesh. Deploy Flex Gateway as an ingress gateway to manage ingress north-south cluster traffic and internal east-west traffic inside the cluster.
To integrate Flex Gateway, use the following architecture diagram and tutorial. Flex Gateway is integrated by using a modified version of the Istio Bookinfo sample application. In the Flex Gateway integration:
  * An Istio virtual service forwards all ingress north-south traffic to Flex Gateway.
  * Direct access to the `bookinfo` name space is restricted. All external traffic into the `bookinfo` namespace must come from the `flex` namespace. Istio automatically configures mTLS configuration between the `bookinfo` and `flex`.
  * Flex Gateway protects and monitors the exposed product page service from ingress traffic with an API instance.
  * The Istio sidecar intercepts east-west traffic between the product page service and the reviews service. Flex Gateway acts as an ingress gateway managing incoming traffic to the reviews service.


In the diagram, Flex Gateway is running in Connected Mode. If Flex Gateway runs in Local Mode, the Anypoint Platform control plane is absent.   
---  
To configure the architecture:
  1. Complete Before You Begin.
  2. Set up your environment.
  3. Intercept ingress north-south traffic.
  4. Intercept east-west traffic between services.


## Before You Begin
Before you begin, install the following prerequisites:
  * Download Flex Gateway for Use in a Kubernetes Cluster
  * K3d to create a Kubernetes cluster inside of docker
  * kubectl to control the Kubernetes cluster
  * Helm to install Flex Gateway and Istio


## Set up Environment
  1. Create a Kubernetes cluster for this demo or skip this step if you already have a cluster you want to use:
```
k3d cluster create demo-istio --k3s-arg "--disable=traefik@server:0" --port '80:80@server:0' --port '443:443@server:0'
```

  2. Add the Flex Gateway and Istio Helm repositories:
```
helm repo add istio https://istio-release.storage.googleapis.com/charts \
&& helm repo add flex-gateway https://flex-packages.anypoint.mulesoft.com/helm \
&& helm repo up
```

  3. Install Istio:
    1. Install the Istio base chart that contains the cluster-wide Custom Resource Definitions (CRDs) that must be installed before deploying the Istio control plane:
```
helm upgrade -i --wait --create-namespace -n istio-system istio-base istio/base --version 1.21.2 --set defaultRevision=default
```

    2. Install the Istio discovery chart that deploys the `istiod` service:
```
helm upgrade -i --wait --create-namespace -n istio-system istiod istio/istiod --version 1.21.2
```

    3. Install an Istio ingress gateway:
```
helm upgrade -i --wait --create-namespace -n istio-system istio-ingress istio/gateway --version 1.21.2
```

  4. Install Flex Gateway:
    1. Create the namespace and set up the label to enable the sidecar injection:
```
kubectl create ns flex && kubectl label ns flex istio-injection=enabled --overwrite
```

    2. Install Flex Gateway:
```
helm upgrade -i --wait -n flex --version 1.7.0 flex flex-gateway/flex-gateway \
--set gateway.scope=Namespace \
--set gateway.mode=connected \
--set service.type=ClusterIP \
--set service.http.port=8081 \
--set service.https.enabled=false \
--set-file registration.content=registration.yaml
```

    3. List all services and API instances previously created:
```
kubectl -n flex get svc
```

  5. Install the `bookinfo` application:
    1. Enable Istio label injection in the default namespace and install the `bookinfo` application:
```
kubectl create ns bookinfo \
&& kubectl label ns bookinfo istio-injection=enabled --overwrite \
&& kubectl -n bookinfo apply -l version!=v2,version!=v3 -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/bookinfo/platform/kube/bookinfo.yaml
```

    2. Check the pod status:
```
kubectl -n bookinfo get pods
```

  6. Install the `sleep` application to test traffic:
    1. Create the `test` namespace and install the `sleep` application:
```
kubectl create ns test \
&& kubectl label ns test istio-injection=enabled --overwrite \
&& kubectl -n test apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/sleep/sleep.yaml
```

    2. Check the status of the pods:
```
kubectl -n test get pods
```



## Intercept Ingress North-South Traffic
Intercept ingress north-south traffic to protect services from external traffic.
To intercept ingress north-south traffic:
  1. Create the Flex Gateway ingress API instance to forward all ingress north-south traffic in the `bookinfo` namespace to the `productpage` service:
     * Local Mode:
```
cat <<EOF | kubectl apply -f -
---
apiVersion: gateway.mulesoft.com/v1alpha1
kind: ApiInstance
metadata:
 name: ingress
 namespace: flex
spec:
 address: http://0.0.0.0:8081/ingress/
 services:
  productpage:
   address: http://productpage.bookinfo.svc:9080
EOF
```

     * Connected Mode:
To add an API instance in Connected Mode, see Adding a Flex Gateway API Instance.
Configure the API instance with the following downstream parameters:
       * **Protocol** : **HTTP**
       * **Port** : `8081`
       * **Base Path** : `/ingress/`
Configure the API instance with the following upstream parameters:
       * **Route label** : `productpage`
       * **Upstream URL** : `http://productpage.bookinfo.svc:9080`
  2. Create the `flex` Istio ingress gateway to forward the ingress traffic to Flex Gateway using a Istio virtual service:
    1. Create the Flex Gateway:
```
cat <<EOF | kubectl apply -f -
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
 name: flex
 namespace: flex
spec:
 selector:
  app: istio-ingress
 servers:
 - port:
   number: 80
   name: http
   protocol: HTTP
  hosts:
  - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: flex
 namespace: flex
spec:
 hosts:
 - "*"
 gateways:
 - flex
 http:
 - route:
  - destination:
    host: flex
    port:
     number: 8081
  rewrite:
   uri: /ingress/
EOF
```

    2. Wait a few seconds (approximately 10) and send a test request to the `/api/v1/products/1` page:
```
curl -v http://localhost/api/v1/products/1
```

    3. Ensure you receive this output:
```
< HTTP/1.1 200 OK
< server: istio-envoy
< date: Tue, 27 Feb 2024 22:06:33 GMT
< content-type: application/json
< content-length: 195
< x-envoy-upstream-service-time: 8
<
* Connection #0 to host localhost left intact
{"id": 2, "author": "William Shakespeare", "year": 1595, "type": "paperback", "pages": 200, "publisher": "PublisherA", "language": "English", "ISBN-10": "1234567890", "ISBN-13": "123-1234567890"}
```

  3. Protect the Flex Gateway API instance by applying the Basic Authentication policy:
    1. Add the policy:
```
cat <<EOF | kubectl apply -f -
---
apiVersion: gateway.mulesoft.com/v1alpha1
kind: ApiInstance
metadata:
 name: ingress
 namespace: flex
spec:
 address: http://0.0.0.0:8081/ingress/
 services:
  productpage:
   address: http://productpage.bookinfo.svc:9080
 policies:
 - policyRef:
   name: http-basic-authentication-flex
  config:
   username: user1
   password: password1
EOF
```

    2. Wait a few seconds (approximately 10) and send a test request:
```
curl -v http://localhost/
```
3. Protect the Flex Gateway API instance by applying the Basic Authentication policy:
    1. Add the policy:
```
cat <<EOF | kubectl apply -f -
---
apiVersion: gateway.mulesoft.com/v1alpha1
kind: ApiInstance
metadata:
 name: ingress
 namespace: flex
spec:
 address: http://0.0.0.0:8081/ingress/
 services:
  productpage:
   address: http://productpage.bookinfo.svc:9080
 policies:
 - policyRef:
   name: http-basic-authentication-flex
  config:
   username: user1
   password: password1
EOF
```

    2. Wait a few seconds (approximately 10) and send a test request:
```
curl -v http://localhost/
```

    3. Make sure you receive a `401` response.
  4. Add the Message Logging policy to log traffic:
```
cat <<EOF | kubectl apply -f -
---
apiVersion: gateway.mulesoft.com/v1alpha1
kind: ApiInstance
metadata:
 name: ingress
 namespace: flex
spec:
 address: http://0.0.0.0:8081/ingress/
 services:
  productpage:
   address: http://productpage.bookinfo.svc:9080
 policies:
 - policyRef:
   name: http-basic-authentication-flex
  config:
   username: user1
   password: password1
 - policyRef:
   name: message-logging-flex
  config:
   loggingConfiguration:
   - itemName: "Request"
    itemData:
     message: "#['> ' ++ attributes.version ++ ' ' ++ attributes.method ++ ' ' ++ attributes.headers.host ++ attributes.requestUri]"
     level: "INFO"
     firstSection: true
   - itemName: "Response"
    itemData:
     message: "#['< Status=' ++ attributes.statusCode ++ ' Length=' ++ (attributes.headers['content-length'] default 'none') ++ ' Time=' ++ (attributes.headers['x-envoy-upstream-service-time'] default 'none')]"
     level: "INFO"
     secondSection: true
  order: 0
EOF
```



## Intercept East-West Traffic Between Services
Use Flex Gateway to intercept east-west traffic between services and protect them with policies.
To intercept east-west traffic:
  1. Create the `bookinfo-reviews` API instance to forward the east-west traffic to the `reviews` service:
     * Local Mode:
```
cat <<EOF | kubectl apply -f -
---
apiVersion: gateway.mulesoft.com/v1alpha1
kind: ApiInstance
metadata:
 name: bookinfo-reviews
 namespace: flex
spec:
 address: http://0.0.0.0:8081/bookinfo/reviews/
 services:
  upstream:
   address: http://reviews.bookinfo.svc:9080
 policies:
 - policyRef:
   name: message-logging-flex
  config:
   loggingConfiguration:
   - itemName: "Request"
    itemData:
     message: "#['> ' ++ attributes.version ++ ' ' ++ attributes.method ++ ' ' ++ attributes.headers.host ++ attributes.requestUri]"
     level: "INFO"
     firstSection: true
   - itemName: "Response"
    itemData:
     message: "#['< Status=' ++ attributes.statusCode ++ ' Length=' ++ (attributes.headers['content-length'] default 'none') ++ ' Time=' ++ (attributes.headers['x-envoy-upstream-service-time'] default 'none')]"
     level: "INFO"
     secondSection: true
EOF
```

     * Connected Mode:
To add an API instance in Connected Mode, see Adding a Flex Gateway API Instance.
Configure the API instance with these downstream parameters:
       * **Protocol** : **HTTP**
       * **Port** : `8081`
       * **Base Path** : `/bookinfo/reviews/`
Configure the API instance with these upstream parameters:
       * **Route label** : `reviews`
       * **Upstream URL** : 
  2. Intercept the traffic between the `productpage` service and the `reviews` service and forward it to the `flex` service:
    1. Create the Istio API instance:
```
cat <<EOF | kubectl apply -f -
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
 name: bookinfo-reviews
 namespace: istio-system
spec:
 hosts:
 - reviews.bookinfo.svc.cluster.local
 http:
 - match:
  - sourceLabels:
    app: flex
  route:
  - destination:
    host: reviews.bookinfo.svc.cluster.local
    port:
     number: 9080
 - route:
  - destination:
    host: flex.flex.svc.cluster.local
    port:
     number: 8081
  rewrite:
   uri: /bookinfo/reviews/
EOF
```

    2. Send a test request with the `user1` username and `password1` password to the `/productpage`:
```
curl -v -u user1:password1 http://localhost/productpage
```

    3. Check the Flex Gateway logs to ensure the request sent from the `productpage` service to the `reviews` service passed through Flex Gateway. The logs appear similar to:
```
[flex-gateway-envoy][info] wasm log productpage-message-logging-flex-2.flex.productpage.flex.svc main: [policy: productpage-message-logging-flex-2.flex][api: productpage.flex.svc][req: 6e1f7c32-918d-4b6a-af3f-36a4430f80ae] [accessLog] > HTTP/1.1 GET localhost/ingress/productpage
[flex-gateway-envoy][info] wasm log bookinfo-reviews-message-logging-flex-1.flex.bookinfo-reviews.flex.svc main: [policy: bookinfo-reviews-message-logging-flex-1.flex][api: bookinfo-reviews.flex.svc][req: b23e9c64-a2aa-4464-8984-d1dd6c18f7ea] [accessLog] > HTTP/1.1 GET reviews:9080/bookinfo/reviews/reviews/0
```

Use the standard output logs for a quick log check. To learn how to view standard output logs, see Viewing Standard Output Logs.   
---  
    4. Apply the Rate Limiting policy to the `bookinfo-reviews` API instance to protect the `reviews` service:
```
cat <<EOF | kubectl apply -f -
---
apiVersion: gateway.mulesoft.com/v1alpha1
kind: ApiInstance
metadata:
 name: bookinfo-reviews
 namespace: flex
spec:
 address: http://0.0.0.0:8081/bookinfo/reviews/
 services:
  upstream:
   address: http://reviews.bookinfo.svc:9080
 policies:
 - policyRef:
   name: message-logging-flex
  config:
   loggingConfiguration:
   - itemName: "Request"
    itemData:
     message: "#['> ' ++ attributes.version ++ ' ' ++ attributes.method ++ ' ' ++ attributes.headers.host ++ attributes.requestUri]"
     level: "INFO"
     firstSection: true
   - itemName: "Response"
    itemData:
     message: "#['< Status=' ++ attributes.statusCode ++ ' Length=' ++ (attributes.headers['content-length'] default 'none') ++ ' Time=' ++ (attributes.headers['x-envoy-upstream-service-time'] default 'none')]"
     level: "INFO"
     secondSection: true
  order: 0
 - policyRef:
   name: rate-limiting-flex
  config:
   rateLimits:
   - timePeriodInMilliseconds: 60000
    maximumRequests: 2
   exposeHeaders: true
EOF
```

  3. Restrict direct access to the `bookinfo` service:
    1. Restrict access:
```
cat <<EOF | kubectl apply -f -
---
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
 name: flex-allow
 namespace: bookinfo
spec:
 action: ALLOW
 rules:
 - from:
  - source:
    namespaces:
    - flex
    - bookinfo
EOF
```

    2. Send a test request from the test namespace to the `details` service:
```
kubectl -n test exec -ti -c sleep $(kubectl -n test get pod --no-headers -o=name) -- curl -v details.bookinfo:9080/details/0
```

    3. Make sure you receive this `403 forbidden` response:
```
< HTTP/1.1 403 Forbidden
< content-length: 19
< content-type: text/plain
< date: Thu, 09 May 2024 15:51:11 GMT
< server: envoy
< x-envoy-upstream-service-time: 0
<
* Connection #0 to host details.bookinfo left intact
RBAC: access denied
```

    4. Send this request to the `details` service to find out how to access the `bookinfo` service from the `flex` namespace:
```
kubectl -n flex exec -ti -c app $(kubectl -n flex get pod --no-headers -o=name) -- flexctl check http http://details.bookinfo:9080/details/0
```

    5. Make sure you receive this response:
```
[flexctl][info] Access to http address 'http://details.bookinfo:9080/details/0': ok
```