aks istio securing gateway service mesh with tls

 



Enable secret provider class if you haven't done so. 


export RESOURCE_GROUP=istio-rg
export AKV_NAME=istio-kv-dev
export LOCATION=australiaeast
export CLUSTER=my-istio-cluster

az keyvault create --name $AKV_NAME --resource-group $RESOURCE_GROUP --location $LOCATION

az aks enable-addons --addons azure-keyvault-secrets-provider --resource-group $RESOURCE_GROUP --name $CLUSTER

Grant all the role assignment to the user you're using so we can store the following into our keyvault.

Once you have enable it, please deploy the book sample application:

kubectl label namespace default istio.io/rev=asm-1-22

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.18/samples/bookinfo/platform/kube/bookinfo.yaml

Next create the relevant secret for your keyvault

az keyvault secret set --vault-name $AKV_NAME --name test-productpage-bookinfo-key --file bookinfo_certs/productpage.bookinfo.com.key
az keyvault secret set --vault-name $AKV_NAME --name test-productpage-bookinfo-crt --file bookinfo_certs/productpage.bookinfo.com.crt
az keyvault secret set --vault-name $AKV_NAME --name test-bookinfo-crt --file bookinfo_certs/bookinfo.com.crt



My secret provider class to extract certificate details looks like this (please provide your tenant id below). We are creating a tls secret and that is what istio expects to find when we configure its gateway below.

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: productpage-credential-spc
  namespace: aks-istio-ingress
spec:
  provider: azure
  secretObjects:
  - secretName: productpage-credential
    type: tls
    data:
    - objectName: test-productpage-bookinfo-key
      key: key
    - objectName: test-productpage-bookinfo-crt
      key: cert
  parameters:
    useVMManagedIdentity: "true"
    userAssignedIdentityID: c113f45a-4300-451e-ba7b-d772ac16a988
    keyvaultName: istio-kv-dev
    cloudName: ""
    objects:  |
      array:
        - |
          objectName: test-productpage-bookinfo-key
          objectType: secret
          objectAlias: "test-productpage-bookinfo-key"
        - |
          objectName: test-productpage-bookinfo-crt
          objectType: secret
          objectAlias: "test-productpage-bookinfo-crt"
    tenantId: provide-your-tenant-id

And after that we can see the secrets being created -

Proceed to apply the following yaml to configure tls to your istio gateway.

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: aks-istio-ingressgateway-external
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: productpage-credential
    hosts:
    - productpage.bookinfo.com
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: productpage-vs
spec:
  hosts:
  - productpage.bookinfo.com
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        port:
          number: 9080
        host: productpage

Then look at the output here:-



To validate run the following command

curl -s -HHost:productpage.bookinfo.com --resolve "productpage.bookinfo.com:$SECURE_INGRESS_PORT_EXTERNAL:$INGRESS_HOST_EXTERNAL" --cacert bookinfo_certs/bookinfo.com.crt "https://productpage.bookinfo.com:$SECURE_INGRESS_PORT_EXTERNAL/productpage" | grep -o "<title>.*</title>"

And you will get the following outputs



Configuring mutual TLS.

Run the following command to remove secret and resources earlier 


kubectl delete secretproviderclass productpage-credential-spc -n aks-istio-ingress
kubectl delete secret/productpage-credential -n aks-istio-ingress
kubectl delete pod/secrets-store-sync-productpage -n aks-istio-ingress


Then reconfigure using the following yamls 


apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: productpage-credential-spc
  namespace: aks-istio-ingress
spec:
  provider: azure
  secretObjects:
  - secretName: productpage-credential
    type: opaque
    data:
    - objectName: test-productpage-bookinfo-key
      key: tls.key
    - objectName: test-productpage-bookinfo-crt
      key: tls.crt
    - objectName: test-bookinfo-crt
      key: ca.crt
  parameters:
    useVMManagedIdentity: "true"
    userAssignedIdentityID: c113f45a-4300-451e-ba7b-d772ac16a988
    keyvaultName: istio-kv-dev
    cloudName: ""
    objects:  |
      array:
        - |
          objectName: test-productpage-bookinfo-key
          objectType: secret
          objectAlias: "test-productpage-bookinfo-key"
        - |
          objectName: test-productpage-bookinfo-crt
          objectType: secret
          objectAlias: "test-productpage-bookinfo-crt"
        - |
          objectName: test-bookinfo-crt
          objectType: secret
          objectAlias: "test-bookinfo-crt"
    tenantId: your-tenant-id


Notice that we're passing test-bookinfo-crt

  - objectName: test-bookinfo-crt
      key: ca.crt


Let's check out our secrets by running the following command:

kubectl describe secret/productpage-credential -n aks-istio-ingress




Let's update our gateway to include support mutual tls.

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: aks-istio-ingressgateway-external # use istio default ingress gateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: MUTUAL
      credentialName: productpage-credential # must be the same as secret
    hosts:
    - productpage.bookinfo.com

And if we were to hit its endpoint without providing client certificate, then it will fail 

curl -v -HHost:productpage.bookinfo.com --resolve "productpage.bookinfo.com:$SECURE_INGRESS_PORT_EXTERNAL:$INGRESS_HOST_EXTERNAL" --cacert bookinfo_certs/bookinfo.com.crt "https://productpage.bookinfo.com:$SECURE_INGRESS_PORT_EXTERNAL/productpage"




If we pass in client certificate like so,

curl -s -HHost:productpage.bookinfo.com --resolve "productpage.bookinfo.com:$SECURE_INGRESS_PORT_EXTERNAL:$INGRESS_HOST_EXTERNAL" --cacert bookinfo_certs/bookinfo.com.crt --cert bookinfo_certs/client.bookinfo.com.crt --key bookinfo_certs/client.bookinfo.com.key "https://productpage.bookinfo.com:$SECURE_INGRESS_PORT_EXTERNAL/productpage" | grep -o "<title>.*</title>"

Then it will pass



Can we have more than one client certificate configure for your gateway? 

https://medium.com/microsoftazure/certificate-pinning-for-mtls-authentication-at-the-istio-ingress-gateway-978ed31699ab#:~:text=Conclusion,level%20of%20trust%20as%20needed.



Comments

Popular posts from this blog

The specified initialization vector (IV) does not match the block size for this algorithm