共用方式為


具有適用於容器的應用程式閘道的前端 MTLS - 閘道 API

本文將透過範例,說明如何使用閘道 API 中的下列資源建立應用程式。 其中提供下列作業的步驟:

背景

相互傳輸層安全性 (MTLS) 是依賴憑證來加密通訊並識別服務用戶端的流程。 這可讓適用於容器的應用程式閘道只信任來自已驗證裝置的連線,進一步提升其安全性態勢。

請參閱下圖:

顯示適用於容器的應用程式閘道前端 MTLS 流程的圖表。

有效的用戶端憑證流程會顯示向適用於容器的應用程式閘道前端出示憑證的用戶端。 適用於容器的應用程式閘道會判斷憑證有效,並將要求 Proxy 傳送至後端目標。 回應最終會傳回至用戶端。

已撤銷的用戶端憑證流程會顯示向適用於容器的應用程式閘道前端出示撤銷憑證的用戶端。 適用於容器的應用程式閘道會判斷憑證無效,並防止要求被 Proxy 傳送至用戶端。 用戶端會收到 HTTP 400 不正確的要求和對應的原因。

必要條件

  1. 如果遵循 BYO 部署策略,請確定您已設定適用於容器的應用程式閘道資源和 ALB 控制器

  2. 如果遵循 ALB 受管理的部署策略,請確定您已透過 ApplicationLoadBalancer 自訂資源佈建 ALB 控制器 以及適用於容器的應用程式閘道資源。

  3. 部署範例 HTTP 應用程式:

    在您的叢集上套用下列 deployment.yaml 檔案,以建立範例 Web 應用程式,並部署範例祕密來示範前端相互驗證 (mTLS)。

    kubectl apply -f https://raw.githubusercontent.com/MicrosoftDocs/azure-docs/refs/heads/main/articles/application-gateway/for-containers/examples/https-scenario/ssl-termination/deployment.yaml
    

    此指令會在您的叢集上建立下列物件:

    • 名為 test-infra 的命名空間
    • echo 命名空間中名為 test-infra 的一個服務
    • echo 命名空間中名為 test-infra 的一個部署
    • listener-tls-secret 命名空間中名為 test-infra 的一個祕密

產生憑證

針對此範例,我們將建立根憑證,並從根憑證發出用戶端憑證。 如果您已經有根憑證和用戶端憑證,則可以跳過這些步驟。

產生根憑證的私密金鑰

openssl genrsa -out root.key 2048

產生根憑證

openssl req -x509 -new -nodes -key root.key -sha256 -days 1024 -out root.crt -subj "/C=US/ST=North Dakota/L=Fargo/O=Contoso/CN=contoso-root"

產生用戶端憑證的私密金鑰

openssl genrsa -out client.key 2048

建立用戶端憑證的憑證簽署要求

openssl req -new -key client.key -out client.csr -subj "/C=US/ST=North Dakota/L=Fargo/O=Contoso/CN=contoso-client"

產生由根憑證簽署的用戶端憑證

openssl x509 -req -in client.csr -CA root.crt -CAkey root.key -CAcreateserial -out client.crt -days 1024 -sha256

部署必要的閘道 API 資源

建立閘道

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway-01
  namespace: test-infra
  annotations:
    alb.networking.azure.io/alb-namespace: alb-test-infra
    alb.networking.azure.io/alb-name: alb-test
spec:
  gatewayClassName: azure-alb-external
  listeners:
  - name: mtls-listener
    port: 443
    protocol: HTTPS
    allowedRoutes:
      namespaces:
        from: Same
    tls:
      mode: Terminate
      certificateRefs:
      - kind : Secret
        group: ""
        name: listener-tls-secret
EOF

注意

當 ALB 控制器在 Azure Resource Manager 中建立容器資源的應用程式閘道時,它會針對前端資源使用下列命名慣例: fe-<eight randomly generated characters>

如果您想要變更在 Azure 中建立的前端資源名稱,請考慮遵循 自備部署策略

建立閘道資源之後,請確定狀態有效,接聽程式的狀態為 [已程式化],並且已經將位址指派給閘道。

kubectl get gateway gateway-01 -n test-infra -o yaml

成功建立閘道後的範例輸出:

status:
  addresses:
  - type: IPAddress
    value: xxxx.yyyy.alb.azure.com
  conditions:
  - lastTransitionTime: "2023-06-19T21:04:55Z"
    message: Valid Gateway
    observedGeneration: 1
    reason: Accepted
    status: "True"
    type: Accepted
  - lastTransitionTime: "2023-06-19T21:04:55Z"
    message: Application Gateway For Containers resource has been successfully updated.
    observedGeneration: 1
    reason: Programmed
    status: "True"
    type: Programmed
  listeners:
  - attachedRoutes: 0
    conditions:
    - lastTransitionTime: "2023-06-19T21:04:55Z"
      message: ""
      observedGeneration: 1
      reason: ResolvedRefs
      status: "True"
      type: ResolvedRefs
    - lastTransitionTime: "2023-06-19T21:04:55Z"
      message: Listener is accepted
      observedGeneration: 1
      reason: Accepted
      status: "True"
      type: Accepted
    - lastTransitionTime: "2023-06-19T21:04:55Z"
      message: Application Gateway For Containers resource has been successfully updated.
      observedGeneration: 1
      reason: Programmed
      status: "True"
      type: Programmed
    name: https-listener
    supportedKinds:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute

建立閘道之後,請建立 HTTPRoute 資源。

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: https-route
  namespace: test-infra
spec:
  parentRefs:
  - name: gateway-01
  rules:
  - backendRefs:
    - name: echo
      port: 80
EOF

建立 HTTPRoute 資源之後,請確定路由的狀態為「已接受」,且適用於容器的應用程式閘道資源的狀態為「已程式化」

kubectl get httproute https-route -n test-infra -o yaml

確認已成功更新適用於容器的應用程式閘道資源的狀態。

status:
  parents:
  - conditions:
    - lastTransitionTime: "2023-06-19T22:18:23Z"
      message: ""
      observedGeneration: 1
      reason: ResolvedRefs
      status: "True"
      type: ResolvedRefs
    - lastTransitionTime: "2023-06-19T22:18:23Z"
      message: Route is Accepted
      observedGeneration: 1
      reason: Accepted
      status: "True"
      type: Accepted
    - lastTransitionTime: "2023-06-19T22:18:23Z"
      message: Application Gateway For Containers resource has been successfully updated.
      observedGeneration: 1
      reason: Programmed
      status: "True"
      type: Programmed
    controllerName: alb.networking.azure.io/alb-controller
    parentRef:
      group: gateway.networking.k8s.io
      kind: Gateway
      name: gateway-01
      namespace: test-infra

使用 kubectl 建立 Kubernetes 祕密,其中包含用戶端憑證的憑證鏈結。

kubectl create secret generic ca.bundle -n test-infra --from-file=ca.crt=root.crt

建立 FrontendTLSPolicy

kubectl apply -f - <<EOF
apiVersion: alb.networking.azure.io/v1
kind: FrontendTLSPolicy
metadata:
  name: mtls-policy
  namespace: test-infra
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: Gateway
    name: gateway-01
    namespace: test-infra
    sectionNames:
    - mtls-listener
  default:
    verify:
      caCertificateRef:
        name: ca.bundle
        group: ""
        kind: Secret
        namespace: test-infra
EOF

建立 FrontendTLSPolicy 物件之後,請檢查物件上的狀態,以確保原則有效:

kubectl get frontendtlspolicy mtls-policy -n test-infra -o yaml

有效 FrontendTLSPolicy 物件建立的範例輸出:

status:
  conditions:
  - lastTransitionTime: "2023-06-29T16:54:42Z"
    message: Valid FrontendTLSPolicy
    observedGeneration: 1
    reason: Accepted
    status: "True"
    type: Accepted

測試應用程式的存取權

現在我們已準備好將一些流量透過指派給前端的 FQDN 傳送至範例應用程式。 使用下列命令來取得 FQDN:

fqdn=$(kubectl get gateway gateway-01 -n test-infra -o jsonpath='{.status.addresses[0].value}')

在沒有用戶端憑證的情況下,將前端的 FQDN 捲曲。

curl --insecure https://$fqdn/

請注意,需要憑證的回應警示。

curl: (56) OpenSSL SSL_read: OpenSSL/1.1.1k: error:1409445C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required, errno 0

對所產生呈現用戶端憑證的 FQDN 執行 Curl。

curl --cert client.crt --key client.key --insecure https://$fqdn/

請注意,回應來自適用於容器的應用程式閘道後方的後端服務。

恭喜您,您已安裝 ALB 控制器、部署後端應用程式、透過用戶端憑證進行驗證,以及透過適用於容器的應用程式閘道從後端服務傳回流量。