From 817a7b942c462fa9d9938dcb62124173634132fb Mon Sep 17 00:00:00 2001 From: Tomasz Pietrek Date: Thu, 16 Mar 2023 12:53:13 +0100 Subject: [PATCH] Improve TLS connection resilience Until now, it was possible to procure MitM attack by acting as malicious fake server. This commit removes that possibility by never trusting pre-tls addresses provided by the NATS server. For now it has to be based of tokio-rustls fork, as ruslts support for IP addresses is not yet released. This points tokio-rustls to rustls main branch. No custom code added. Signed-off-by: Tomasz Pietrek --- async-nats/Cargo.toml | 4 +- async-nats/src/connector.rs | 18 +--- async-nats/src/tls.rs | 22 +++-- async-nats/tests/configs/certs/ip-ca.pem | 27 ++++++ async-nats/tests/configs/certs/ip-cert.pem | 99 ++++++++++++++++++++++ async-nats/tests/configs/certs/ip-key.pem | 28 ++++++ async-nats/tests/configs/ip-tls.conf | 17 ++++ async-nats/tests/tls_tests.rs | 28 ++++++ 8 files changed, 213 insertions(+), 30 deletions(-) create mode 100644 async-nats/tests/configs/certs/ip-ca.pem create mode 100644 async-nats/tests/configs/certs/ip-cert.pem create mode 100644 async-nats/tests/configs/certs/ip-key.pem create mode 100644 async-nats/tests/configs/ip-tls.conf diff --git a/async-nats/Cargo.toml b/async-nats/Cargo.toml index 9771a61f8..909a4f01f 100644 --- a/async-nats/Cargo.toml +++ b/async-nats/Cargo.toml @@ -28,12 +28,12 @@ http = "0.2.9" tokio = { version = "1.25.0", features = ["macros", "rt", "fs", "net", "sync", "time", "io-util"] } itoa = "1" url = "2" -tokio-rustls = "0.23" +tokio-rustls = { git = "https://github.com/Jarema/tls", rev = "935b459"} rustls-pemfile = "1.0.2" nuid = "0.3.2" serde_nanos = "0.1.3" time = { version = "0.3.20", features = ["parsing", "formatting", "serde", "serde-well-known"] } -rustls-native-certs = "0.6.2" +rustls-native-certs = "0.6" tracing = "0.1" thiserror = "1.0" base64 = "0.13" diff --git a/async-nats/src/connector.rs b/async-nats/src/connector.rs index 2af84be4a..716032b0e 100644 --- a/async-nats/src/connector.rs +++ b/async-nats/src/connector.rs @@ -300,22 +300,8 @@ impl Connector { }) .map_err(|err| ConnectError::with_source(crate::ConnectErrorKind::Tls, err))?; - // Use the server-advertised hostname to validate if given as a hostname, not an IP address - let domain = if let Ok(server_hostname @ rustls::ServerName::DnsName(_)) = - rustls::ServerName::try_from(info.host.as_str()) - { - server_hostname - } else if let Ok(tls_hostname @ rustls::ServerName::DnsName(_)) = - rustls::ServerName::try_from(tls_host) - { - tls_hostname - } else { - return Err(io::Error::new( - ErrorKind::InvalidInput, - "cannot determine hostname for TLS connection", - )) - .map_err(|err| ConnectError::with_source(crate::ConnectErrorKind::Tls, err)); - }; + let domain = rustls::ServerName::try_from(tls_host) + .map_err(|err| ConnectError::with_source(crate::ConnectErrorKind::Tls, err))?; connection = Connection { stream: Box::new(tls_connector.connect(domain, connection.stream).await?), diff --git a/async-nats/src/tls.rs b/async-nats/src/tls.rs index 3a94c360d..5a3a2caa3 100644 --- a/async-nats/src/tls.rs +++ b/async-nats/src/tls.rs @@ -63,24 +63,22 @@ pub(crate) async fn load_key(path: PathBuf) -> io::Result { } pub(crate) async fn config_tls(options: &ConnectorOptions) -> io::Result { - let mut root_store = rustls::RootCertStore::empty(); + let mut root_store = tokio_rustls::rustls::RootCertStore::empty(); // load native system certs only if user did not specify them. if options.tls_client_config.is_some() || options.certificates.is_empty() { - for cert in rustls_native_certs::load_native_certs().map_err(|err| { - io::Error::new( - ErrorKind::Other, - format!("could not load platform certs: {err}"), - ) - })? { - root_store - .add(&rustls::Certificate(cert.0)) + root_store.add_parsable_certificates( + rustls_native_certs::load_native_certs() .map_err(|err| { io::Error::new( ErrorKind::Other, - format!("failed to read root certificates: {err}"), + format!("could not load platform certs: {err}"), ) - })?; - } + })? + .into_iter() + .map(|cert| cert.0) + .collect::>>() + .as_ref(), + ); } // use provided ClientConfig or built it from options. diff --git a/async-nats/tests/configs/certs/ip-ca.pem b/async-nats/tests/configs/certs/ip-ca.pem new file mode 100644 index 000000000..911c486c1 --- /dev/null +++ b/async-nats/tests/configs/certs/ip-ca.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEkDCCA3igAwIBAgIUSZwW7btc9EUbrMWtjHpbM0C2bSEwDQYJKoZIhvcNAQEL +BQAwcTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNVBAoM +B1N5bmFkaWExEDAOBgNVBAsMB25hdHMuaW8xKTAnBgNVBAMMIENlcnRpZmljYXRl +IEF1dGhvcml0eSAyMDIyLTA4LTI3MB4XDTIyMDgyNzIwMjMwMloXDTMyMDgyNDIw +MjMwMlowcTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNV +BAoMB1N5bmFkaWExEDAOBgNVBAsMB25hdHMuaW8xKTAnBgNVBAMMIENlcnRpZmlj +YXRlIEF1dGhvcml0eSAyMDIyLTA4LTI3MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAqilVqyY8rmCpTwAsLF7DEtWEq37KbljBWVjmlp2Wo6TgMd3b537t +6iO8+SbI8KH75i63RcxV3Uzt1/L9Yb6enDXF52A/U5ugmDhaa+Vsoo2HBTbCczmp +qndp7znllQqn7wNLv6aGSvaeIUeYS5Dmlh3kt7Vqbn4YRANkOUTDYGSpMv7jYKSu +1ee05Rco3H674zdwToYto8L8V7nVMrky42qZnGrJTaze+Cm9tmaIyHCwUq362CxS +dkmaEuWx11MOIFZvL80n7ci6pveDxe5MIfwMC3/oGn7mbsSqidPMcTtjw6ey5NEu +Z0UrC/2lL1FtF4gnVMKUSaEhU2oKjj0ZAQIDAQABo4IBHjCCARowHQYDVR0OBBYE +FP7Pfz4u7sSt6ltviEVsx4hIFIs6MIGuBgNVHSMEgaYwgaOAFP7Pfz4u7sSt6ltv +iEVsx4hIFIs6oXWkczBxMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5p +YTEQMA4GA1UECgwHU3luYWRpYTEQMA4GA1UECwwHbmF0cy5pbzEpMCcGA1UEAwwg +Q2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMjItMDgtMjeCFEmcFu27XPRFG6zFrYx6 +WzNAtm0hMAwGA1UdEwQFMAMBAf8wOgYJYIZIAYb4QgENBC0WK25hdHMuaW8gbmF0 +cy1zZXJ2ZXIgdGVzdC1zdWl0ZSB0cmFuc2llbnQgQ0EwDQYJKoZIhvcNAQELBQAD +ggEBAHDCHLQklYZlnzHDaSwxgGSiPUrCf2zhk2DNIYSDyBgdzrIapmaVYQRrCBtA +j/4jVFesgw5WDoe4TKsyha0QeVwJDIN8qg2pvpbmD8nOtLApfl0P966vcucxDwqO +dQWrIgNsaUdHdwdo0OfvAlTfG0v/y2X0kbL7h/el5W9kWpxM/rfbX4IHseZL2sLq +FH69SN3FhMbdIm1ldrcLBQVz8vJAGI+6B9hSSFQWljssE0JfAX+8VW/foJgMSx7A +vBTq58rLkAko56Jlzqh/4QT+ckayg9I73v1Q5/44jP1mHw35s5ZrzpDQt2sVv4l5 +lwRPJFXMwe64flUs9sM+/vqJaIY= +-----END CERTIFICATE----- diff --git a/async-nats/tests/configs/certs/ip-cert.pem b/async-nats/tests/configs/certs/ip-cert.pem new file mode 100644 index 000000000..80a9d8fe0 --- /dev/null +++ b/async-nats/tests/configs/certs/ip-cert.pem @@ -0,0 +1,99 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 1d:d9:1f:06:dd:fd:90:26:4e:27:ea:2e:01:4b:31:e6:d2:49:31:1f + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=California, O=Synadia, OU=nats.io, CN=Certificate Authority 2022-08-27 + Validity + Not Before: Aug 27 20:23:02 2022 GMT + Not After : Aug 24 20:23:02 2032 GMT + Subject: C=US, ST=California, O=Synadia, OU=nats.io, CN=localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:e6:fb:47:65:cd:c9:a2:2d:af:8b:cd:d5:6a:79: + 54:3c:07:5f:eb:5a:71:2b:2b:e5:6f:be:31:fb:16: + 65:68:76:0e:59:e7:e4:57:ca:88:e9:77:d6:41:ad: + 57:7a:42:b2:d2:54:c4:0f:7c:5b:c1:bc:61:97:e3: + 22:3a:3e:1e:4a:5d:47:9f:6b:7d:6f:34:e3:8c:86: + 9d:85:19:29:9a:11:58:44:4c:a1:90:d3:14:61:e1: + 57:da:01:ea:ce:3f:90:ae:9e:5d:13:6d:2c:89:ca: + 39:15:6b:b6:9e:32:d7:2a:4c:48:85:2f:b0:1e:d8: + 4b:62:32:14:eb:32:b6:29:04:34:3c:af:39:b6:8b: + 52:32:4d:bf:43:5f:9b:fb:0d:43:a6:ad:2c:a7:41: + 29:55:c9:70:b3:b5:15:46:34:bf:e4:1e:52:2d:a4: + 49:2e:d5:21:ed:fc:00:f7:a2:0b:bc:12:0a:90:64: + 50:7c:c5:14:70:f5:fb:9b:62:08:78:43:49:31:f3: + 47:b8:93:d4:2d:4c:a9:dc:17:70:76:34:66:ff:65: + c1:39:67:e9:a6:1c:80:6a:f0:9d:b3:28:c8:a3:3a: + b7:5d:de:6e:53:6d:09:b3:0d:b1:13:10:e8:ec:e0: + bd:5e:a1:94:4b:70:bf:dc:bd:8b:b9:82:65:dd:af: + 81:7b + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + Netscape Comment: + nats.io nats-server test-suite certificate + X509v3 Subject Key Identifier: + 2B:8C:A3:8B:DB:DB:5C:CE:18:DB:F6:A8:31:4E:C2:3E:EE:D3:40:7E + X509v3 Authority Key Identifier: + keyid:FE:CF:7F:3E:2E:EE:C4:AD:EA:5B:6F:88:45:6C:C7:88:48:14:8B:3A + DirName:/C=US/ST=California/O=Synadia/OU=nats.io/CN=Certificate Authority 2022-08-27 + serial:49:9C:16:ED:BB:5C:F4:45:1B:AC:C5:AD:8C:7A:5B:33:40:B6:6D:21 + + X509v3 Subject Alternative Name: + DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1 + Netscape Cert Type: + SSL Client, SSL Server + X509v3 Key Usage: + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Server Authentication, Netscape Server Gated Crypto, Microsoft Server Gated Crypto, TLS Web Client Authentication + Signature Algorithm: sha256WithRSAEncryption + 54:49:34:2b:38:d1:aa:3b:43:60:4c:3f:6a:f8:74:ca:49:53: + a1:af:12:d3:a8:17:90:7b:9d:a3:69:13:6e:da:2c:b7:61:31: + ac:eb:00:93:92:fc:0c:10:d4:18:a0:16:61:94:4b:42:cb:eb: + 7a:f6:80:c6:45:c0:9c:09:aa:a9:48:e8:36:e3:c5:be:36:e0: + e9:78:2a:bb:ab:64:9b:20:eb:e6:0f:63:2b:59:c3:58:0b:3a: + 84:15:04:c1:7e:12:03:1b:09:25:8d:4c:03:e8:18:26:c0:6c: + b7:90:b1:fd:bc:f1:cf:d0:d5:4a:03:15:71:0c:7d:c1:76:87: + 92:f1:3e:bc:75:51:5a:c4:36:a4:ff:91:98:df:33:5d:a7:38: + de:50:29:fd:0f:c8:55:e6:8f:24:c2:2e:98:ab:d9:5d:65:2f: + 50:cc:25:f6:84:f2:21:2e:5e:76:d0:86:1e:69:8b:cb:8a:3a: + 2d:79:21:5e:e7:f7:2d:06:18:a1:13:cb:01:c3:46:91:2a:de: + b4:82:d7:c3:62:6f:08:a1:d5:90:19:30:9d:64:8e:e4:f8:ba: + 4f:2f:ba:13:b4:a3:9f:d1:d5:77:64:8a:3e:eb:53:c5:47:ac: + ab:3e:0e:7a:9b:a6:f4:48:25:66:eb:c7:4c:f9:50:24:eb:71: + e0:75:ae:e6 +-----BEGIN CERTIFICATE----- +MIIE+TCCA+GgAwIBAgIUHdkfBt39kCZOJ+ouAUsx5tJJMR8wDQYJKoZIhvcNAQEL +BQAwcTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNVBAoM +B1N5bmFkaWExEDAOBgNVBAsMB25hdHMuaW8xKTAnBgNVBAMMIENlcnRpZmljYXRl +IEF1dGhvcml0eSAyMDIyLTA4LTI3MB4XDTIyMDgyNzIwMjMwMloXDTMyMDgyNDIw +MjMwMlowWjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEDAOBgNV +BAoMB1N5bmFkaWExEDAOBgNVBAsMB25hdHMuaW8xEjAQBgNVBAMMCWxvY2FsaG9z +dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOb7R2XNyaItr4vN1Wp5 +VDwHX+tacSsr5W++MfsWZWh2Dlnn5FfKiOl31kGtV3pCstJUxA98W8G8YZfjIjo+ +HkpdR59rfW8044yGnYUZKZoRWERMoZDTFGHhV9oB6s4/kK6eXRNtLInKORVrtp4y +1ypMSIUvsB7YS2IyFOsytikENDyvObaLUjJNv0Nfm/sNQ6atLKdBKVXJcLO1FUY0 +v+QeUi2kSS7VIe38APeiC7wSCpBkUHzFFHD1+5tiCHhDSTHzR7iT1C1MqdwXcHY0 +Zv9lwTln6aYcgGrwnbMoyKM6t13eblNtCbMNsRMQ6OzgvV6hlEtwv9y9i7mCZd2v +gXsCAwEAAaOCAZ4wggGaMAkGA1UdEwQCMAAwOQYJYIZIAYb4QgENBCwWKm5hdHMu +aW8gbmF0cy1zZXJ2ZXIgdGVzdC1zdWl0ZSBjZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU +K4yji9vbXM4Y2/aoMU7CPu7TQH4wga4GA1UdIwSBpjCBo4AU/s9/Pi7uxK3qW2+I +RWzHiEgUizqhdaRzMHExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh +MRAwDgYDVQQKDAdTeW5hZGlhMRAwDgYDVQQLDAduYXRzLmlvMSkwJwYDVQQDDCBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAyMi0wOC0yN4IUSZwW7btc9EUbrMWtjHpb +M0C2bSEwLAYDVR0RBCUwI4IJbG9jYWxob3N0hwR/AAABhxAAAAAAAAAAAAAAAAAA +AAABMBEGCWCGSAGG+EIBAQQEAwIGwDALBgNVHQ8EBAMCBaAwNAYDVR0lBC0wKwYI +KwYBBQUHAwEGCWCGSAGG+EIEAQYKKwYBBAGCNwoDAwYIKwYBBQUHAwIwDQYJKoZI +hvcNAQELBQADggEBAFRJNCs40ao7Q2BMP2r4dMpJU6GvEtOoF5B7naNpE27aLLdh +MazrAJOS/AwQ1BigFmGUS0LL63r2gMZFwJwJqqlI6Dbjxb424Ol4KrurZJsg6+YP +YytZw1gLOoQVBMF+EgMbCSWNTAPoGCbAbLeQsf288c/Q1UoDFXEMfcF2h5LxPrx1 +UVrENqT/kZjfM12nON5QKf0PyFXmjyTCLpir2V1lL1DMJfaE8iEuXnbQhh5pi8uK +Oi15IV7n9y0GGKETywHDRpEq3rSC18Nibwih1ZAZMJ1kjuT4uk8vuhO0o5/R1Xdk +ij7rU8VHrKs+DnqbpvRIJWbrx0z5UCTrceB1ruY= +-----END CERTIFICATE----- diff --git a/async-nats/tests/configs/certs/ip-key.pem b/async-nats/tests/configs/certs/ip-key.pem new file mode 100644 index 000000000..f2c2c6c2f --- /dev/null +++ b/async-nats/tests/configs/certs/ip-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQDm+0dlzcmiLa+L +zdVqeVQ8B1/rWnErK+VvvjH7FmVodg5Z5+RXyojpd9ZBrVd6QrLSVMQPfFvBvGGX +4yI6Ph5KXUefa31vNOOMhp2FGSmaEVhETKGQ0xRh4VfaAerOP5Cunl0TbSyJyjkV +a7aeMtcqTEiFL7Ae2EtiMhTrMrYpBDQ8rzm2i1IyTb9DX5v7DUOmrSynQSlVyXCz +tRVGNL/kHlItpEku1SHt/AD3ogu8EgqQZFB8xRRw9fubYgh4Q0kx80e4k9QtTKnc +F3B2NGb/ZcE5Z+mmHIBq8J2zKMijOrdd3m5TbQmzDbETEOjs4L1eoZRLcL/cvYu5 +gmXdr4F7AgMBAAECggEBAK4sr3MiEbjcsHJAvXyzjwRRH1Bu+8VtLW7swe2vvrpd +w4aiKXrV/BXpSsRtvPgxkXyvdMSkpuBZeFI7cVTwAJFc86RQPt77x9bwr5ltFwTZ +rXCbRH3b3ZPNhByds3zhS+2Q92itu5cPyanQdn2mor9/lHPyOOGZgobCcynELL6R +wRElkeDyf5ODuWEd7ADC5IFyZuwb3azNVexIK+0yqnMmv+QzEW3hsycFmFGAeB7v +MIMjb2BhLrRr6Y5Nh+k58yM5DCf9h/OJhDpeXwLkxyK4BFg+aZffEbUX0wHDMR7f +/nMv1g6cKvDWiLU8xLzez4t2qNIBNdxw5ZSLyQRRolECgYEA+ySTKrBAqI0Uwn8H +sUFH95WhWUXryeRyGyQsnWAjZGF1+d67sSY2un2W6gfZrxRgiNLWEFq9AaUs0MuH +6syF4Xwx/aZgU/gvsGtkgzuKw1bgvekT9pS/+opmHRCZyQAFEHj0IEpzyB6rW1u/ +LdlR3ShEENnmXilFv/uF/uXP5tMCgYEA63LiT0w46aGPA/E+aLRWU10c1eZ7KdhR +c3En6zfgIxgFs8J38oLdkOR0CF6T53DSuvGR/OprVKdlnUhhDxBgT1oQjK2GlhPx +JV5uMvarJDJxAwsF+7T4H2QtZ00BtEfpyp790+TlypSG1jo/BnSMmX2uEbV722lY +hzINLY49obkCgYBEpN2YyG4T4+PtuXznxRkfogVk+kiVeVx68KtFJLbnw//UGT4i +EHjbBmLOevDT+vTb0QzzkWmh3nzeYRM4aUiatjCPzP79VJPsW54whIDMHZ32KpPr +TQMgPt3kSdpO5zN7KiRIAzGcXE2n/e7GYGUQ1uWr2XMu/4byD5SzdCscQwJ/Ymii +LoKtRvk/zWYHr7uwWSeR5dVvpQ3E/XtONAImrIRd3cRqXfJUqTrTRKxDJXkCmyBc +5FkWg0t0LUkTSDiQCJqcUDA3EINFR1kwthxja72pfpwc5Be/nV9BmuuUysVD8myB +qw8A/KsXsHKn5QrRuVXOa5hvLEXbuqYw29mX6QKBgDGDzIzpR9uPtBCqzWJmc+IJ +z4m/1NFlEz0N0QNwZ/TlhyT60ytJNcmW8qkgOSTHG7RDueEIzjQ8LKJYH7kXjfcF +6AJczUG5PQo9cdJKo9JP3e1037P/58JpLcLe8xxQ4ce03zZpzhsxR2G/tz8DstJs +b8jpnLyqfGrcV2feUtIZ +-----END PRIVATE KEY----- diff --git a/async-nats/tests/configs/ip-tls.conf b/async-nats/tests/configs/ip-tls.conf new file mode 100644 index 000000000..ba85c64a6 --- /dev/null +++ b/async-nats/tests/configs/ip-tls.conf @@ -0,0 +1,17 @@ +# Simple TLS config file + +port: 4443 +net: localhost # net interface + +tls { + cert_file: "./tests/configs/certs/ip-cert.pem" + key_file: "./tests/configs/certs/ip-key.pem" + ca_file: "./tests/configs/certs/ip-ca.pem" + timeout: 2 +} + +authorization { + user: derek + password: porkchop + timeout: 1 +} diff --git a/async-nats/tests/tls_tests.rs b/async-nats/tests/tls_tests.rs index f8ebd5fca..a46941c84 100644 --- a/async-nats/tests/tls_tests.rs +++ b/async-nats/tests/tls_tests.rs @@ -14,11 +14,22 @@ mod client { use std::path::PathBuf; + use futures::StreamExt; + #[tokio::test] async fn basic_tls() { let server = nats_server::run_server("tests/configs/tls.conf"); + + // Should fail without certs. assert!(async_nats::connect(&server.client_url()).await.is_err()); + // Should fail with IP (cert doesn't have proper SAN entry) + assert!( + async_nats::connect(format!("tls://127.0.0.1:{}", server.client_port())) + .await + .is_err() + ); + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); async_nats::ConnectOptions::with_user_and_password("derek".into(), "porkchop".into()) @@ -33,6 +44,19 @@ mod client { .unwrap(); } + #[tokio::test] + async fn ip_basic_tls() { + let server = nats_server::run_server("tests/configs/ip-tls.conf"); + + let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + async_nats::ConnectOptions::with_user_and_password("derek".into(), "porkchop".into()) + .add_root_certificates(path.join("tests/configs/certs/ip-ca.pem")) + .require_tls(true) + .connect(format!("tls://127.0.0.1:{}", server.client_port())) + .await + .unwrap(); + } #[tokio::test] async fn unknown_server_ca() { let server = nats_server::run_server("tests/configs/tls.conf"); @@ -75,9 +99,13 @@ mod client { .await .unwrap(); + let mut subscription = client.subscribe("subject".into()).await.unwrap(); client .publish("subject".into(), "data".into()) .await .unwrap(); + + client.flush().await.unwrap(); + assert!(subscription.next().await.is_some()); } }