diff --git a/certs/ca-key.pem b/certs/ca-key.pem new file mode 100644 index 0000000..3ea9731 --- /dev/null +++ b/certs/ca-key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAm2N8QHBg9TWnGslkBEMkBvggBFPmvJ6IRNCRBeeC7QcrLvHF +KZ6TAeM1kQq2Saaodso35xABW1kecb9HPEtIIMYMVP0kaCwUN+77cf+loSYwZwq6 +ZHzoHVXEkUt6HEeNw7nFxApYmgufEbFwa8rzKY+DZQ0ZD9HJjYOT55hcL6sbRns7 +JG8/gfWx3qz8roXR0idVydVa9MROED1db9JuI5L9g+DMpJ5zOVf/V4w8kaZsU6hQ +rIwgANlH6dZJt1+BUxu6H9t6EZUe7eT04lviZG0ydOwBqsdDOXk/pukQZiLDJdDI +/QOzd/SvtYsv/KTprRSi68/cik7iTXuPlb196QIDAQABAoIBADRkYdOUUIy9D1/P +wYJSZQZYiOsMowK77TROomc8PP/QZ/YHHLRAvE5pnnkOBJJmt+x9mEW3Ns3nCYXO +uaURuPsb67KIO8tH+XU2hd9VFDJ2nuFPU7NoDhc+AO4AZea9FYaFz7Gez2r5OiQM +ENy3bC96LRJYTTfxQyUM1UTEMWj8oNFq7ySa9p9WWrJ2WUM9IdBUkpjN+pGFqW5m +PkeViIquQqkqfhCoNLeRpqo2IpZOye32nMIbp5gVvnpW7ALL36MNB2tYbH6h+Iik +FQ3QtCfeHy5R3zPeBZWeDrJK11jQpQZX6ZTxCP9pt3baPGHPppNqQ6kTSXBUQoAv +JcrYfoUCgYEAx2hrwtuu4ne8jtLdHAB079Uw1mult4CMOGwWl/MP93yc++3XPboG +tF2l/LFLc8hpQrkRAbYVw1Xp3U84vxkjM9EsOIfMn/KsYDxRHXv4fCDMS57js/eC +07vzyJWvMkyiW+gl77Z0iyDwhIw6TiXI58XH5luok420xrQi/YxYB8MCgYEAx3zu +qll6tcebq1lf/XxZUy69iJXesBN9qpG/B2jbt8szt5ARszYaPOKwSAv/UXbRHYvl +Bpe8fbwxgQJJlygaDTjBVVtmN/ANia8UXEjKaohTdxFWPkWNViJiUsQ8UPXIxE48 +LOZe/Ja0MmJOs5EvZNFh2w03mlHifp/3Go7JNOMCgYAmzzDh7MWdt/YPygRUldYs +c06c/Lh0/WTM+mRvUFQUM8GN2p1gmxsA8ZUDmDH6J9Astz4TGjAkI01v0CJYNvk9 +9YDow61Ul/Nqi3KyDVWwOuXn9dWVSh/BO7xXlqJRZM7Ymlb/z3/hMBj/gxc57Gqs +iTa9o6sshJDhd1+z/yOG5wKBgBegclv2sRPqikNnGHlbSvERLh2JMpDEHjQfgvKL +tsoz5PIuvAnvtHfVmW9PDHRHkEjhksSPICH8MhjHfpPKihtax3smkhq58cCG3fB4 +JpEriEcn5IEHl8/FzsNivooQMjEd2v6uYj2kU79L6WpXHbfhHKfnDtjWLe81Xvzk +QGxlAoGBALtVXT+vHK8atg9utCTxA9Ckqm00t0cpZw68+KlZaoAncd8c086yKUe1 +n+IpKxKDJ1JAG5Zq5k29FuCkfD7KteLp49GwHNZItSPdadvfZOCIyIMvDGIOZYuK +jVd8TONCnTNigSqoqCLCrQfcet+8iXKGSWt+AF+P78Ydx2yLpza/ +-----END RSA PRIVATE KEY----- diff --git a/certs/ca.csr b/certs/ca.csr new file mode 100644 index 0000000..0100ae6 --- /dev/null +++ b/certs/ca.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICmTCCAYECAQAwVDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEx +EjAQBgNVBAcTCVNhbiBEaWVnbzENMAsGA1UEChMEbmF0czENMAsGA1UEAxMEbmF0 +czCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJtjfEBwYPU1pxrJZARD +JAb4IART5ryeiETQkQXngu0HKy7xxSmekwHjNZEKtkmmqHbKN+cQAVtZHnG/RzxL +SCDGDFT9JGgsFDfu+3H/paEmMGcKumR86B1VxJFLehxHjcO5xcQKWJoLnxGxcGvK +8ymPg2UNGQ/RyY2Dk+eYXC+rG0Z7OyRvP4H1sd6s/K6F0dInVcnVWvTEThA9XW/S +biOS/YPgzKSeczlX/1eMPJGmbFOoUKyMIADZR+nWSbdfgVMbuh/behGVHu3k9OJb +4mRtMnTsAarHQzl5P6bpEGYiwyXQyP0Ds3f0r7WLL/yk6a0UouvP3IpO4k17j5W9 +fekCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQATWXkL9AE3VRdaQRjf3GDmGbqp +A3fWEaIRqUtIiFEWpvk2UBPuwN3hdY7JeEmTm6i3hk2paAGgO3uHWVu4S7HqfjLv +fAAcgk7c/6jbBBnuomZ5gUbB0IpDy4DQI7D8wkHydJMPgwr24RJDvok2NL+h1ZXf +trkyjpUG5nor7GASiYuEJqhha616bin3n+68ZYLjV0VoApbRvMdAe4ZOBZKY9/8w +3vxN2AGZNDdDEv0ZpZi4rQCTQHQfuosm2reGzJra4pir9TQKfk/AG1mln8qC0aqn +LsCzZCJtkvq2w7KxEDyMUmh7h9UTHrPwUfpaEV6Nqr8Nf9SqRPmxU8RJUI5i +-----END CERTIFICATE REQUEST----- diff --git a/certs/ca.json b/certs/ca.json new file mode 100644 index 0000000..61f67e9 --- /dev/null +++ b/certs/ca.json @@ -0,0 +1,15 @@ +{ + "CN": "nats", + "key": { + "algo": "rsa", + "size": 2048 + }, + "names": [ + { + "C": "US", + "L": "San Diego", + "O": "nats", + "ST": "California" + } + ] +} \ No newline at end of file diff --git a/certs/ca.pem b/certs/ca.pem new file mode 100644 index 0000000..4ee4c96 --- /dev/null +++ b/certs/ca.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDeDCCAmCgAwIBAgIUT8QdiHpoNNfvL36Rx3h2o2nXj2wwDQYJKoZIhvcNAQEL +BQAwVDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcT +CVNhbiBEaWVnbzENMAsGA1UEChMEbmF0czENMAsGA1UEAxMEbmF0czAeFw0yMDEw +MjMwNDIwMDBaFw0yNTEwMjIwNDIwMDBaMFQxCzAJBgNVBAYTAlVTMRMwEQYDVQQI +EwpDYWxpZm9ybmlhMRIwEAYDVQQHEwlTYW4gRGllZ28xDTALBgNVBAoTBG5hdHMx +DTALBgNVBAMTBG5hdHMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCb +Y3xAcGD1NacayWQEQyQG+CAEU+a8nohE0JEF54LtBysu8cUpnpMB4zWRCrZJpqh2 +yjfnEAFbWR5xv0c8S0ggxgxU/SRoLBQ37vtx/6WhJjBnCrpkfOgdVcSRS3ocR43D +ucXECliaC58RsXBryvMpj4NlDRkP0cmNg5PnmFwvqxtGezskbz+B9bHerPyuhdHS +J1XJ1Vr0xE4QPV1v0m4jkv2D4MyknnM5V/9XjDyRpmxTqFCsjCAA2Ufp1km3X4FT +G7of23oRlR7t5PTiW+JkbTJ07AGqx0M5eT+m6RBmIsMl0Mj9A7N39K+1iy/8pOmt +FKLrz9yKTuJNe4+VvX3pAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBRfcBLfgqhpBwyVbOZdC/tMyespEDANBgkqhkiG +9w0BAQsFAAOCAQEAZfL9qetvorLgjGb6idBrhhbHuVvXgnohru3KsB8C2PVbDsTX +7z8b+NKN+C09T0LhgDlkf5gOqXvRTC0LqSQsXHD5ytTSswYH1K8QZSBOzDL5Zz2V +0bAsClt7J7Es8Q/RZKrxOrcLe5+rihDAcFt+SwQG5zz4Z4itnHbyNwHaH1tj/PWy +W9UDWq57HKH0AzCYM96EKYXf90UDK2ZzaINB9GT8TI6X2hjItn6ExMtOBoHbopJ5 +RoUoRy9AZjoSrOWa92TZkoQCLKmqWh5NdnP6G0jPuHzHxiCfCEqkYXEUEUYtigrx +aOcSU/8PadHNHoLu8wo0OfnyZp30Zw6duyg7Pg== +-----END CERTIFICATE----- diff --git a/certs/config.json b/certs/config.json new file mode 100644 index 0000000..f4ea147 --- /dev/null +++ b/certs/config.json @@ -0,0 +1,18 @@ +{ + "signing": { + "default": { + "expiry": "43800h" + }, + "profiles": { + "server": { + "expiry": "43800h", + "usages": [ + "signing", + "digital signing", + "key encipherment", + "server auth" + ] + } + } + } +} \ No newline at end of file diff --git a/certs/server-key.pem b/certs/server-key.pem new file mode 100644 index 0000000..0cb2f69 --- /dev/null +++ b/certs/server-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIIkrP8cig7mW3Z5qF8chGT99r2Rb7ORk7fQKWxYVfEU0oAoGCCqGSM49 +AwEHoUQDQgAE8LlUBCS4ghLkvzPrBEZWcug99fpb1K6D4waV2fYpQ1OVuKx7vi1K +e43f0lV8VcjvRB7E3J9sDveZ9qZidmycDw== +-----END EC PRIVATE KEY----- diff --git a/certs/server.csr b/certs/server.csr new file mode 100644 index 0000000..d365db6 --- /dev/null +++ b/certs/server.csr @@ -0,0 +1,7 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIHtMIGVAgEAMBExDzANBgNVBAMTBlNlcnZlcjBZMBMGByqGSM49AgEGCCqGSM49 +AwEHA0IABPC5VAQkuIIS5L8z6wRGVnLoPfX6W9Sug+MGldn2KUNTlbise74tSnuN +39JVfFXI70QexNyfbA73mfamYnZsnA+gIjAgBgkqhkiG9w0BCQ4xEzARMA8GA1Ud +EQQIMAaHBH8AAAEwCgYIKoZIzj0EAwIDRwAwRAIgQKiuZ/jQ9/w7z6nd9ychy9J8 +d7wva8+STodsWbPc65ECIE+O67914O5crAid2iwLaVRIprxojlglG56zkX9O+Mz9 +-----END CERTIFICATE REQUEST----- diff --git a/certs/server.json b/certs/server.json new file mode 100644 index 0000000..82b798c --- /dev/null +++ b/certs/server.json @@ -0,0 +1,6 @@ +{ + "CN": "Server", + "hosts": [ + "127.0.0.1" + ] +} \ No newline at end of file diff --git a/certs/server.pem b/certs/server.pem new file mode 100644 index 0000000..2505d2c --- /dev/null +++ b/certs/server.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICsDCCAZigAwIBAgIUJeeD2Whl+DzB1xP4E9ewIJXMSYgwDQYJKoZIhvcNAQEL +BQAwVDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExEjAQBgNVBAcT +CVNhbiBEaWVnbzENMAsGA1UEChMEbmF0czENMAsGA1UEAxMEbmF0czAeFw0yMDEw +MjMwNDIzMDBaFw0yNTEwMjIwNDIzMDBaMBExDzANBgNVBAMTBlNlcnZlcjBZMBMG +ByqGSM49AgEGCCqGSM49AwEHA0IABPC5VAQkuIIS5L8z6wRGVnLoPfX6W9Sug+MG +ldn2KUNTlbise74tSnuN39JVfFXI70QexNyfbA73mfamYnZsnA+jgYcwgYQwDgYD +VR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAw +HQYDVR0OBBYEFLY1SUjWP/eBmRLNdWAd0TfJyhktMB8GA1UdIwQYMBaAFF9wEt+C +qGkHDJVs5l0L+0zJ6ykQMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQELBQAD +ggEBACELpjhp3e+rj8Jnvk8hzbJDt24WtO2EPRS06MKsWr1WTjgLJmgZPNiCD4u/ +ANZpjxAnn4VgteaUS59uPNdlbqKTslRWeRtByHq5sHqCCA+xhgIMMGzUbSHrH+Um +W7SSrAAm16/TtjVwu727qH0U38oLEuxmZ9y7tQmF12ZLrV3xSVr/XR2k6VmPL2Pt +xgzKn5/Y02onggZk5ov13mTuV9M1HM0Jg5snCZ1M702ipAvJeh/kD0HAzf8EgJ/l +RAjvEz/S5BrNJ5HtU4Ug8Pl84iPAYHesAiPENHJYuXKi1UWOLI2rnVfWx5MCEhQM +cHxOTXr1uHXl0im2ldbEWOlZ+3U= +-----END CERTIFICATE----- diff --git a/spec/nats/tls_spec.cr b/spec/nats/tls_spec.cr index 8d89be6..d28c9cd 100644 --- a/spec/nats/tls_spec.cr +++ b/spec/nats/tls_spec.cr @@ -1,7 +1,14 @@ require "../spec_helper" describe "NATS::Connection#TLS" do + folders = __DIR__.split("/") + cert_dir = "#{folders[0...-2].join("/")}/certs" + tls_uri = "tls://demo.nats.io" + tls_with_cert_uri = "tls://127.0.0.1:4322" + tls_ca_cert = "#{cert_dir}/ca.pem" + tls_cert = "#{cert_dir}/server.pem" + tls_key = "#{cert_dir}/server-key.pem" describe "#new" do it "should connect to a TLS based server" do @@ -9,6 +16,21 @@ describe "NATS::Connection#TLS" do nc.should_not be_nil nc.close end + + it "should connect to a TLS based server with tls config" do + uri = URI.parse(tls_with_cert_uri) + server = NATSServer.new(uri, "--tls --tlscert=#{tls_cert} --tlskey=#{tls_key}") + server.start(false) + server.wait_for_server(uri) + + nc = NATS::Connection.new(tls_with_cert_uri, tls_config: {"ca" => tls_ca_cert, "key" => tls_key, "cert" => tls_cert}) + nc.should_not be_nil + nc.close + + server.try(&.shutdown) + sleep(20.millisecond) + server = nil + end end describe "#subscribe" do diff --git a/src/nats/connection.cr b/src/nats/connection.cr index 9b2541b..f9d962f 100644 --- a/src/nats/connection.cr +++ b/src/nats/connection.cr @@ -47,6 +47,7 @@ module NATS # ``` # nc = NATS::Connection.new("demo.nats.io") # nc = NATS::Connection.new("tls://demo.nats.io") + # nc = NATS::Connection.new("tls://demo.nats.io", tls_config: {"ca" => "ca.pem", "key" => "cert.key", "cert" => "cert.pem"}) # nc = NATS::Connection.new("nats://#{user}:#{pass}@127.0.0.1:4222") # nc = NATS::Connection.new(4222, name: "Sample App", user: "derek", pass: "s3cr3t") # nc = NATS::Connection.new(4222) @@ -58,7 +59,8 @@ module NATS @pass : String? = nil, @name : String? = nil, @echo = true, - @pedantic = false + @pedantic = false, + @tls_config : Hash(String, String)? = nil ) # For new style INBOX behavior. @nuid = NUID.new @@ -523,9 +525,12 @@ module NATS raise "INFO not valid" end - # FIXME(dlc) - client side certs, etc. tls_required = @server_info["tls_required"].as_bool rescue false - @socket = OpenSSL::SSL::Socket::Client.new(@socket) if tls_required + if tls_required + context = @tls_config.nil? ? OpenSSL::SSL::Context::Client.new : OpenSSL::SSL::Context::Client.from_hash(@tls_config.as(Hash(String, String))) + + @socket = OpenSSL::SSL::Socket::Client.new(@socket, context) + end end private def send_connect