Delen via


Beveiligde toegangsgateway voor invoegtoepassing voor Istio-service-mesh voor Azure Kubernetes Service

In het artikel Externe of interne Istio Inkomend verkeer implementeren wordt beschreven hoe u een toegangsgateway configureert om een HTTP-service beschikbaar te maken voor extern/intern verkeer. In dit artikel wordt beschreven hoe u een beveiligde HTTPS-service beschikbaar maakt met behulp van eenvoudige of wederzijdse TLS.

Vereisten

Notitie

Dit artikel verwijst naar de externe ingangsgateway voor demonstratie. Dezelfde stappen zijn van toepassing op het configureren van wederzijdse TLS voor interne toegangsgateway.

Vereiste client-/servercertificaten en -sleutels

Voor dit artikel zijn verschillende certificaten en sleutels vereist. U kunt uw favoriete hulpprogramma gebruiken om ze te maken of u kunt de volgende openssl-opdrachten gebruiken.

  1. Maak een basiscertificaat en een persoonlijke sleutel voor het ondertekenen van de certificaten voor voorbeeldservices:

    mkdir bookinfo_certs
    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=bookinfo Inc./CN=bookinfo.com' -keyout bookinfo_certs/bookinfo.com.key -out bookinfo_certs/bookinfo.com.crt
    
  2. Genereer een certificaat en een persoonlijke sleutel voor productpage.bookinfo.com:

    openssl req -out bookinfo_certs/productpage.bookinfo.com.csr -newkey rsa:2048 -nodes -keyout bookinfo_certs/productpage.bookinfo.com.key -subj "/CN=productpage.bookinfo.com/O=product organization"
    openssl x509 -req -sha256 -days 365 -CA bookinfo_certs/bookinfo.com.crt -CAkey bookinfo_certs/bookinfo.com.key -set_serial 0 -in bookinfo_certs/productpage.bookinfo.com.csr -out bookinfo_certs/productpage.bookinfo.com.crt
    
  3. Genereer een clientcertificaat en een persoonlijke sleutel:

    openssl req -out bookinfo_certs/client.bookinfo.com.csr -newkey rsa:2048 -nodes -keyout bookinfo_certs/client.bookinfo.com.key -subj "/CN=client.bookinfo.com/O=client organization"
    openssl x509 -req -sha256 -days 365 -CA bookinfo_certs/bookinfo.com.crt -CAkey bookinfo_certs/bookinfo.com.key -set_serial 1 -in bookinfo_certs/client.bookinfo.com.csr -out bookinfo_certs/client.bookinfo.com.crt
    

Een TLS-ingangsgateway configureren

Maak een Kubernetes TLS-geheim voor de toegangsbeheergateway; Gebruik Azure Key Vault om certificaten/sleutels en azure Key Vault Secrets Provider-invoegtoepassing te hosten om geheimen te synchroniseren met het cluster.

Azure Key Vault instellen en geheimen synchroniseren met het cluster

  1. Azure Key Vault maken

    U hebt een Azure Key Vault-resource nodig om het certificaat en de sleutelinvoer op te geven aan de Istio-invoegtoepassing.

    export AKV_NAME=<azure-key-vault-resource-name>  
    az keyvault create --name $AKV_NAME --resource-group $RESOURCE_GROUP --location $LOCATION
    
  2. Schakel de Azure Key Vault-provider in voor de invoegtoepassing CSI-stuurprogramma secret store in uw cluster.

    az aks enable-addons --addons azure-keyvault-secrets-provider --resource-group $RESOURCE_GROUP --name $CLUSTER
    
  3. Autoriseren van de door de gebruiker toegewezen beheerde identiteit van de invoegtoepassing voor toegang tot Azure Key Vault-resource met behulp van toegangsbeleid. Als uw Key Vault Azure RBAC gebruikt voor het machtigingsmodel, volgt u de instructies hier om een Azure-rol van Key Vault toe te wijzen voor de door de gebruiker toegewezen beheerde identiteit van de invoegtoepassing.

    OBJECT_ID=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER --query 'addonProfiles.azureKeyvaultSecretsProvider.identity.objectId' -o tsv | tr -d '\r')
    CLIENT_ID=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER --query 'addonProfiles.azureKeyvaultSecretsProvider.identity.clientId')
    TENANT_ID=$(az keyvault show --resource-group $RESOURCE_GROUP --name $AKV_NAME --query 'properties.tenantId')
    
    az keyvault set-policy --name $AKV_NAME --object-id $OBJECT_ID --secret-permissions get list
    
  4. Geheimen maken in Azure Key Vault met behulp van de certificaten en sleutels.

    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
    
  5. Gebruik het volgende manifest om SecretProviderClass te implementeren om azure Key Vault-specifieke parameters op te geven voor het CSI-stuurprogramma.

    cat <<EOF | kubectl apply -f -
    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: $CLIENT_ID 
        keyvaultName: $AKV_NAME
        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: $TENANT_ID
    EOF
    
  6. Gebruik het volgende manifest om een voorbeeldpod te implementeren. Het CSI-stuurprogramma voor het geheimarchief vereist een pod om te verwijzen naar de SecretProviderClass-resource om ervoor te zorgen dat geheimen worden gesynchroniseerd van Azure Key Vault naar het cluster.

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: secrets-store-sync-productpage
      namespace: aks-istio-ingress
    spec:
      containers:
        - name: busybox
          image: mcr.microsoft.com/oss/busybox/busybox:1.33.1
          command:
            - "/bin/sleep"
            - "10"
          volumeMounts:
          - name: secrets-store01-inline
            mountPath: "/mnt/secrets-store"
            readOnly: true
      volumes:
        - name: secrets-store01-inline
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: "productpage-credential-spc"
    EOF
    
    • Controleer of productpage-credential het geheim dat is gemaakt in de clusternaamruimte aks-istio-ingress , zoals gedefinieerd in de SecretProviderClass-resource.

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

      Voorbeelduitvoer:

      Name:         productpage-credential
      Namespace:    aks-istio-ingress
      Labels:       secrets-store.csi.k8s.io/managed=true
      Annotations:  <none>
      
      Type:  tls
      
      Data
      ====
      cert:  1066 bytes
      key:   1704 bytes
      

Toegangsbeheerobjectgateway en virtuele service configureren

Routeer HTTPS-verkeer via de Ingress-gateway van Istio naar de voorbeeldtoepassingen. Gebruik het volgende manifest om gateway- en virtuele-servicebronnen te implementeren.

cat <<EOF | kubectl apply -f -
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
EOF

Notitie

In de gatewaydefinitie credentialName moet deze overeenkomen met de secretName in SecretProviderClass-resource en selector moet deze verwijzen naar de externe ingangsgateway op basis van het label, waarin de sleutel van het label is istio en de waarde is aks-istio-ingressgateway-external. Voor intern inkomend gatewaylabel is istio en de waarde is aks-istio-ingressgateway-internal.

Omgevingsvariabelen instellen voor externe ingangshost en poorten:

export INGRESS_HOST_EXTERNAL=$(kubectl -n aks-istio-ingress get service aks-istio-ingressgateway-external -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export SECURE_INGRESS_PORT_EXTERNAL=$(kubectl -n aks-istio-ingress get service aks-istio-ingressgateway-external -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
export SECURE_GATEWAY_URL_EXTERNAL=$INGRESS_HOST_EXTERNAL:$SECURE_INGRESS_PORT_EXTERNAL

echo "https://$SECURE_GATEWAY_URL_EXTERNAL/productpage"

Verificatie

Een HTTPS-aanvraag verzenden voor toegang tot de productpaginaservice via HTTPS:

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>"

Controleer of de productpagina van de voorbeeldtoepassing toegankelijk is. De verwachte uitvoer is:

<title>Simple Bookstore App</title>

Notitie

Als u toegang voor inkomend HTTPS-verkeer tot een HTTPS-service wilt configureren, configureert u een gateway voor inkomend verkeer om SNI-passthrough uit te voeren in plaats van TLS-beëindiging voor binnenkomende aanvragen, werkt u de TLS-modus in de gatewaydefinitie bij naar PASSTHROUGH. Hiermee wordt de gateway geïnstrueerd om het inkomend verkeer 'zoals is' door te geven zonder TLS te beëindigen.

Een wederzijdse TLS-ingangsgateway configureren

Breid uw gatewaydefinitie uit om wederzijdse TLS te ondersteunen.

  1. Werk de referentie voor de toegangsbeheergateway bij door het huidige geheim te verwijderen en een nieuw geheim te maken. De server gebruikt het CA-certificaat om de clients te verifiëren en we moeten de sleutel ca.crt gebruiken om het CA-certificaat te bewaren.

    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
    

    Gebruik het volgende manifest om SecretProviderClass opnieuw te maken met een CA-certificaat.

    cat <<EOF | kubectl apply -f -
    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: $CLIENT_ID 
        keyvaultName: $AKV_NAME
        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: $TENANT_ID
    EOF
    

    Gebruik het volgende manifest om een voorbeeldpod opnieuw te implementeren om geheimen van Azure Key Vault naar het cluster te synchroniseren.

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: secrets-store-sync-productpage
      namespace: aks-istio-ingress
    spec:
      containers:
        - name: busybox
          image: registry.k8s.io/e2e-test-images/busybox:1.29-4
          command:
            - "/bin/sleep"
            - "10"
          volumeMounts:
          - name: secrets-store01-inline
            mountPath: "/mnt/secrets-store"
            readOnly: true
      volumes:
        - name: secrets-store01-inline
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: "productpage-credential-spc"
    EOF
    
    • Controleer het productpage-credential geheim dat is gemaakt in de clusternaamruimte aks-istio-ingress.

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

      Voorbeelduitvoer:

      Name:         productpage-credential
      Namespace:    aks-istio-ingress
      Labels:       secrets-store.csi.k8s.io/managed=true
      Annotations:  <none>
      
      Type:  opaque
      
      Data
      ====
      ca.crt:   1188 bytes
      tls.crt:  1066 bytes
      tls.key:  1704 bytes
      
  2. Gebruik het volgende manifest om de gatewaydefinitie bij te werken om de TLS-modus in te stellen op MUTUAL.

    cat <<EOF | kubectl apply -f -
    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
    EOF
    

Verificatie

Probeer een HTTPS-aanvraag te verzenden met behulp van de voorgaande methode, zonder het clientcertificaat door te geven, en zie dat deze mislukt.

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" 

Voorbeelduitvoer:


...
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS alert, unknown (628):
* OpenSSL SSL_read: error:0A00045C:SSL routines::tlsv13 alert certificate required, errno 0
* Failed receiving HTTP2 data
* OpenSSL SSL_write: SSL_ERROR_ZERO_RETURN, errno 0
* Failed sending HTTP2 data
* Connection #0 to host productpage.bookinfo.com left intact
curl: (56) OpenSSL SSL_read: error:0A00045C:SSL routines::tlsv13 alert certificate required, errno 0

Geef het certificaat van uw client door met de --cert vlag en de persoonlijke sleutel met de --key vlag aan curl.

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>"

Controleer of de productpagina van de voorbeeldtoepassing toegankelijk is. De verwachte uitvoer is:

<title>Simple Bookstore App</title>

Resources verwijderen

Als u de Istio-service-mesh en de ingresses (achter het cluster) wilt opschonen, voert u de volgende opdracht uit:

az aks mesh disable --resource-group ${RESOURCE_GROUP} --name ${CLUSTER}

Als u alle resources wilt opschonen die zijn gemaakt op basis van de Istio instructiedocumenten, voert u de volgende opdracht uit:

az group delete --name ${RESOURCE_GROUP} --yes --no-wait