全部產品
Search
文件中心

Alibaba Cloud Service Mesh:在ASM入口網關上配置mTLS服務並限制特定用戶端訪問

更新時間:Oct 11, 2024

ASM網關支援對外提供mTLS服務。mTLS協議要求用戶端提供自身認證,認證中包含了使用者的身份資訊。您可以在授權策略中配置只有特定的使用者才可以成功訪問該服務,進而為服務提供更加進階別的保護。本文將介紹如何在ASM入口網關上配置mTLS服務,並且通過授權策略實現對特定使用者的訪問限制。

前提條件

步驟一:產生mTLS通訊認證

說明

在建立認證時,如果需要填寫認證資訊,請使用預設值。這些預設值已在設定檔中預先設定。

  1. 使用以下內容建立ca.cnf檔案,產生根憑證。

    展開查看CNF檔案內容

    HOME = .`
    RANDFILE = $ENV::HOME/.rnd
    ####################################################################
    [ ca ]
    default_ca = CA_default # The default ca section
    [ CA_default ]
    default_days = 1000 # how long to certify for
    default_crl_days = 30 # how long before next CRL
    default_md = sha256 # use public key default MD
    preserve = no # keep passed DN ordering
    x509_extensions = ca_extensions # The extensions to add to the cert
    email_in_dn = no # Don't concat the email in the DN
    copy_extensions = copy # Required to copy SANs from CSR to cert
    
    #====Following 7 lines are for signing other certs, not for making the CA cert.====
    base_dir = .
    certificate = $base_dir/cacert.pem # The CA certifcate
    private_key = $base_dir/cakey.pem # The CA private key
    new_certs_dir = $base_dir # Location for new certs after signing
    database = $base_dir/index.txt # Database index file
    serial = $base_dir/serial.txt # The current serial number
    unique_subject = no # Set to 'no' to allow creation of several certificates with same subject.
    
    ####################################################################
    [ req ]
    default_bits = 4096
    default_keyfile = cakey.pem
    distinguished_name = ca_distinguished_name
    x509_extensions = ca_extensions
    string_mask = utf8only
    ####################################################################
    [ ca_distinguished_name ]
    countryName = Country Name (2 letter code)
    countryName_default = CN
    stateOrProvinceName = State or Province Name (full name)
    stateOrProvinceName_default = bj
    localityName = Locality Name (eg, city)
    localityName_default = bj
    organizationName = Organization Name (eg, company)
    organizationName_default = test-asm
    organizationalUnitName = Organizational Unit (eg, division)
    organizationalUnitName_default = R&D
    commonName = Common Name (e.g. server FQDN or YOUR name)
    commonName_default = Test CA
    emailAddress = Email Address
    emailAddress_default = test@example.com
    ####################################################################
    [ ca_extensions ]
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always, issuer
    basicConstraints = critical, CA:true
    keyUsage = keyCertSign, cRLSign
    
    
    #====All lines below are for signing other certs, not for making the CA cert.======
    
    ####################################################################
    [ signing_policy ]
    countryName = optional
    stateOrProvinceName = optional
    localityName = optional
    organizationName = optional
    organizationalUnitName = optional
    commonName = supplied
    emailAddress = optional
    ####################################################################
    [ signing_req ]
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid,issuer
    basicConstraints = CA:FALSE
    keyUsage = digitalSignature, keyEncipherment
  2. 執行以下命令,產生根憑證。

    openssl req -x509 -config ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM

    此命令會輸出cacert.pemcakey.pem檔案。

  3. 使用以下內容建立server.cnf檔案,用於產生伺服器憑證。

    HOME = .
    RANDFILE = $ENV::HOME/.rnd
    ####################################################################
    [ req ]
    default_bits = 2048
    default_keyfile = serverkey.pem
    distinguished_name = server_distinguished_name
    req_extensions = server_req_extensions
    string_mask = utf8only
    ####################################################################
    [ server_distinguished_name ]
    countryName = Country Name (2 letter code)
    countryName_default = CN
    stateOrProvinceName = State or Province Name (full name)
    stateOrProvinceName_default = bj
    localityName = Locality Name (eg, city)
    localityName_default = bj
    organizationName = Organization Name (eg, company)
    organizationName_default = test
    commonName = Common Name (e.g. server FQDN or YOUR name)
    commonName_default = test.com
    emailAddress = Email Address
    emailAddress_default = test@example.com
    ####################################################################
    [ server_req_extensions ]
    subjectKeyIdentifier = hash
    basicConstraints = CA:FALSE
    keyUsage = digitalSignature, keyEncipherment
    subjectAltName = @alternate_names
    nsComment = "OpenSSL Generated Certificate"
    ####################################################################
    [ alternate_names ]
    DNS.1 = test.com
  4. 依次執行以下命令,產生伺服器憑證。

    openssl req -config server.cnf -newkey rsa:2048 -sha256 -nodes -out server.csr -outform PEM
    touch index.txt
    echo '01' > serial.txt
    openssl ca -config ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles server.csr

    此命令會輸出servercert.pemserverkey.pem

  5. 使用以下內容建立client.cnf檔案,用於建立用戶端認證。

    HOME = .
    RANDFILE = $ENV::HOME/.rnd
    ####################################################################
    [ req ]
    default_bits = 2048
    default_keyfile = client.key.pem
    distinguished_name = server_distinguished_name
    req_extensions = server_req_extensions
    string_mask = utf8only
    ####################################################################
    [ server_distinguished_name ]
    countryName = Country Name (2 letter code)
    countryName_default = CN
    stateOrProvinceName = State or Province Name (full name)
    stateOrProvinceName_default = bj
    localityName = Locality Name (eg, city)
    localityName_default = bj
    organizationName = Organization Name (eg, company)
    organizationName_default = test.client
    commonName = Common Name (e.g. server FQDN or YOUR name)
    commonName_default = test.client
    emailAddress = Email Address
    emailAddress_default = test.client@example.com
    ####################################################################
    [ server_req_extensions ]
    subjectKeyIdentifier = hash
    basicConstraints = CA:FALSE
    keyUsage = digitalSignature, keyEncipherment
    subjectAltName = @alternate_names
    nsComment = "OpenSSL Generated Certificate"
    ####################################################################
    [ alternate_names ]
    URI.1 = spiffe://test.client

    用戶端認證的CommonNametest.client,SAN資訊中需要新增欄位URI.1 = spiffe://test.client,這裡需要額外加上spiffe://首碼,因為ASM的授權策略中principals欄位會匹配spiffe://之後的部分。

  6. 依次執行以下命令,產生用戶端認證。

    openssl req -config client.cnf -newkey rsa:2048 -sha256 -nodes -out clientcert.csr -outform PEM
    openssl ca -config ca.cnf -policy signing_policy -extensions signing_req -out clientcert.pem -infiles clientcert.csr

    此命令會輸出clientcert.pem以及client.key.pem

  7. 使用ASM認證管理匯入mTLS認證,請確保此處匯入的認證名稱為test.com。具體操作,請參見使用ASM認證管理

    您也可以使用kubectl直接建立secret來完成認證匯入。使用資料面叢集的kubeconfig,執行如下命令。

    kubectl create -n istio-system secret generic test.com \
      --from-file=tls.key=serverkey.pem \
      --from-file=tls.crt=servercert.pem \
      --from-file=ca.crt=cacert.pem

步驟二:在網關443連接埠上配置mTLS監聽

本節將為ASM網關的443連接埠配置mTLS監聽,讓外部客戶端可以通過mTLS訪問httpbin服務。

  1. 使用以下內容,更新網關規則。

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: httpbin
      namespace: default
    spec:
      selector:
        istio: ingressgateway
      servers:
        - hosts:
            - '*'
          port:
            name: test
            number: 80
            protocol: HTTP
        - hosts:
          - test.com
          port:
            number: 443
            name: https
            protocol: HTTPS
          tls:
            mode: MUTUAL
            credentialName: test.com
  2. 執行以下命令,使用client認證訪問httpbin服務。

    curl --header "host:test.com" --resolve "test.com:443:${ASM網關IP}" --cacert cacert.pem --cert clientcert.pem --key client.key.pem  https://test.com/status/200 -I

    預期輸出:

    HTTP/2 200
    server: istio-envoy
    date: Sun, 28 Jul 2024 7:30:30 GMT
    content-type: text/html; charset=utf-8
    access-control-allow-origin: *
    access-control-allow-credentials: true
    content-length: 0
    x-envoy-upstream-service-time: 6

步驟三:配置授權策略,限制test.client訪問

  1. 使用以下內容,部署授權策略。限制test.client不能訪問httpbin應用的/status/418路徑。具體操作,請參見為HTTP流量設定授權策略

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: test
      namespace: istio-system
    spec:
      action: DENY
      rules:
        - from:
            - source:
                principals:
                  - test.client
          to:
            - operation:
                paths:
                  - /status/418
      selector:
        matchLabels:
          istio: ingressgateway
  2. 執行以下命令,使用client認證訪問/status/200路徑。

    curl --header "host:test.com" --resolve "test.com:443:${ASM網關IP}" --cacert cacert.pem --cert clientcert.pem --key client.key.pem  https://test.com/status/200 -I

    預期輸出:

    HTTP/2 200
    server: istio-envoy
    date: Sun, 28 Jul 2024 7:33:30 GMT
    content-type: text/html; charset=utf-8
    access-control-allow-origin: *
    access-control-allow-credentials: true
    content-length: 0
    x-envoy-upstream-service-time: 6
  3. 執行以下命令,使用client認證訪問/status/418路徑。

    curl --header "host:test.com" --resolve "test.com:443:${ASM網關IP}" --cacert cacert.pem --cert clientcert.pem --key client.key.pem  https://test.com/status/418

    預期輸出:

    RBAC: access denied%
  4. 執行以下命令,使用server認證訪問/status/418路徑。

    curl --header "host:test.com" --resolve "test.com:443:${ASM網關IP}" --cacert cacert.pem --cert servercert.pem --key serverkey.pem  https://test.com/status/418

    預期輸出:

        -=[ teapot ]=-
    
           _...._
         .'  _ _ `.
        | ."` ^ `". _,
        \_;`"---"`|//
          |       ;/
          \_     _/
            `"""`