مشاركة عبر


بوابة الدخول الآمنة للوظيفة الإضافية لشبكة خدمة Istio لخدمة Azure Kubernetes

توضح مقالة Deploy external or internal Istio Ingress كيفية تكوين بوابة دخول لعرض خدمة HTTP لحركة المرور الخارجية/الداخلية. توضح هذه المقالة كيفية كشف خدمة HTTPS آمنة باستخدام TLS بسيطة أو متبادلة.

المتطلبات الأساسية

إشعار

تشير هذه المقالة إلى بوابة الدخول الخارجية للعرض التوضيحي، سيتم تطبيق نفس الخطوات لتكوين TLS المتبادل لبوابة الدخول الداخلية.

شهادات ومفاتيح العميل/الخادم المطلوبة

تتطلب هذه المقالة العديد من الشهادات والمفاتيح. يمكنك استخدام الأداة المفضلة لديك لإنشائها أو يمكنك استخدام أوامر openssl التالية.

  1. إنشاء شهادة جذر ومفتاح خاص لتوقيع الشهادات لنماذج الخدمات:

    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. إنشاء شهادة ومفتاح خاص ل 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. إنشاء شهادة عميل ومفتاح خاص:

    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
    

تكوين بوابة دخول TLS

إنشاء سر Kubernetes TLS لبوابة الدخول؛ استخدم Azure Key Vault لاستضافة الشهادات/المفاتيح والوظيفة الإضافية لموفر أسرار Azure Key Vault لمزامنة الأسرار مع نظام المجموعة.

إعداد Azure Key Vault ومزامنة البيانات السرية إلى نظام المجموعة

  1. إنشاء Azure Key Vault

    تحتاج إلى مورد Azure Key Vault لتوفير الشهادة والمدخلات الرئيسية إلى الوظيفة الإضافية Istio.

    export AKV_NAME=<azure-key-vault-resource-name>  
    az keyvault create --name $AKV_NAME --resource-group $RESOURCE_GROUP --location $LOCATION
    
  2. تمكين موفر Azure Key Vault للوظيفة الإضافية لبرنامج تشغيل CSI للمخزن السري على مجموعتك.

    az aks enable-addons --addons azure-keyvault-secrets-provider --resource-group $RESOURCE_GROUP --name $CLUSTER
    
  3. تخويل الهوية المدارة المعينة من قبل المستخدم للوظيفة الإضافية للوصول إلى مورد Azure Key Vault باستخدام نهج الوصول. بدلا من ذلك، إذا كان Key Vault الخاص بك يستخدم Azure RBAC لنموذج الأذونات، فاتبع الإرشادات هنا لتعيين دور Azure ل Key Vault للهوية المدارة المعينة من قبل المستخدم للوظيفة الإضافية.

    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. إنشاء أسرار في Azure Key Vault باستخدام الشهادات والمفاتيح.

    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. استخدم البيان التالي لنشر SecretProviderClass لتوفير معلمات خاصة ب Azure Key Vault إلى برنامج تشغيل CSI.

    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. استخدم البيان التالي لنشر نموذج pod. يتطلب برنامج تشغيل CSI للمخزن السري جراب للإشارة إلى مورد SecretProviderClass لضمان مزامنة الأسرار من Azure Key Vault إلى نظام المجموعة.

    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
    
    • تحقق من productpage-credential البيانات السرية التي تم إنشاؤها على مساحة aks-istio-ingress اسم نظام المجموعة كما هو محدد في مورد SecretProviderClass.

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

      مثال على الإخراج:

      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
      

تكوين بوابة الدخول والخدمة الظاهرية

توجيه حركة مرور HTTPS عبر بوابة دخول Istio إلى نماذج التطبيقات. استخدم البيان التالي لنشر موارد البوابة والخدمة الظاهرية.

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

إشعار

في تعريف البوابة، credentialName يجب أن يتطابق secretName مع في مورد selector SecretProviderClass ويجب أن يشير إلى بوابة الدخول الخارجية بواسطة التسمية الخاصة بها، حيث يكون istio مفتاح التسمية والقيمة هي aks-istio-ingressgateway-external. بالنسبة لتسمية بوابة الدخول الداخلية هي istio والقيمة هي aks-istio-ingressgateway-internal.

تعيين متغيرات البيئة لمضيف الدخول الخارجي والمنافذ:

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"

التحقق من الصحة

إرسال طلب HTTPS للوصول إلى خدمة صفحة المنتج من خلال 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>"

تأكد من إمكانية الوصول إلى صفحة منتج نموذج التطبيق. الإخراج المتوقع هو:

<title>Simple Bookstore App</title>

إشعار

لتكوين الوصول إلى دخول HTTPS إلى خدمة HTTPS، أي تكوين بوابة دخول لتنفيذ تمرير SNI بدلا من إنهاء TLS على الطلبات الواردة، قم بتحديث وضع tls في تعريف البوابة إلى PASSTHROUGH. هذا يوجه البوابة لتمرير حركة مرور الدخول "كما هي"، دون إنهاء TLS.

تكوين بوابة دخول TLS متبادلة

توسيع تعريف البوابة لدعم TLS المتبادل.

  1. تحديث بيانات اعتماد بوابة الدخول عن طريق حذف السر الحالي وإنشاء سر جديد. يستخدم الخادم شهادة المرجع المصدق للتحقق من عملائه، ويجب علينا استخدام المفتاح 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
    

    استخدم البيان التالي لإعادة إنشاء SecretProviderClass مع شهادة CA.

    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
    

    استخدم البيان التالي لإعادة نشر نموذج pod لمزامنة البيانات السرية من Azure Key Vault إلى نظام المجموعة.

    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
    
    • تحقق من productpage-credential البيانات السرية التي تم إنشاؤها على مساحة aks-istio-ingressاسم نظام المجموعة .

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

      مثال على الإخراج:

      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. استخدم البيان التالي لتحديث تعريف البوابة لتعيين وضع TLS إلى 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
    

التحقق من الصحة

حاول إرسال طلب HTTPS باستخدام النهج السابق - دون تمرير شهادة العميل - واطلع على فشلها.

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" 

مثال على الإخراج:


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

مرر شهادة العميل مع العلامة --cert والمفتاح الخاص مع العلامة --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>"

تأكد من إمكانية الوصول إلى صفحة منتج نموذج التطبيق. الإخراج المتوقع هو:

<title>Simple Bookstore App</title>

حذف الموارد

إذا كنت ترغب في تنظيف شبكة خدمة Istio والدخول (تاركا وراءها نظام المجموعة)، فقم بتشغيل الأمر التالي:

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

إذا كنت ترغب في تنظيف جميع الموارد التي تم إنشاؤها من مستندات إرشادات Istio الإرشادية، فقم بتشغيل الأمر التالي:

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