Todos os produtos
Search
Central de documentação

Alibaba Cloud Service Mesh:Configure mTLS on the ASM ingress gateway and restrict client access

Última atualização: Jul 04, 2026

O Mutual TLS (mTLS) no gateway de entrada do ASM exige que os clientes apresentem um certificado durante o handshake TLS para comprovar sua identidade. Após a autenticação, as políticas de autorização controlam o que cada identidade de cliente pode acessar. Essa abordagem em duas camadas separa a autenticação (o mTLS verifica quem é o cliente) da autorização (as políticas controlam o que o cliente pode fazer).

Este guia aborda três tarefas:

  1. Gerar os certificados para mTLS (CA, servidor e cliente).

  2. Configure o gateway de entrada do ASM para exigir certificados de cliente na porta 443.

  3. Crie uma política de autorização que negue a uma identidade de cliente específica o acesso a um caminho específico.

Como a identidade do cliente se mapeia para as regras de autorização

O certificado do cliente inclui uma URI SPIFFE em seu Subject Alternative Name (SAN), como spiffe://test.client. As políticas de autorização do ASM usam o campo principals para corresponder a essa identidade. A política faz a correspondência com o valor após o prefixo spiffe://. Por exemplo, um valor principals definido como test.client corresponde a um certificado com URI.1 = spiffe://test.client.

Esse mapeamento é o mecanismo central que conecta a autenticação mTLS ao controle de acesso baseado em caminho.

Pré-requisitos

Antes de começar, verifique se você tem:

Etapa 1: Gerar certificados mTLS

O mTLS requer três conjuntos de certificados: uma CA raiz, um certificado de servidor e um certificado de cliente. A CA raiz assina tanto o certificado do servidor quanto o do cliente. O gateway apresenta o certificado do servidor para se identificar, e os clientes apresentam o certificado de cliente para provar sua identidade.

Nota

Ao ser solicitado a preencher campos de certificado durante a geração, aceite os valores padrão. Os arquivos de configuração abaixo já definem todos os campos obrigatórios.

  1. Crie um arquivo chamado ca.cnf com o seguinte conteúdo.

    ca.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 certificates, not for making the CA certificate.====
    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. Gere o certificado da CA raiz e a chave privada.

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

    Esse comando gera dois arquivos: cacert.pem (o certificado da CA) e cakey.pem (a chave privada da CA).

  3. Crie um arquivo chamado server.cnf com o seguinte conteúdo.

    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. Gere o certificado do servidor, inicialize o banco de dados de assinatura da CA e assine o certificado.

    # Generate the CSR and private key
    openssl req -config server.cnf -newkey rsa:2048 -sha256 -nodes -out server.csr -outform PEM
    
    # Initialize the CA signing database
    touch index.txt
    echo '01' > serial.txt
    
    # Sign the server certificate with the root CA
    openssl ca -config ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles server.csr

    Esse processo gera dois arquivos: servercert.pem (o certificado do servidor) e serverkey.pem (a chave privada do servidor).

  5. Crie um arquivo chamado client.cnf com o seguinte conteúdo.

    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

    Dois campos nesta configuração determinam a identidade do cliente para autorização:

    Campo

    Valor

    Função

    commonName_default

    test.client

    Identifica o cliente

    URI.1 (SAN)

    spiffe://test.client

    Correspondido pelo campo principals nas políticas de autorização (após o prefixo spiffe://)

  6. Gere o certificado do cliente e assine-o com a CA raiz.

    # Generate the CSR and private key
    openssl req -config client.cnf -newkey rsa:2048 -sha256 -nodes -out clientcert.csr -outform PEM
    
    # Sign the client certificate with the root CA
    openssl ca -config ca.cnf -policy signing_policy -extensions signing_req -out clientcert.pem -infiles clientcert.csr

    Como resultado, são gerados dois arquivos: clientcert.pem (o certificado do cliente) e client.key.pem (a chave privada do cliente).

  7. Importe o certificado mTLS usando o recurso de gerenciamento de certificados do ASM. Defina o nome do certificado como test.com. Para mais informações, consulte Usar o recurso de gerenciamento de certificados do ASM.

    Como alternativa, crie um Secret do Kubernetes diretamente. Execute o comando a seguir usando o kubeconfig do seu cluster de plano de dados:

    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

    Este Secret agrupa três arquivos:

    Chave

    Arquivo

    Finalidade

    tls.key

    serverkey.pem

    Chave privada do servidor para terminação TLS

    tls.crt

    servercert.pem

    Certificado do servidor apresentado aos clientes

    ca.crt

    cacert.pem

    Certificado da CA raiz usado para verificar certificados de cliente

Etapa 2: Configure o listener mTLS no gateway

Adicione um listener mTLS na porta 443 do gateway de entrada do ASM. Após essa configuração, os clientes externos devem apresentar um certificado de cliente válido para acessar o serviço httpbin.

  1. Atualize o resource Gateway com o seguinte conteúdo.

    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

    A configuração tls.mode: MUTUAL exige que os clientes apresentem um certificado assinado pela CA no Secret test.com. Sem um certificado de cliente válido, o handshake TLS falha e o gateway rejeita a conexão.

    Nota

    Outros modos TLS incluem SIMPLE (apenas TLS no lado do servidor, sem necessidade de certificado de cliente) e PASSTHROUGH (o TLS não é terminado no gateway). Use MUTUAL quando precisar autenticar a identidade do cliente no nível do gateway.

  2. Verifique se o mTLS rejeita requisições sem um certificado de cliente.

    curl -v --resolve "test.com:443:<ASM-gateway-IP>" \
      --cacert cacert.pem \
      https://test.com/status/200

    Substitua <ASM-gateway-IP> pelo endereço IP do seu gateway de entrada do ASM.

    A requisição falha com um erro de handshake TLS porque nenhum certificado de cliente foi fornecido. Isso confirma que o gateway impõe o mTLS.

  3. Verifique se o mTLS aceita requisições com um certificado de cliente válido.

    curl --header "host:test.com" \
         --resolve "test.com:443:<ASM-gateway-IP>" \
         --cacert cacert.pem \
         --cert clientcert.pem \
         --key client.key.pem \
         https://test.com/status/200 -I

    Saída esperada:

    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

    Uma resposta HTTP/2 200 confirma que o gateway aceitou o certificado do cliente e encaminhou a requisição para o httpbin.

Etapa 3: Restringir o acesso do cliente com uma política de autorização

Depois que o mTLS autentica cada cliente, as políticas de autorização controlam o que cada cliente pode acessar. Nesta etapa, crie uma política DENY que bloqueie a identidade test.client de acessar um caminho específico. Outros clientes permanecem inalterados.

Nota

Quando existem várias políticas de autorização na mesma carga de trabalho, as políticas DENY são avaliadas antes das políticas ALLOW. Uma requisição que corresponda a qualquer regra DENY será rejeitada, independentemente das regras ALLOW.

  1. Implante o seguinte AuthorizationPolicy para negar ao test.client o acesso ao caminho /status/418 na aplicação httpbin. Para mais informações, consulte Configurar políticas de autorização para requisições 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

    Esta política tem como alvo o gateway de entrada (istio: ingressgateway) e nega qualquer requisição do principal test.client para o caminho /status/418. O valor principals definido como test.client corresponde à URI SPIFFE spiffe://test.client no SAN do certificado do cliente.

Verifique a política de autorização

  1. Confirme se o test.client ainda consegue acessar outros caminhos. Envie uma requisição para /status/200:

    curl --header "host:test.com" \
         --resolve "test.com:443:<ASM-gateway-IP>" \
         --cacert cacert.pem \
         --cert clientcert.pem \
         --key client.key.pem \
         https://test.com/status/200 -I

    Saída esperada:

    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

    Uma resposta 200 significa que a política DENY se aplica apenas a /status/418, e não a outros caminhos.

  2. Confirme se o acesso do test.client a /status/418 foi negado:

    curl --header "host:test.com" \
         --resolve "test.com:443:<ASM-gateway-IP>" \
         --cacert cacert.pem \
         --cert clientcert.pem \
         --key client.key.pem \
         https://test.com/status/418

    Saída esperada:

    RBAC: access denied

    A mensagem RBAC: access denied confirma que a política de autorização bloqueou o test.client neste caminho.

  3. Confirme se uma identidade de cliente diferente ainda consegue acessar /status/418. Envie uma requisição usando o certificado do servidor:

    curl --header "host:test.com" \
         --resolve "test.com:443:<ASM-gateway-IP>" \
         --cacert cacert.pem \
         --cert servercert.pem \
         --key serverkey.pem \
         https://test.com/status/418

    Saída esperada:

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

    A resposta "teapot" confirma que a regra DENY tem como alvo apenas a identidade test.client. Outras identidades com certificados válidos ainda podem acessar /status/418.