Configure Gateways to use Aspen Mesh minted certificates#

This guide describes the process of consuming Aspen Mesh certificates by Gateways to terminate TLS traffic coming from end user clients. By default, all Aspen Mesh generated certificates only include SPIFFE URI in SAN which is not compatible with end user clients like browsers or curl. Adding SAN entries in certificates enables you to terminate TLS traffic coming from browsers and other end user clients at Aspen Mesh gateways.

The functionality provided by Aspen Mesh will enable you to have your Certificate Authority (CA) certificates be used to sign certificates for TLS termination at your gateway. The key benefit of using this capability is that the lifecycle and rotations of this certificate will be managed by Aspen Mesh.

Prerequisites#

DNS name is configured to point to the cluster via A, ALIAS, or CNAME records

Setup#

  1. Follow the instructions for enabling Mesh Workload Certificates with SAN DNS and URI entries.

  2. Follow the instructions for Consuming Aspen Mesh certificates via Kubernetes Secrets API to enable Aspen Mesh Citadel.

  3. Ensure that the ingress gateway chart has been deployed successfully to your cluster.

    $ helm ls -A | grep 'istio-ingress'
    
  4. Create or modify a Service Account in the namespace where your ingress gateway was deployed to include the following annotation, which includes the domain your gateway will serve:

    metadata:
      annotations:
        "certificate.aspenmesh.io/customFields": '{ "SAN": { "DNS": [ "YOUR_DOMAIN_HERE" ] } }'
    
  5. Aspen Mesh Citadel will create a secret named istio.<YOUR SERVICE ACCOUNT NAME> in that namespace.

  6. Add or modify your Gateway resource to reference this secret

    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    ...
    - port:
        number: 443
        name: https
        protocol: HTTPS
      tls:
        mode: SIMPLE
        credentialName: istio.<YOUR SERVICE ACCOUNT NAME>
    
  7. This secret’s lifecycle, including rotation, will be handled by Aspen Mesh Citadel.

  8. Create or modify a VirtualService associated with the service you wish to expose and connect it to the Gateway resource. You can follow the example below for a step-by-step guide.

Example Deployment#

Here you will deploy a copy of the httpbin application from the samples directory found in the Aspen Mesh install directory and expose it via the ingress gateway using the certificate generated from Aspen Mesh Citadel based on httpbin’s Service Account. These steps assume that Aspen Mesh has been installed into the cluster and that the current directory is the root of the extracted installation archive.

Note

This example assumes you have deployed your own CA certificates for use within the cluster and that Aspen Mesh Citadel has been enabled and deployed.

  1. Create an httpbin namespace where the httpbin application will be deployed:

    $ kubectl create namespace httpbin
    
  2. Enable Istio Sidecar injection in the httpbin namespace

    $ kubectl label namespace httpbin istio-injection=enabled
    
  3. Add to the namespace the label ca.istio.io/override to have Aspen Mesh Citadel generate secrets for Service Accounts

    $ kubectl label --overwrite namespace httpbin ca.istio.io/override=true
    
  4. Deploy the ingressgateway chart to the httpbin namespace

    $ helm install httpbin-ingress manifests/charts/gateways/istio-ingress \
        --namespace httpbin --values <YOUR OVERRIDES>
    
  5. Store the domain your gateway will serve as a variable within bash. Modify the value to your domain.

    $ export MY_DOMAIN=YOUR_DOMAIN_HERE
    
  6. Deploy the httpbin application to the httpbin namespace. Note that service account has been augmented to provide certificate annotations.

    $ cat <<EOF | kubectl apply -n httpbin -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: httpbin
      annotations:
        "certificate.aspenmesh.io/customFields": '{ "SAN": { "DNS": [ "$MY_DOMAIN" ] } }'
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      labels:
        app: httpbin
    spec:
      ports:
      - name: http
        port: 8000
        targetPort: 80
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          serviceAccountName: httpbin
          containers:
          - image: docker.io/kennethreitz/httpbin
            imagePullPolicy: IfNotPresent
            name: httpbin
            ports:
            - containerPort: 80
    EOF
    
  7. Verify that the secret istio.httpbin is created for the service account httpbin associated with the httpbin deployment:

    $ kubectl get secret istio.httpbin -n httpbin
    
    NAME            TYPE                    DATA   AGE
    istio.httpbin   istio.io/key-and-cert   3      1m
    
  8. Verify that the certificate contains an extension for SAN using the domain you specified above:

    $ kubectl get secret -n httpbin istio.httpbin -o yaml | \
        yq r - 'data."cert"' | base64 --decode | openssl x509 -noout -text
    
    Certificate:
       Data:
       ...
                X509v3 Subject Alternative Name: critical
                    URI:spiffe://cluster.local/ns/httpbin/sa/httpbin, DNS:YOUR_DOMAIN_HERE
    
  9. Deploy the following Gateway and Virtual Service to your cluster to enable routing of traffic from the ingress gateway to the httpbin workload:

    $ cat <<EOF | kubectl apply -n httpbin -f -
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: httpbin-gateway
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 443
          name: https
          protocol: HTTPS
        tls:
          mode: SIMPLE
          credentialName: istio.httpbin
        hosts:
        - "*"
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: httpbin
    spec:
      hosts:
      - "*"
      gateways:
      - httpbin-gateway
      http:
      - route:
        - destination:
            host: httpbin
            port:
              number: 8000
    EOF
    
  10. Fetch and store the ingress hostname that your ingressgateway is listening on so that we can send requests to the httpbin application:

    $ export INGRESS_HOST=$(kubectl -n httpbin get service istio-ingressgateway \
        -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    
  11. You can inspect the certificate presented by the ingress gateway using the openssl tool:

    $ echo | openssl s_client -showcerts -connect $INGRESS_HOST:443 2>/dev/null | \
        openssl x509 -inform pem -noout -text
    
    Certificate:
        Data:
        ...
          Validity
              Not Before: Nov 12 03:24:14 2020 GMT
              Not After : Nov 13 03:24:14 2020 GMT
        ...
                    URI:spiffe://cluster.local/ns/httpbin/sa/httpbin, DNS:YOUR_DOMAIN_HERE
    
  12. Congratulations, you’ve now setup Aspen Mesh to serve the managed istio.httpbin secret to clients of your gateway!