Dela via


Säker ingressgateway för Tillägg för Istio-tjänstnät för Azure Kubernetes Service

Artikeln Distribuera extern eller intern Istio-ingress beskriver hur du konfigurerar en ingressgateway för att exponera en HTTP-tjänst för extern/intern trafik. Den här artikeln visar hur du exponerar en säker HTTPS-tjänst med enkel eller ömsesidig TLS.

Förutsättningar

Kommentar

Den här artikeln refererar till den externa ingressgatewayen för demonstration, samma steg skulle gälla för att konfigurera ömsesidig TLS för intern ingressgateway.

Nödvändiga klient-/servercertifikat och nycklar

Den här artikeln kräver flera certifikat och nycklar. Du kan använda ditt favoritverktyg för att skapa dem eller så kan du använda följande openssl-kommandon .

  1. Skapa ett rotcertifikat och en privat nyckel för signering av certifikaten för exempeltjänster:

    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. Generera ett certifikat och en privat nyckel för 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. Generera ett klientcertifikat och en privat nyckel:

    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
    

Konfigurera en TLS-ingressgateway

Skapa en Kubernetes TLS-hemlighet för ingressgatewayen. Använd Azure Key Vault som värd för certifikat/nycklar och Azure Key Vault Secrets Provider-tillägget för att synkronisera hemligheter till klustret.

Konfigurera Azure Key Vault och synkronisera hemligheter till klustret

  1. Skapa Azure Key Vault

    Du behöver en Azure Key Vault-resurs för att ange certifikatet och nyckelindata till Istio-tillägget.

    export AKV_NAME=<azure-key-vault-resource-name>  
    az keyvault create --name $AKV_NAME --resource-group $RESOURCE_GROUP --location $LOCATION
    
  2. Aktivera Azure Key Vault-providern för CSI-drivrutinstillägget för Secret Store i klustret.

    az aks enable-addons --addons azure-keyvault-secrets-provider --resource-group $RESOURCE_GROUP --name $CLUSTER
    
  3. Auktorisera den användartilldelade hanterade identiteten för tillägget för åtkomst till Azure Key Vault-resursen med hjälp av åtkomstprincip. Om ditt Key Vault använder Azure RBAC för behörighetsmodellen följer du anvisningarna här för att tilldela en Azure-roll för Key Vault för tilläggets användartilldelade hanterade identitet.

    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. Skapa hemligheter i Azure Key Vault med hjälp av certifikat och nycklar.

    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. Använd följande manifest för att distribuera SecretProviderClass för att tillhandahålla Azure Key Vault-specifika parametrar till CSI-drivrutinen.

    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. Använd följande manifest för att distribuera en exempelpodd. CSI-drivrutinen för det hemliga arkivet kräver att en podd refererar till SecretProviderClass-resursen för att säkerställa att hemligheter synkroniseras från Azure Key Vault till klustret.

    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
    
    • Verifiera productpage-credential hemligheten som skapats i klusternamnområdet aks-istio-ingress enligt definitionen i SecretProviderClass-resursen.

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

      Exempel på utdata>

      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
      

Konfigurera ingressgateway och virtuell tjänst

Dirigera HTTPS-trafik via Istio-ingressgatewayen till exempelprogrammen. Använd följande manifest för att distribuera gateway- och virtuella tjänstresurser.

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

Kommentar

I gatewaydefinitionen credentialName måste den matcha resursen secretName i SecretProviderClass och selector måste referera till den externa ingressgatewayen med dess etikett, där etikettens nyckel är istio och värdet är aks-istio-ingressgateway-external. För den interna ingressgatewayetiketten är istio och värdet är aks-istio-ingressgateway-internal.

Ange miljövariabler för extern inkommande värd och portar:

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"

Verifiering

Skicka en HTTPS-begäran för att få åtkomst till tjänsten productpage 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>"

Bekräfta att exempelprogrammets produktsida är tillgänglig. Förväntade utdata är:

<title>Simple Bookstore App</title>

Kommentar

Om du vill konfigurera HTTPS-inkommande åtkomst till en HTTPS-tjänst, d.v.s. konfigurera en ingressgateway för att utföra SNI-genomströmning i stället för TLS-avslutning på inkommande begäranden, uppdaterar du tls-läget i gatewaydefinitionen till PASSTHROUGH. Detta instruerar gatewayen att skicka inkommande trafik "som den är", utan att avsluta TLS.

Konfigurera en ömsesidig TLS-ingressgateway

Utöka gatewaydefinitionen så att den stöder ömsesidig TLS.

  1. Uppdatera ingressgatewayens autentiseringsuppgifter genom att ta bort den aktuella hemligheten och skapa en ny. Servern använder CA-certifikatet för att verifiera sina klienter, och vi måste använda nyckeln ca.crt för att lagra CA-certifikatet.

    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
    

    Använd följande manifest för att återskapa SecretProviderClass med CA-certifikat.

    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
    

    Använd följande manifest för att distribuera om exempelpodden för att synkronisera hemligheter från Azure Key Vault till klustret.

    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
    
    • Verifiera productpage-credential hemligheten som skapats på klusternamnområdet aks-istio-ingress.

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

      Exempel på utdata>

      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. Använd följande manifest för att uppdatera gatewaydefinitionen för att ställa in TLS-läget på 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
    

Verifiering

Försök att skicka HTTPS-begäran med den tidigare metoden – utan att skicka klientcertifikatet – och se att den misslyckas.

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" 

Exempel på utdata>


...
* 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

Skicka klientens certifikat med flaggan och den --cert privata nyckeln med --key flaggan för att curla.

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

Bekräfta att exempelprogrammets produktsida är tillgänglig. Förväntade utdata är:

<title>Simple Bookstore App</title>

Ta bort resurser

Om du vill rensa Istio-tjänstnätet och ingresserna (lämnar kvar klustret) kör du följande kommando:

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

Om du vill rensa alla resurser som skapats från instruktionsdokumenten för Istio kör du följande kommando:

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