Sdílet prostřednictvím


Zabezpečený doplněk ingress gateway for Istio Service Mesh pro Azure Kubernetes Service

Článek Nasazení externího nebo interního příchozího přenosu dat Istio popisuje, jak nakonfigurovat bránu příchozího přenosu dat tak, aby zpřístupnil službu HTTP externímu nebo internímu provozu. Tento článek ukazuje, jak zveřejnit zabezpečenou službu HTTPS pomocí jednoduchého nebo vzájemného protokolu TLS.

Požadavky

Poznámka:

Tento článek se týká externí brány příchozího přenosu dat pro ukázku. Stejný postup by se použil ke konfiguraci vzájemného protokolu TLS pro interní bránu příchozího přenosu dat.

Požadované certifikáty klienta/serveru a klíče

Tento článek vyžaduje několik certifikátů a klíčů. Pomocí svého oblíbeného nástroje je můžete vytvořit nebo můžete použít následující příkazy openssl .

  1. Vytvořte kořenový certifikát a privátní klíč pro podepisování certifikátů pro ukázkové služby:

    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. Vygenerujte certifikát a privátní klíč pro 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. Vygenerujte klientský certifikát a privátní klíč:

    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
    

Konfigurace brány příchozího přenosu dat TLS

Vytvoření tajného klíče protokolu TLS Kubernetes pro bránu příchozího přenosu dat; Azure Key Vault slouží k hostování certifikátů a klíčů a doplňků zprostředkovatele tajných kódů služby Azure Key Vault k synchronizaci tajných kódů do clusteru.

Nastavení služby Azure Key Vault a synchronizace tajných kódů do clusteru

  1. Vytvoření služby Azure Key Vault

    K zadání certifikátu a vstupů klíčů do doplňku Istio potřebujete prostředek služby Azure Key Vault.

    export AKV_NAME=<azure-key-vault-resource-name>  
    az keyvault create --name $AKV_NAME --resource-group $RESOURCE_GROUP --location $LOCATION
    
  2. Povolte ve svém clusteru zprostředkovatele služby Azure Key Vault doplněk Ovladače CSI pro úložiště tajných kódů.

    az aks enable-addons --addons azure-keyvault-secrets-provider --resource-group $RESOURCE_GROUP --name $CLUSTER
    
  3. Autorizuje spravovanou identitu přiřazenou uživatelem doplňku pro přístup k prostředku služby Azure Key Vault pomocí zásad přístupu. Případně pokud služba Key Vault pro model oprávnění používá Azure RBAC, přiřaďte roli Azure Key Vault pro spravovanou identitu přiřazenou uživatelem podle těchto pokynů.

    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. Vytvářejte tajné kódy ve službě Azure Key Vault pomocí certifikátů a klíčů.

    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. Pomocí následujícího manifestu nasaďte SecretProviderClass a poskytněte ovladači CSI specifické parametry služby Azure Key Vault.

    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. K nasazení ukázkového podu použijte následující manifest. Ovladač CSI úložiště tajných kódů vyžaduje pod, který odkazuje na prostředek SecretProviderClass, aby se zajistila synchronizace tajných kódů ze služby Azure Key Vault do clusteru.

    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
    
    • Ověřte productpage-credential tajný klíč vytvořený v oboru názvů aks-istio-ingress clusteru definovaný v prostředku SecretProviderClass.

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

      Příklad výstupu:

      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
      

Konfigurace brány příchozího přenosu dat a virtuální služby

Směrujte provoz HTTPS přes bránu příchozího přenosu dat Istio do ukázkových aplikací. Pomocí následujícího manifestu nasaďte prostředky brány a virtuální služby.

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

Poznámka:

V definici credentialName brány musí odpovídat secretName prostředku SecretProviderClass a selector musí odkazovat na externí příchozí bránu pomocí jeho popisku, ve kterém je istio klíč popisku a hodnota je aks-istio-ingressgateway-external. Pro interní popisek brány příchozího přenosu dat je istio a hodnota je aks-istio-ingressgateway-internal.

Nastavte proměnné prostředí pro hostitele a porty externího příchozího přenosu dat:

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"

Ověření

Odešlete požadavek HTTPS pro přístup ke službě productpage prostřednictvím protokolu 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>"

Ověřte, že je stránka produktu ukázkové aplikace přístupná. Očekávaný výstup je:

<title>Simple Bookstore App</title>

Poznámka:

Pokud chcete nakonfigurovat přístup příchozího přenosu dat HTTPS ke službě HTTPS, tj. nakonfigurujte bránu příchozího přenosu dat tak, aby prováděla předávání SNI místo ukončení protokolu TLS u příchozích požadavků, aktualizujte režim tls v definici brány na PASSTHROUGH. To dává bráně pokyn, aby předával příchozí provoz "tak, jak je", aniž by ukončoval protokol TLS.

Konfigurace vzájemné brány příchozího přenosu dat TLS

Rozšiřte definici brány tak, aby podporovala vzájemné tls.

  1. Aktualizujte přihlašovací údaje brány příchozího přenosu dat odstraněním aktuálního tajného kódu a vytvořením nového. Server používá certifikát certifikační autority k ověření svých klientů a k uložení certifikátu certifikační autority musíme použít klíč ca.crt.

    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
    

    Pomocí následujícího manifestu znovu vytvořte SecretProviderClass s certifikátem certifikační autority.

    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
    

    Pomocí následujícího manifestu znovu nasaďte ukázkový pod pro synchronizaci tajných kódů ze služby Azure Key Vault do clusteru.

    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
    
    • Ověřte productpage-credential tajný klíč vytvořený v oboru názvů aks-istio-ingressclusteru .

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

      Příklad výstupu:

      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. Pomocí následujícího manifestu aktualizujte definici brány tak, aby nastavil režim TLS na VZÁJEMNÉ.

    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
    

Ověření

Pokus o odeslání požadavku HTTPS pomocí předchozího přístupu bez předání klientského certifikátu – a zobrazení se nezdaří.

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" 

Příklad výstupu:


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

Předejte certifikát klienta s příznakem --cert a privátním klíčem s příznakem --key 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>"

Ověřte, že je stránka produktu ukázkové aplikace přístupná. Očekávaný výstup je:

<title>Simple Bookstore App</title>

Odstranění prostředků

Pokud chcete vyčistit síť služby Istio a příchozí přenos dat (opouští se za clusterem), spusťte následující příkaz:

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

Pokud chcete vyčistit všechny prostředky vytvořené z dokumentů s postupy istio, spusťte následující příkaz:

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