Search code examples
rustmtlsrust-tonic

Unexpected NotValidForName with Rust's tonic with TLS


I am using the Rust's tonic library for GRPC with TLS.

I get the following error

thread 'main' panicked at 'Failed to create request insight client: tonic::transport::Error(Transport,
   hyper::Error(Connect, Custom { kind: InvalidData, error: InvalidCertificate(NotValidForName) }))'

The same certificate works for other languages.

curl --cacert <path to cert> -vv <server>

shows the expected certificate subject name.

This is how the ClientTlsConfig and Channel is created:

    let tls = ClientTlsConfig::new()
        .domain_name("server") // <server> matches the certificate subject name
        .ca_certificate(Certificate::from_pem(client_ca_data));
    let channel = Channel::from_shared(endpoint.to_string()) // endpoint is http://server:50051
                    .unwrap()
                    .tls_config(tls_config)?
                    .connect()
                    .await?;

It is not clear what the next steps are.


Solution

  • I had the same issue when using the rustls to establish connection between server and the client. Apparently, the rust is strict in handling such errors according to RFC regulations. Please use the following bash script to regenerate the key and self-signed certificates for your case. The generated files will exist under keys directory. Remember to change the [alt_names] based on your settings.

    #!/bin/sh
    mkdir -p keys
    cd keys/
    
    # source: https://users.rust-lang.org/t/use-tokio-tungstenite-with-rustls-instead-of-native-tls-for-secure-websockets/90130
    
    # Create unencrypted private key and a CSR (certificate signing request)
    openssl req -newkey rsa:2048 -nodes -subj "/C=FI/CN=vahid" -keyout key.pem -out key.csr
    
    # Create self-signed certificate (`cert.pem`) with the private key and CSR
    openssl x509 -signkey key.pem -in key.csr -req -days 365 -out cert.pem
    
    # Create a self-signed root CA
    openssl req -x509 -sha256 -nodes -subj "/C=FI/CN=vahid" -days 1825 -newkey rsa:2048 -keyout rootCA.key -out rootCA.crt
    
    
    # Create file localhost.ext with the following content:
    cat <<'EOF' >> localhost.ext
    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = server
    IP.1 = <The Ip of the server!>
    EOF
    
    # Sign the CSR (`cert.pem`) with the root CA certificate and private key
    # => this overwrites `cert.pem` because it gets signed
    openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in key.csr -out cert.pem -days 365 -CAcreateserial -extfile localhost.ext
    

    Please make sure that the client has the rootCA.crt in your code. Something like this:

        let tls = ClientTlsConfig::new()
            .domain_name("server") // <server> matches the certificate subject name
            .ca_certificate(Certificate::from_pem("keys/rootCA.crt"));