From 67cb801f54fdd4f990ea5bbcc019330bd3c797d8 Mon Sep 17 00:00:00 2001 From: torque Date: Sat, 2 Sep 2023 17:12:00 -0700 Subject: [PATCH] tests.connection: add basic encrypted connection tests Since I went to the effort of getting this to build with LibreSSL, it makes sense to check that it works. And it seems to. There's nothing special about the certificates added, except that they don't expire for 100 years, which is hopefully long enough that nothing will matter any more. They get baked into the test executable, since this was the best way I could figure out to be able to consistently load them during runtime, since they're stored relative to the source, not necessarily relative to the working directory in use when the test executable is run. This required some augmentation to the test server launcher which will make it easier to add additional flags to it in the future, if that becomes necessary. --- src/connection.zig | 2 +- tests/connection.zig | 83 +++++++++++++++++++++++++++++------ tests/data/client-ecc.cert | 16 +++++++ tests/data/client-ecc.key | 6 +++ tests/data/client-rsa.cert | 34 ++++++++++++++ tests/data/client-rsa.key | 52 ++++++++++++++++++++++ tests/data/server-ecc.cert | 16 +++++++ tests/data/server-ecc.key | 6 +++ tests/data/server-rsa.cert | 34 ++++++++++++++ tests/data/server-rsa.key | 52 ++++++++++++++++++++++ tests/nats.zig | 2 +- tests/util.zig | 90 ++++++++++++++++++++++++++++---------- 12 files changed, 355 insertions(+), 38 deletions(-) create mode 100644 tests/data/client-ecc.cert create mode 100644 tests/data/client-ecc.key create mode 100644 tests/data/client-rsa.cert create mode 100644 tests/data/client-rsa.key create mode 100644 tests/data/server-ecc.cert create mode 100644 tests/data/server-ecc.key create mode 100644 tests/data/server-rsa.cert create mode 100644 tests/data/server-rsa.key diff --git a/src/connection.zig b/src/connection.zig index b77655e..6d88c43 100644 --- a/src/connection.zig +++ b/src/connection.zig @@ -60,7 +60,7 @@ pub const AddressPort = struct { }; pub const Connection = opaque { - pub fn create(options: *ConnectionOptions) Error!*Connection { + pub fn connect(options: *ConnectionOptions) Error!*Connection { var self: *Connection = undefined; const status = Status.fromInt(nats_c.natsConnection_Connect(@ptrCast(&self), @ptrCast(options))); return status.toError() orelse self; diff --git a/tests/connection.zig b/tests/connection.zig index 629bad2..738f4c9 100644 --- a/tests/connection.zig +++ b/tests/connection.zig @@ -7,6 +7,11 @@ const nats = @import("nats"); const util = @import("./util.zig"); +const rsa_key = @embedFile("./data/client-rsa.key"); +const rsa_cert = @embedFile("./data/client-rsa.cert"); +const ecc_key = @embedFile("./data/client-ecc.key"); +const ecc_cert = @embedFile("./data/client-ecc.cert"); + test "nats.Connection.connectTo" { { var server = try util.TestServer.launch(.{}); @@ -46,11 +51,6 @@ test "nats.Connection.connectTo" { } } -fn tokenHandler(userdata: *u32) [:0]const u8 { - _ = userdata; - return "token"; -} - fn reconnectDelayHandler(userdata: *u32, connection: *nats.Connection, attempts: c_int) i64 { _ = userdata; _ = connection; @@ -103,19 +103,10 @@ test "nats.ConnectionOptions" { try options.setServers(&servers); try options.setCredentials("user", "password"); try options.setToken("test_token"); - // requires a functioning token handler, which I will not write right now. Also - // cannot be called if a token has already been set - // try options.setTokenHandler(u32, tokenHandler, &userdata); try options.setNoRandomize(false); try options.setTimeout(1000); try options.setName("name"); - // the following all require a build with openssl - // try options.setSecure(false); - // try options.setCiphers("-ALL:HIGH"); - // try options.setCipherSuites("TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"); - // try options.setExpectedHostname("host.name"); - // try options.skipServerVerification(true); try options.setVerbose(true); try options.setPedantic(true); try options.setPingInterval(1000); @@ -147,3 +138,67 @@ test "nats.ConnectionOptions" { try options.setCustomInboxPrefix("_FOOBOX"); try options.setMessageBufferPadding(123); } + +fn tokenHandler(userdata: *u32) [:0]const u8 { + _ = userdata; + return "token"; +} + +test "nats.ConnectionOptions (crypto edition)" { + try nats.init(nats.default_spin_count); + defer nats.deinit(); + + const options = try nats.ConnectionOptions.create(); + defer options.destroy(); + var userdata: u32 = 0; + + try options.setTokenHandler(u32, tokenHandler, &userdata); + try options.setSecure(false); + try options.setCertificatesChain(rsa_cert, rsa_key); + try options.setCiphers("-ALL:HIGH"); + try options.setCipherSuites("TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256"); + try options.setExpectedHostname("test.nats.zig"); + try options.skipServerVerification(true); +} + +test "nats.ConnectionOptions (crypto connect)" { + { + var server = try util.TestServer.launch(.{ .tls = .rsa }); + defer server.stop(); + + try nats.init(nats.default_spin_count); + defer nats.deinit(); + + const options = try nats.ConnectionOptions.create(); + defer options.destroy(); + + try options.setSecure(true); + try options.skipServerVerification(true); + try options.setCertificatesChain(rsa_cert, rsa_key); + + const connection = try nats.Connection.connect(options); + defer connection.destroy(); + + try connection.publish("foo", "bar"); + } + + { + var server = try util.TestServer.launch(.{ .tls = .ecc }); + defer server.stop(); + + try nats.init(nats.default_spin_count); + defer nats.deinit(); + + const options = try nats.ConnectionOptions.create(); + defer options.destroy(); + + try options.setSecure(true); + try options.skipServerVerification(true); + try options.setCertificatesChain(ecc_cert, ecc_key); + + const connection = try nats.Connection.connect(options); + defer connection.destroy(); + + try connection.publish("foo", "bar"); + } +} diff --git a/tests/data/client-ecc.cert b/tests/data/client-ecc.cert new file mode 100644 index 0000000..d29c73d --- /dev/null +++ b/tests/data/client-ecc.cert @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIClTCCAhygAwIBAgIUNUxHIA2G0sEDgjWcx1svHk9wK1AwCgYIKoZIzj0EAwIw +gYAxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlTdGF0ZU5hbWUxETAPBgNVBAcMCENp +dHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFtZTEbMBkGA1UECwwSQ29tcGFueVNl +Y3Rpb25OYW1lMRcwFQYDVQQDDA50ZXN0cy5uYXRzLnppZzAgFw0yMzA5MDIyMjEz +MzJaGA8yMTIzMDgwOTIyMTMzMlowgYAxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlT +dGF0ZU5hbWUxETAPBgNVBAcMCENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFt +ZTEbMBkGA1UECwwSQ29tcGFueVNlY3Rpb25OYW1lMRcwFQYDVQQDDA50ZXN0cy5u +YXRzLnppZzB2MBAGByqGSM49AgEGBSuBBAAiA2IABPcAhGdzooeoL0SY1qJmY3SY +cyngBaon8ICyaQLRvOKEIhym25jB90xj4J2IDy3pg/5564G43NOOBZ/T4ClTv3XF ++2E71w+31HVGVKW4l+natAQt72oXn+HcjSnwrplYz6NTMFEwHQYDVR0OBBYEFFkN +/08ID2jBHkYMUzm7o8S8Ch86MB8GA1UdIwQYMBaAFFkN/08ID2jBHkYMUzm7o8S8 +Ch86MA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDZwAwZAIwWauKBQMCf6XT +K1y2TvNZpqehk+MsQ8aDcNoUJ+iALJM7Y89XpibdZ4hvGPsQK/cgAjAg8SXHVWS5 +yeFNtZdnRowEuQhtk5rRaj983wMSLbMXbz9Oxm0MY7edcS4MWP7l7nI= +-----END CERTIFICATE----- diff --git a/tests/data/client-ecc.key b/tests/data/client-ecc.key new file mode 100644 index 0000000..3030cda --- /dev/null +++ b/tests/data/client-ecc.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDDfkvPMjrVTAU06KSLK +vxKDF3+vdWDQUxQBIJ3F1qrSMJNzfuguXiYv8DMTbNvCNB+hZANiAAT3AIRnc6KH +qC9EmNaiZmN0mHMp4AWqJ/CAsmkC0bzihCIcptuYwfdMY+CdiA8t6YP+eeuBuNzT +jgWf0+ApU791xfthO9cPt9R1RlSluJfp2rQELe9qF5/h3I0p8K6ZWM8= +-----END PRIVATE KEY----- diff --git a/tests/data/client-rsa.cert b/tests/data/client-rsa.cert new file mode 100644 index 0000000..41ff772 --- /dev/null +++ b/tests/data/client-rsa.cert @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF5TCCA82gAwIBAgIUSiVHqM6yI2CBF8ZuakGuaXdAd0EwDQYJKoZIhvcNAQEL +BQAwgYAxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlTdGF0ZU5hbWUxETAPBgNVBAcM +CENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFtZTEbMBkGA1UECwwSQ29tcGFu +eVNlY3Rpb25OYW1lMRcwFQYDVQQDDA50ZXN0cy5uYXRzLnppZzAgFw0yMzA5MDIy +MjE0MDZaGA8yMTIzMDgwOTIyMTQwNlowgYAxCzAJBgNVBAYTAlhYMRIwEAYDVQQI +DAlTdGF0ZU5hbWUxETAPBgNVBAcMCENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55 +TmFtZTEbMBkGA1UECwwSQ29tcGFueVNlY3Rpb25OYW1lMRcwFQYDVQQDDA50ZXN0 +cy5uYXRzLnppZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOF2MLuH +xvEUbc2PXQKhTL7flDvl/KWGxikE4HBQ96vQ3bHAzVuLezTI9D0qLTOvY1SVBy0C +En4e5ZklufTHciOg/a1B76IC2EFPEnhY0oO7pLfLzA43MU7biNvb1BGPW/MEihOZ +2ZmGnK1CiwynFKTkRJdafzK8OrQV9nmz+WNX0UqbDH6Gjp36V6VMcz+gHi01hqK+ +v1lbAuUATGNEoZSVpGSoJx4+Ogyob9f4irsJX7GpO0dsKHUwd51pAm1pkpOH1rIU +CM+biSYaLt5fxFkSUJc9wqa+odE997hu5Ch6EEkdwg/4vYnigBMZxwFB3EVinXI0 +5ywrYMwO8ozCrKmIDVG/FhNlzspooKVkZFKl8/T/1n8rDElsLc8No7clD0xFQxU8 +3qyw05yaYm3khDMWTaD/B2w3AOoifZ9oWr6Ra2NN57yQx4sQdDy8s0WY4rVkv/nX +9VsBSeJwmmCfnnpse1Tq4Wfo7Jjz1Akl4n0GAQxkxR6gAkCfnkJrdkMKaOPQe+ep +Fs+5g2VrIeWQgzs5L4rte1qtMokK963IvqDSnsbPM6m9tcMQb8r+A0YbEOAK6D0D +nnKcguSKNkPP8hwaqJ9XNDXSN65I+DsgX0ngfHCh/grkSPJI2oEmx4DeaA8hgRzh +zbGpazOcVa4ahyUCxZKZi9c/+Aw3gir0fpQbAgMBAAGjUzBRMB0GA1UdDgQWBBRI +3sPebMsmYX0ourw+0SA8BqcXwTAfBgNVHSMEGDAWgBRI3sPebMsmYX0ourw+0SA8 +BqcXwTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCkGzTMZdGT +dUQBbAqTzHvoc1Vy5OxadgJ4UGly9s7GpYg8brsevFmHyGHl+J9dBsnhmmNGxs1t +rU5lvnMWLOyvg7iLyx/4rkNAR03wyRgx1jK+4xIxMBj7YDB0WK6AtL3OUiqvTW4h +INoEIylyrIIOf7oHS9UkzDdZ3ZghH+EADjE6ksM/PuCRK0oTz9z7LUSMlcI5UCeb +P/V6N2QHzz2n+/BvTo/bpjHrwyUZ+eZbUC7rCfZX7Pi/pTGS2bps16lO2Us6tzIn +9If5h+MHHGOZXQtOZPYDFi3nLo/E+bBzt6Lvrt0Vm5DjXKzplrq+UMPbsEtGue7v +xSfcbPsXf44n+kZSFtFTjZ4zqpP05/H3R5eTayRUhVLkJlxDZbPiFjOSEupUmZq+ +cpmf6Mq9OJJimyJBRaC0Lex4mCDUarXYLXXyNaIAQ2O+EmaNxZ2B86gHy6R3gaHr +w66pDXq0IXznJyr50aKu7WYJHOE5HOaBgptU7lXz35+5yId7WKWorXfGIYBWCc3g +LRDr0pgyLk1YVxz2tphR8hEJ7rJb+gMR3t5UzDElsUIqKJo/6Aziq4dRlrj5x62s +Vmm7JJqMSyh6UDJowwFicS3KTZbKZnxRHdyy8Km6gRvi26pdNWW5+/57ETLG3cn5 ++MDARAttyn8SEhbPolxttebRKDAIFnxYkQ== +-----END CERTIFICATE----- diff --git a/tests/data/client-rsa.key b/tests/data/client-rsa.key new file mode 100644 index 0000000..abc11d6 --- /dev/null +++ b/tests/data/client-rsa.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +qnLykaAJSPCsd4jY4P3EtZLNbee3fQ== +-----END PRIVATE KEY----- diff --git a/tests/data/server-ecc.cert b/tests/data/server-ecc.cert new file mode 100644 index 0000000..c020aab --- /dev/null +++ b/tests/data/server-ecc.cert @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICljCCAhygAwIBAgIUcjxQ8y9DFk5UChiI2CTG4fKNuzswCgYIKoZIzj0EAwIw +gYAxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlTdGF0ZU5hbWUxETAPBgNVBAcMCENp +dHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFtZTEbMBkGA1UECwwSQ29tcGFueVNl +Y3Rpb25OYW1lMRcwFQYDVQQDDA50ZXN0cy5uYXRzLnppZzAgFw0yMzA5MDIyMjEy +NDJaGA8yMTIzMDgwOTIyMTI0MlowgYAxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlT +dGF0ZU5hbWUxETAPBgNVBAcMCENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFt +ZTEbMBkGA1UECwwSQ29tcGFueVNlY3Rpb25OYW1lMRcwFQYDVQQDDA50ZXN0cy5u +YXRzLnppZzB2MBAGByqGSM49AgEGBSuBBAAiA2IABL1QQVL1CUI+g8EAFtW4OYRk +bsa4GpLMojjWYGZ5azB6zFJsjqr626hwl8B+yUOLV8O8COZtSHhh9TOwMK9my+mF +jSlRLkBhViJtiQS/i+lOAHLSZhyYGi0LMwR/84s9zqNTMFEwHQYDVR0OBBYEFDep +AJQvuHNpqaxaBt5Md4mAcMcBMB8GA1UdIwQYMBaAFDepAJQvuHNpqaxaBt5Md4mA +cMcBMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwIDaAAwZQIwWiMIHiOwfO0+ +CcjrMZmSVqhBiDY8bcJgpPFCp+GFfPiTwse1eUQhYE0K2onU1mYTAjEA7atUdQxL +8SjkuTRdvNoRJ2EOVMHMeaYMU5HPAxHhIPDWBaHmHOHgOx5hUw/chRjf +-----END CERTIFICATE----- diff --git a/tests/data/server-ecc.key b/tests/data/server-ecc.key new file mode 100644 index 0000000..ff06900 --- /dev/null +++ b/tests/data/server-ecc.key @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAdXFWFvY4ujDsDxw2e +Vga7jpgVBKAg7mEA/AYL+yjLanR52DJ6XM8iU4qbPEaMH66hZANiAAS9UEFS9QlC +PoPBABbVuDmEZG7GuBqSzKI41mBmeWswesxSbI6q+tuocJfAfslDi1fDvAjmbUh4 +YfUzsDCvZsvphY0pUS5AYVYibYkEv4vpTgBy0mYcmBotCzMEf/OLPc4= +-----END PRIVATE KEY----- diff --git a/tests/data/server-rsa.cert b/tests/data/server-rsa.cert new file mode 100644 index 0000000..e4a56ba --- /dev/null +++ b/tests/data/server-rsa.cert @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +MIIF5TCCA82gAwIBAgIUUIWzfooDSLVR8sW3AiBJuqDHZMYwDQYJKoZIhvcNAQEL +BQAwgYAxCzAJBgNVBAYTAlhYMRIwEAYDVQQIDAlTdGF0ZU5hbWUxETAPBgNVBAcM +CENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55TmFtZTEbMBkGA1UECwwSQ29tcGFu +eVNlY3Rpb25OYW1lMRcwFQYDVQQDDA50ZXN0cy5uYXRzLnppZzAgFw0yMzA5MDIy +MjA5MTdaGA8yMTIzMDgwOTIyMDkxN1owgYAxCzAJBgNVBAYTAlhYMRIwEAYDVQQI +DAlTdGF0ZU5hbWUxETAPBgNVBAcMCENpdHlOYW1lMRQwEgYDVQQKDAtDb21wYW55 +TmFtZTEbMBkGA1UECwwSQ29tcGFueVNlY3Rpb25OYW1lMRcwFQYDVQQDDA50ZXN0 +cy5uYXRzLnppZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOolz+6A +j1S3fJl8VSglQBaOplTsukup0Li7pDluS+Sgj5G5Vvl1Ki8jPVTWz9HcYl/7jgFz +iE7AG7qymH1+q/smzxl59MyiKkBPSvynRQ/iY35uyyCFSxgqNSFqnahzHmd1BpNX +9WJX2iRs+UyaWjhtj7T2cbIr2UZQtCUqF/ae0jeR+hb6beQCMoGzFG3Zn9uupazg +u49WdNmOSE/qf6DAmftnmdX7pc7u6jclMAk8WOvjL9LoxK8Nu+ZGusklJohjbUsG +DNdktsaqZQphlXbVCa6gV6cITup2oFmHQvMcncZ2xtYs/4Ul45UxGGEWGWQLQtaJ +KSS5B5YAkXTCga8k/cS+NRyy/NxQmuR3FeQUYYfMpiNhXweZ7zEWjosU9jjEiS6w +UhlTCQYH6p9/jZmByE8DySNQtcexV1IBVzOYsg7MS/AwHq9ym9iqT9tx+S9Vub/f +ysbgQU9GkKeic64iYVC+gG/Y2W8XS9LSzSKCJuvf8EUD18g3dmmRxzltwq7oH14W +f0KjyhwdzeJUhoEvPgaEgWvlvff9uSP0utX/KmOJPJckjoQrk9RN/GDxR01U2SPf +1pVclir3IEWSPOCNSil8Et/ut1MI7JGlDhsysZA3zoqIPAu+QYVUEytdSf+n3UHf +ZvT7VdDQlNyq2XYaP9kBEx4P7oGfto/HHOHtAgMBAAGjUzBRMB0GA1UdDgQWBBQV +GBaOUXiHmG3KT2uiwgOR7xBDSDAfBgNVHSMEGDAWgBQVGBaOUXiHmG3KT2uiwgOR +7xBDSDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4ICAQCZhqnD3uVi +3q2plOHUBnlkYcCCoC0W7AHPSJ1pcb/wa1CgSkrXHNhBmaWfWEbs+JJ+eMHxStFr +kdJWNbVEnmS27ruMNE6S5XCj/1zdqncZnCr3gLRdmvb3S5yZHGphgEdNrAvPKIyi +XtfmROVh3y2/ZENRZfdJ984xU/yaHmfTy8ULiSCe0Jz9dxHvTgUCrZ5RVEIwmAkL +gcs1Hrw/5TDs/DagsNliH2Atn6cYzhAostBN9wDkra6xUkRqscE8R7D2/XJni+W3 +toL+DTTFIww0pNlh2BWG5DMqeLdYPODhuxWWw5JhdKWx3cisPhiJ9RDKaSy532wC +i/tjKQAnNWQRvGFGfJDMIEcPL3s1JhQM/lhSanlloMsxHmGpOJOEI6IN0clYpPaX +7COo+qvGueQPRLDq/7vDRM3i7sQHBHeC71VdEN4TgyJQvQcGMFjGPPQ868VvJhYG +2CbUWhBaADWlWjZ5d5tMI+WT8J/y6D6cSOymXcgbHV8DpUCB9vImmTKvgiL9TLi1 +PxZCP9nLUOCmCSnbz4vhupvxM38KesuvAfOUPKTEixjXBfD9iiEKVnMUKVv31TLO +5sfeYf6Zn8oDFCInUgdHgQRs/UXOAOTWYsOQQhS6xfZXJHom/Mcy0Q2TxsiI2dmw +ah/FB4DsF0XDCuDqGJWyywTbzQnh55uBBQ== +-----END CERTIFICATE----- diff --git a/tests/data/server-rsa.key b/tests/data/server-rsa.key new file mode 100644 index 0000000..78f22b7 --- /dev/null +++ b/tests/data/server-rsa.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +u2Iow+n+vuh3lPHBmdmCxfYo50P+HA== +-----END PRIVATE KEY----- diff --git a/tests/nats.zig b/tests/nats.zig index 7407c60..73ba9f6 100644 --- a/tests/nats.zig +++ b/tests/nats.zig @@ -70,7 +70,7 @@ test "misc" { // and switch. const signed = nats.sign("12345678", "12345678") catch { const err = nats.getLastError(); - std.debug.print("signing failed: {s}\n", .{err.desc}); + std.debug.print("as expected, signing failed: {s}\n", .{err.desc}); var stackmem = [_]u8{0} ** 512; var stackbuf: []u8 = &stackmem; diff --git a/tests/util.zig b/tests/util.zig index 68e9306..deb61f1 100644 --- a/tests/util.zig +++ b/tests/util.zig @@ -3,12 +3,24 @@ const std = @import("std"); +const KeyCert = struct { key: [:0]const u8, cert: [:0]const u8 }; +const server_rsa: KeyCert = .{ + .key = @embedFile("./data/server-rsa.key"), + .cert = @embedFile("./data/server-rsa.cert"), +}; + +const server_ecc: KeyCert = .{ + .key = @embedFile("./data/server-ecc.key"), + .cert = @embedFile("./data/server-ecc.cert"), +}; + const TestLaunchError = error{ NoLaunchStringFound, }; pub const TestServer = struct { process: std.ChildProcess, + key_dir: ?std.testing.TmpDir, pub const LaunchOptions = struct { executable: []const u8 = "nats-server", @@ -18,38 +30,71 @@ pub const TestServer = struct { token: []const u8, password: struct { user: []const u8, pass: []const u8 }, } = .none, + tls: enum { + none, + rsa, + ecc, + } = .none, allocator: std.mem.Allocator = std.testing.allocator, - - fn argLen(self: LaunchOptions) usize { - // executable, -a, 127.0.0.1, -p, 4222 - const base_len: usize = 5; - return base_len + switch (self.auth) { - .none => @as(usize, 0), - .token => @as(usize, 2), - .password => @as(usize, 4), - }; - } }; pub fn launch(options: LaunchOptions) !TestServer { - // const allocator = std.testing.allocator; var portbuf = [_]u8{0} ** 5; const strport = try std.fmt.bufPrint(&portbuf, "{d}", .{options.port}); - const argsbuf: [9][]const u8 = blk: { - const executable: [1][]const u8 = .{options.executable}; - const listen: [2][]const u8 = .{ "-a", "127.0.0.1" }; - const port: [2][]const u8 = .{ "-p", strport }; - const auth: [4][]const u8 = switch (options.auth) { - .none => .{""} ** 4, - .token => |tok| .{ "--auth", tok, "", "" }, - .password => |auth| .{ "--user", auth.user, "--pass", auth.pass }, + var key_dir: ?std.testing.TmpDir = null; + var key_path: ?[]const u8 = null; + var cert_path: ?[]const u8 = null; + // ChildProcess copies these, so we can free them before the process has + // closed. + defer { + if (key_path) |kp| options.allocator.free(kp); + if (cert_path) |cp| options.allocator.free(cp); + } + + const args: [][]const u8 = blk: { + const executable: []const []const u8 = &.{options.executable}; + const listen: []const []const u8 = &.{ "-a", "127.0.0.1" }; + const port: []const []const u8 = &.{ "-p", strport }; + const auth: []const []const u8 = switch (options.auth) { + .none => &[_][]const u8{}, + .token => |tok| &[_][]const u8{ "--auth", tok }, + .password => |auth| &[_][]const u8{ "--user", auth.user, "--pass", auth.pass }, + }; + const tls: []const []const u8 = switch (options.tls) { + .none => &[_][]const u8{}, + .rsa, .ecc => |keytype| keyb: { + const pair = switch (keytype) { + .rsa => server_rsa, + .ecc => server_ecc, + else => unreachable, + }; + + const out_dir = std.testing.tmpDir(.{}); + try out_dir.dir.writeFile("server.key", pair.key); + try out_dir.dir.writeFile("server.cert", pair.cert); + // since testing.tmpDir will actually bury itself in zig-cache/tmp, + // there's not an easy way to extract files from within the temp + // directory except through using realPath, as far as I can tell + // (or reproducing the path naming logic, but that seems fragile). + const out_key = try out_dir.dir.realpathAlloc(options.allocator, "server.key"); + const out_cert = try out_dir.dir.realpathAlloc(options.allocator, "server.cert"); + + key_dir = out_dir; + key_path = out_key; + cert_path = out_cert; + break :keyb &[_][]const u8{ "--tls", "--tlscert", out_cert, "--tlskey", out_key }; + }, }; - break :blk executable ++ listen ++ port ++ auth; + break :blk try std.mem.concat( + options.allocator, + []const u8, + &.{ executable, listen, port, auth, tls }, + ); }; - const args = argsbuf[0..options.argLen()]; + defer options.allocator.free(args); var child = std.ChildProcess.init(args, options.allocator); child.stdin_behavior = .Ignore; @@ -62,7 +107,7 @@ pub const TestServer = struct { while (try poller.poll()) { if (std.mem.indexOf(u8, poller.fifo(.stderr).buf, "[INF] Server is ready")) |_| { - return .{ .process = child }; + return .{ .process = child, .key_dir = key_dir }; } } @@ -72,6 +117,7 @@ pub const TestServer = struct { } pub fn stop(self: *TestServer) void { + if (self.key_dir) |*key_dir| key_dir.cleanup(); _ = self.process.kill() catch return; } };