From e8008b12f9ab2736bf198bdd164fe0b13e46ea56 Mon Sep 17 00:00:00 2001 From: Tero Saarni Date: Thu, 14 Sep 2023 11:35:43 +0300 Subject: [PATCH] Added support for CRL check (#62) Add support for CRL to check for the server certificate is revocation status. Co-authored-by: @tsaarni --- CHANGELOG.md | 1 + docs/index.asciidoc | 20 ++++ lib/logstash/outputs/syslog.rb | 16 +++ spec/fixtures/README.txt | 1 + spec/fixtures/ca-crl.pem | 11 ++ spec/fixtures/ca-key.pem | 28 +++++ spec/fixtures/ca.pem | 18 +++ spec/fixtures/certs.yaml | 34 ++++++ spec/fixtures/client-key.pem | 28 +++++ spec/fixtures/client.pem | 18 +++ spec/fixtures/invalid.pem | 1 + spec/fixtures/revoked-server-key.pem | 28 +++++ spec/fixtures/revoked-server.pem | 18 +++ spec/fixtures/untrusted-server-key.pem | 28 +++++ spec/fixtures/untrusted-server.pem | 18 +++ spec/fixtures/valid-server-key.pem | 28 +++++ spec/fixtures/valid-server.pem | 18 +++ spec/outputs/syslog_tls_spec.rb | 152 +++++++++++++++++++++++++ 18 files changed, 466 insertions(+) create mode 100644 spec/fixtures/README.txt create mode 100644 spec/fixtures/ca-crl.pem create mode 100644 spec/fixtures/ca-key.pem create mode 100644 spec/fixtures/ca.pem create mode 100644 spec/fixtures/certs.yaml create mode 100644 spec/fixtures/client-key.pem create mode 100644 spec/fixtures/client.pem create mode 100644 spec/fixtures/invalid.pem create mode 100644 spec/fixtures/revoked-server-key.pem create mode 100644 spec/fixtures/revoked-server.pem create mode 100644 spec/fixtures/untrusted-server-key.pem create mode 100644 spec/fixtures/untrusted-server.pem create mode 100644 spec/fixtures/valid-server-key.pem create mode 100644 spec/fixtures/valid-server.pem create mode 100644 spec/outputs/syslog_tls_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cffa66..e0fde3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Change codec instance comparison [#69](https://github.com/logstash-plugins/logstash-output-syslog/pull/69) - Added support for RFC5424 structured data [#67](https://github.com/logstash-plugins/logstash-output-syslog/pull/67) - The SNI (Server Name Indication) extension is now used when connecting to syslog server with TLS and `host` is set to FQDN (Fully Qualified Domain Name) [#66](https://github.com/logstash-plugins/logstash-output-syslog/pull/66) + - Add support for CRL to check for the server certificate is revocation status [#62](https://github.com/logstash-plugins/logstash-output-syslog/pull/62) ## 3.0.5 - Docs: Set the default_codec doc attribute. diff --git a/docs/index.asciidoc b/docs/index.asciidoc index fee925f..c33f48e 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -58,6 +58,8 @@ This plugin supports the following configuration options plus the <> |a valid filesystem path|No | <> |<>|No | <> |<>|No +| <> |a valid filesystem path|No +| <> |<>|No | <> |<>|No | <> |<>|No |======================================================================= @@ -226,6 +228,24 @@ SSL key passphrase Verify the identity of the other end of the SSL connection against the CA. +[id="plugins-{type}s-{plugin}-ssl_crl"] +===== `ssl_crl` + + * Value type is <> + * There is no default value for this setting. + +SSL CRL path for checking the revocation status of the server certificate. +File may contain one or more PEM encoded CRLs. + +[id="plugins-{type}s-{plugin}-ssl_crl_check_all"] +===== `ssl_crl_check_all` + + * Value type is <> + * Default value is `false` + +If this option is set to false, only the certificate at the end of the certificate chain will be subject to validation by CRL. +If set to true the complete chain is validated. CRLs must be available from all CAs. + [id="plugins-{type}s-{plugin}-use_labels"] ===== `use_labels` diff --git a/lib/logstash/outputs/syslog.rb b/lib/logstash/outputs/syslog.rb index 7ea7465..c2b2171 100644 --- a/lib/logstash/outputs/syslog.rb +++ b/lib/logstash/outputs/syslog.rb @@ -54,6 +54,8 @@ class LogStash::Outputs::Syslog < LogStash::Outputs::Base "debug", ] + CRL_END_TAG = "\n-----END X509 CRL-----\n" + # syslog server address to connect to config :host, :validate => :string, :required => true @@ -81,6 +83,12 @@ class LogStash::Outputs::Syslog < LogStash::Outputs::Base # SSL key passphrase config :ssl_key_passphrase, :validate => :password, :default => nil + # CRL file or bundle of CRLs + config :ssl_crl, :validate => :path + + # Check CRL for only leaf certificate (false) or require CRL check for the complete chain (true) + config :ssl_crl_check_all, :validate => :boolean, :default => false + # use label parsing for severity and facility levels # use priority field if set to false config :use_labels, :validate => :boolean, :default => true @@ -248,6 +256,14 @@ def setup_ssl else cert_store.add_file(@ssl_cacert) end + if @ssl_crl + # copy the behavior of X509_load_crl_file() which supports loading bundles of CRLs. + File.read(@ssl_crl).split(CRL_END_TAG).each do |crl| + crl << CRL_END_TAG + cert_store.add_crl(OpenSSL::X509::CRL.new(crl)) + end + cert_store.flags = @ssl_crl_check_all ? OpenSSL::X509::V_FLAG_CRL_CHECK|OpenSSL::X509::V_FLAG_CRL_CHECK_ALL : OpenSSL::X509::V_FLAG_CRL_CHECK + end ssl_context.cert_store = cert_store ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT end diff --git a/spec/fixtures/README.txt b/spec/fixtures/README.txt new file mode 100644 index 0000000..1e11841 --- /dev/null +++ b/spec/fixtures/README.txt @@ -0,0 +1 @@ +To regenerate the test certificates, you can use https://github.com/tsaarni/certyaml. diff --git a/spec/fixtures/ca-crl.pem b/spec/fixtures/ca-crl.pem new file mode 100644 index 0000000..0a36026 --- /dev/null +++ b/spec/fixtures/ca-crl.pem @@ -0,0 +1,11 @@ +-----BEGIN X509 CRL----- +MIIBmDCBgQIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDEwJjYRcNMjMwOTEz +MTEwOTA4WhcNMjMwOTIwMTEwOTA4WjAbMBkCCBeEcMRQn525Fw0yMzA5MTMxMTA5 +MDhaoCMwITAfBgNVHSMEGDAWgBRNukfgtxJMkwu7XMvQ8ETWqi5BVTANBgkqhkiG +9w0BAQsFAAOCAQEAEMhDOnI3Nh8ggAty32gkGwVd4ypGrVu8dI0CvD+PjnYRAHfK +Ngs4ByGOM5mKVTN63To6MulytSRR2WtW4JwcfHq1N9lQiL3qLePcU0CNYfcpRK48 +yRVV9qXV2jQAT2halBEhAqlyOH6+enFklCQNUdeCO38jWGPwFOyS4zR+PYWYuymq +WhtScDaHqk/8DZmY/nblabZ4BIDmActqtfpjR+nF8xhTwThgPpETJkQFh3N4PCy+ +UHp46T5hMlib1Dj1JN/TvSW9XsW40QSJGhqOaaEB0tZKRnGWzpABgcMylrtmuVW/ +du7jT9nrGVczZYoaxF9HVRNHs5d9jUgqfDVETg== +-----END X509 CRL----- diff --git a/spec/fixtures/ca-key.pem b/spec/fixtures/ca-key.pem new file mode 100644 index 0000000..4446058 --- /dev/null +++ b/spec/fixtures/ca-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC1bRafVn9FLMBV +sxq49Zv69XJIMPkm7jr6c67jXIw+V7H1xYrwsPhtpnu4naM185T6F4IStFuBu0Kt +gAw61t3xk0EIwEIN0ESG6g1DUVnk0lamvN/qjgg92sFrsb14L16rO8hEF5x2EGho +pq4+0irCggUjG2CiJ7PYQhMW8PQU3XSZT3K6H+Csegvt5wjDYLcxtxcptRdBHlvl +WAQACg1e2qQ36KL+3tRwVFkbv2zwvAu55DzHHoGlOwfyd4iyLnk9Bw1GIp8gJaqi +odSESvOAxkHLeVUqq8vzr3kRN+pNN6lWADxcOTyATiwzkPKje+5WJn44ROvombtm +9l++KT+VAgMBAAECggEBALJDD7lb+g10HT+XjigyXCLHzJSWWhkgdx7jT/HiW4Je +FGPSx+QbXt4OeP47FcTLI5RgSNQsFsVvw+JKMLoXqVfWQk5g6gY8nziY/JMqedNV +wQJwDuuexwZPzUEOEYbntHM3eF0/feKb2JsLO6ZKRu17Z6TJH7f0nsdclPkzpABi +uJUChSVmHvcI7lK2aKrrW7NLgO05VDKNp0Z+9f7m3qpsputdc01+S50D9+I6FXOv +zPBdjNz4LYvKLqdBkJZerBeViTvQ+YcoovxQzy6g5gaWfknVy/vvUG7DXN1yptJ0 +si4ZLT0WbSRX0NU7tAuaaQ2dCVgzYEheYQwDBqFq/4ECgYEA3pRFsyW4doAbY3R7 +598LZjoMGr8LzllOxJEjEPnQiC4sSn2kP2HJ9YQBHt/oZ9Sixx5RmLF05jbWVpEE +FKxNqPj3B1Ny11lMTUYc8nmu6040u1F30XrG3fRB7bPUSMq7+SfeM9CBMiDlMsJG +CqJUt6Mf4HiwBIY9cQn8HB5KBbECgYEA0KrusLgxzquF/I7eFEzVdf4u2GlRB8lw +QDFZNkx4AmHca+dVDUb/QWRGvaHN6Mn9vS1CC1GqO7Vpx6FD6BOm/+ZMHTEFpXmz +CkDTjXv3oivzfJmec/YCaSSx/xjaYPdz9xesfNhBzraAh1c+KeG4ilYZ/z9H1yAV ++03o+dxffSUCgYEAra1A3dM3JrA7rtU7wehW+sOcolokmjUxs0wU8rAbucddpBp5 +yUNC1aLVRQQuUqanBXxw6xa9Qs3TXeT2LDNuvcTW7Q5+c+8oDLwC5mlwxgdWOjwN +pJWLC7IGp7ZElTAskPQ8/G1cAoOMlJjnEnEsbcaJnxxNLJqa4tOJt18jH2ECgYA4 +cgSfSTQv87YK25q3YxFbGacSY2rH8HWs56x6Q7Uy78XwamNXdB0YU0fPhDVvAzTg +N53l8fFatXgnyDfWT3qdPm7YdqpQWNtVqrOPUjlqZPk4e1WhiKqeRo7fsplgIY/9 +Byphmx4yDKw38CGgsq54vVHK+hM03jkUAb9D15j9AQKBgF+mgmL8teGiKPM6u932 +O5zX/vwvcdxdT/BInliJA2I/gJZ0wYEIMcFlTSl8DI52nBZIssjPpNRp4W3fKWR3 +tnbBzFiFXU88l6QOd3NotINFh/br0LOaJ550zyepcx9z6mN1Z5vv0iYgsZE78nCg +Z6Tlk4gYoS3xG1q5V1f0JJee +-----END PRIVATE KEY----- diff --git a/spec/fixtures/ca.pem b/spec/fixtures/ca.pem new file mode 100644 index 0000000..dfb9f0e --- /dev/null +++ b/spec/fixtures/ca.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC4DCCAcigAwIBAgIIF4RwxEiEg+UwDQYJKoZIhvcNAQELBQAwDTELMAkGA1UE +AxMCY2EwIBcNNzAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMA0xCzAJBgNV +BAMTAmNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtW0Wn1Z/RSzA +VbMauPWb+vVySDD5Ju46+nOu41yMPlex9cWK8LD4baZ7uJ2jNfOU+heCErRbgbtC +rYAMOtbd8ZNBCMBCDdBEhuoNQ1FZ5NJWprzf6o4IPdrBa7G9eC9eqzvIRBecdhBo +aKauPtIqwoIFIxtgoiez2EITFvD0FN10mU9yuh/grHoL7ecIw2C3MbcXKbUXQR5b +5VgEAAoNXtqkN+ii/t7UcFRZG79s8LwLueQ8xx6BpTsH8neIsi55PQcNRiKfICWq +oqHUhErzgMZBy3lVKqvL8695ETfqTTepVgA8XDk8gE4sM5Dyo3vuViZ+OETr6Jm7 +ZvZfvik/lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUTbpH4LcSTJMLu1zL0PBE1qouQVUwDQYJKoZIhvcNAQELBQAD +ggEBADG3pp79VsvFqR3dAznHtMmprya6gLbh6/oFLGeSaYRZG/eIQQFdnGBxhBu/ +7YfYsZ385ATRvPB5diwpbPZ0u6PVLkXhE2RbYwV3EtPTvRHoTAB1/jdzAp5OoKlx +DEpN45KiGgkwknkBz0NEPKoOPc++dTnPn1SD3mqdIPSBD+nDrQibCKODAhN+TjfZ +Fith6yp+RIgst62RrFML56/EhKF4TgCXPKQBvXTXhwyBKeMlXglxhxghXXa+9Pw6 +X6PL238t3iGJm/ClZd+nyifPjR1DUNVJQXDC/ZDsI6qHe5TNZyYBBwC6ymDd/sCU +L/SfQIFGjFAc2GP3DCiZM5HgvFg= +-----END CERTIFICATE----- diff --git a/spec/fixtures/certs.yaml b/spec/fixtures/certs.yaml new file mode 100644 index 0000000..479c6b2 --- /dev/null +++ b/spec/fixtures/certs.yaml @@ -0,0 +1,34 @@ +subject: cn=ca +key_type: RSA +not_before: 1970-01-01T00:00:00Z +not_after: 2100-01-01T00:00:00Z +--- +subject: cn=valid-server +issuer: cn=ca +key_type: RSA +not_before: 1970-01-01T00:00:00Z +not_after: 2100-01-01T00:00:00Z +sans: +- DNS:localhost +--- +subject: cn=revoked-server +issuer: cn=ca +key_type: RSA +revoked: true +not_before: 1970-01-01T00:00:00Z +not_after: 2100-01-01T00:00:00Z +sans: +- DNS:localhost +--- +subject: cn=untrusted-server +key_type: RSA +ca: false +not_before: 1970-01-01T00:00:00Z +not_after: 2100-01-01T00:00:00Z +sans: +- DNS:localhost +--- +subject: cn=client +issuer: cn=ca +key_type: RSA +--- diff --git a/spec/fixtures/client-key.pem b/spec/fixtures/client-key.pem new file mode 100644 index 0000000..3cfcfd1 --- /dev/null +++ b/spec/fixtures/client-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCnPqjlJMF4uvsN +t1kdrVP/Zi3KS3dvCg2Dpg1BAyo0nhe8vKHAAK0TE9//peTOqt5P+hps7fw4SG3N +ZNmmkOk8u6B0I15FLHywTsMPU9H+gLrte8Y/yZC4AbdmVrYFml83Q41wGj8UM05t +pslVMfkveNkG/LBzKrPENo2Wb2+2/Um/BzNsaX0bhg7MGesD8TjhMFmh+kvChUMp +jFK4dKDOlXFMBLd43wtNVeWDz7duNx/oz6LyQ5JsAmVCHCMxlgc4GQEeUJ2lEnkI +Jw+lwDCKutwIQ4lm6pWAm4KU/BTcA7h6PWM0ku6XnfW7/xbT0FdeKnga8uTO8+vM +7/GqawGLAgMBAAECggEAdJl38QG2LTDXNVHdvJYKGOapB/+jTfQJRf5wASJuu255 +CCnO72jJQaK6qaaEJh30jnfFEqq9DJRakTc9kyY2phP9otrBr6J7cAQJdFcw8anY +KRgBOJmT3uW7cosDrlZZCdN7+WsjDTdT95ivh0km/JTZYkir0C82U5bhEb+xeDZv +f/76b1gDYz3ZrvQMnb4x+60vb9U7iVrnXNEVxle/FhpLNbA9tsFLoSsm/6SbEnju +cyimwmkMnQhPdiN5wmdTzXaTTsM3Ayomtj2bZZMTM9VSrFYAFPYAh2GwX7xn1hmo +gacYqZcXgqu+uIE812hbWEAFmaS3vrxNVAXwa7IjkQKBgQDeR9EdabphDryvgjgA +MUm5TxKKp5Wm9Cz+FiEUASFxoduuCdSb4vq2YGL5PL22MNxmMtYq2oc/dZOMtr45 +hruq0IZmVBNlViqjjcY1J3zvBRWSn93JdSY32o3g3rpgx6/6AZvUzfJmbwVcZBZR +VimCf6oknoNt3lADEJXaVtYBAwKBgQDAnYyGPrufS52dRinnuFVImKX/FvbFDYJI +F31cfi2y4y+g0tFFh0vjG0qVkxkBII5Cy5y1brLYColVWd8gWKibQMJ0TVZfV1ez +gAkR69XIdMLlHl5oXzwyaMYLnsx6MYgzPRHB2ojhtGiEym0dUUrzovl4zB9+LpRd +z6hpMoti2QKBgQDPWo9osMh84hKCZyd2hoQPqgPR9KNWK1INdPdGggeAyUz0/Zao +FQVsPF4XwuH2o332mFXRhCnGuRf7nD23zEglAIFf0+6ECe2cxRSxYTTahBOrxBZR +aEdOs0LHEv8qaR1wSy/jRHtrswV9OqDXH1l5sz41CunwBAL/2Ojx1S+toQKBgQCB +iPK6TXIMXOPwowEHjtX77nykIqNuPfmB1ho+m7TL+zFKrLyET8rfPrlYAgbs1SIX +Faub8Ihh9iQJvFjr/fPWBSVA5cnScIDQfKic3sd0+eEgCN5gvrtTA1c89Vx6SNlZ +7BYHEpq/f35S33emIceQNegkLtJ3H4gz1rVhmdZXcQKBgQCl1OvIJI7FmBzG1XPz +VNkE1nCPhXZEnrR3csZsiJiHCkI+t7izoIwFZZnEaW/+rqrZAWjMdFu11hy0Fz1n +y74CmHrlupOoSbNZlB7w7MfqZydqXT6XXgjHdlnR9+celzkS7HnZ/jxwJChCnznm +JR8q9KOY82PMpTHNnlEoUDqCJA== +-----END PRIVATE KEY----- diff --git a/spec/fixtures/client.pem b/spec/fixtures/client.pem new file mode 100644 index 0000000..afef11b --- /dev/null +++ b/spec/fixtures/client.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC0zCCAbugAwIBAgIIF4RwxFvwiMEwDQYJKoZIhvcNAQELBQAwDTELMAkGA1UE +AxMCY2EwHhcNMjMwOTEzMTEwOTA4WhcNMjQwOTEyMTEwOTA4WjARMQ8wDQYDVQQD +EwZjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnPqjlJMF4 +uvsNt1kdrVP/Zi3KS3dvCg2Dpg1BAyo0nhe8vKHAAK0TE9//peTOqt5P+hps7fw4 +SG3NZNmmkOk8u6B0I15FLHywTsMPU9H+gLrte8Y/yZC4AbdmVrYFml83Q41wGj8U +M05tpslVMfkveNkG/LBzKrPENo2Wb2+2/Um/BzNsaX0bhg7MGesD8TjhMFmh+kvC +hUMpjFK4dKDOlXFMBLd43wtNVeWDz7duNx/oz6LyQ5JsAmVCHCMxlgc4GQEeUJ2l +EnkIJw+lwDCKutwIQ4lm6pWAm4KU/BTcA7h6PWM0ku6XnfW7/xbT0FdeKnga8uTO +8+vM7/GqawGLAgMBAAGjMzAxMA4GA1UdDwEB/wQEAwIFoDAfBgNVHSMEGDAWgBRN +ukfgtxJMkwu7XMvQ8ETWqi5BVTANBgkqhkiG9w0BAQsFAAOCAQEAkyK273ywVTm8 +SFssX0igt/sGDD/PMy9D9X5ovg7083g6FFYqdP9bWrkIasXzVb5s0feeV/tAV+DO +sDjHcR7K5SwBjsNdYA+wie5WC1XaKAxSVNfe+VnwbZcgXaHcKPeqG7S3ZHJ3riRh +GTPMArnb/w9+RqWTTSsxEvzw1lPVVbqFDiAPHsg6FTKetNEr83xbOzk4EOAnD2Hq +CgKstcxl+lm8kaIhz1Jd5wVZ68i/+wDLRtk16inkoKIQYFvksdoMjNQLfhc5Cx+h +4+3gOylszUF92SSbipFmEBs5LJ88G3U35xHS/imI9OdsMNdj4HE9Tk7TiuYH3Kt7 +DUOgg4S+0w== +-----END CERTIFICATE----- diff --git a/spec/fixtures/invalid.pem b/spec/fixtures/invalid.pem new file mode 100644 index 0000000..7d1253c --- /dev/null +++ b/spec/fixtures/invalid.pem @@ -0,0 +1 @@ +not a pem file diff --git a/spec/fixtures/revoked-server-key.pem b/spec/fixtures/revoked-server-key.pem new file mode 100644 index 0000000..0a5c197 --- /dev/null +++ b/spec/fixtures/revoked-server-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDiN1fa3BcTbvHN +XN7ulMnYyFrGC+RiOlpa/PlI76NWjoaOmgy7sDzXP3e27ES6k6kRtBf/OriGXJdB +KQ0z14OCyzTkG7mUjhgRMRtopsWyTKC8TRcjiObIBue89NeiSKZk0YPCNWFZCs2D +IBSzrK3PoKyMt+cw5nh9MPDe0dypoeDJmiV494LFdOO7FkjLqFH9qcBq30HFdp7Z +i04OIFnmSEOWWdhIOhXUUKp/aIipsQCp++t1Yn7r2tvHXU7KfT6/q4cKqxA5sWSa +0KsT/IrcB/fj1DpdLG3apaxETZiaW+6AuCDfNeeKxG0sQLb6U1+1IsSp/p7vG9S2 +2upExnrjAgMBAAECggEAbcyzBfYB9VrKXwWO53qspl5JQQuQpOTx6mwTi4VVYLP5 +N8oqGAeo4ElcEBuKGI2HaKJja2zTF9RlTilg0SLwIFIFsBqM70AxClctmJQqLSro +cb1xV7whWEGRxbOJ3qkoqpLPQzqpr5CAw/6UTcmo67hvSDYTLzcOkKVqpJx0YJja +XvQ9m9zeOIOANN2cj3mZPCniDNGzYMF6D2twNEjEwE1OOm8wTkhfdWIimVGmn4US +mOA4vT78XV2lDvFrroCWKdNFaUZhw0pw3b/uVqagXk2PmDAi0gVg1PzbjwkniwXt +poTltUpAMyMveMYDK8dbK2wQIJ95F0qQa4KyLIkl4QKBgQD04Bcu6JyUWWAERrm4 +dOxXEGCQeCNp8QmBddSGa8HaWFlmTedCXvCNNOJZYeB+pYdbzVc0nJM3xxDq0o9X +hXg5iS+I1jEQAuLJCcnaqXdM9nB2EFsy/KRSK6xoxZsiYyUof5DGozbo6GB+bdyl +NgaPGUkIsOS5GWF+se9whj00WQKBgQDsfj7sMo//bJEPexMsMxTSbq9stAsk9MFe +WBCYmvD1p7OcwgnICYFOkWo6jcOHYA4ByDIJUyufDgu0Ta4wLyTBZh2dXqHs80jW +DmeYl4xQzTlEtpVZUX8vMDk9N+9tWHi+Z19MgNpt/QeKBJqaBHgGGqx2CEQzAcjC +jRAxLPDxmwKBgQDkhGc+IFdW3Z0MAJB6gaq4iREEYQjzabvsM3C0TMUoJQCwxwyE +VKL5s5tzvDJLHeAWnKa/80ozaDLyYLLiAy0xzEMu2GwKvBa1c8wKodEyYlyK4TKq +fzg9coI/eAEQ8yMPCxSpOlEYwxqhgZbCGou+aONOF/4qenQQTq7a/HsLaQKBgQDn +qF7wtjLSDMIn/PJx+HOsElpqzA6im9KTHQbcxeHFcQoDQxubxJvSn6UESHvBLzlp +S3agJcV0H6kdbH51mqiRffsCfYF2f3XYoPGfysvbFrzDb2rqvGcujTl0m0dAwEo+ +kToL0ail1xc8fngG6Nu9dwF6+Wv83wGOeenjkddPgwKBgD/tIsEPxkiNfi/y1mLT +cM8i6zZNjoH52lkhJ+zWGwPPLTE2HP5FzY/FEG7qwVAqMTC1Tnw9IXiP0bXPTcxk +NEaP2GG9g57OtLR4NK+Pw+fiYemoxDf3l9dgoa5T/HBv7Epzaadv0np2TterpE0H +ul9dMftda0KPvPdGf5xdWCkJ +-----END PRIVATE KEY----- diff --git a/spec/fixtures/revoked-server.pem b/spec/fixtures/revoked-server.pem new file mode 100644 index 0000000..d86e6ce --- /dev/null +++ b/spec/fixtures/revoked-server.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC8zCCAdugAwIBAgIIF4RwxFCfnbkwDQYJKoZIhvcNAQELBQAwDTELMAkGA1UE +AxMCY2EwIBcNNzAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMBkxFzAVBgNV +BAMTDnJldm9rZWQtc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA4jdX2twXE27xzVze7pTJ2MhaxgvkYjpaWvz5SO+jVo6GjpoMu7A81z93tuxE +upOpEbQX/zq4hlyXQSkNM9eDgss05Bu5lI4YETEbaKbFskygvE0XI4jmyAbnvPTX +okimZNGDwjVhWQrNgyAUs6ytz6CsjLfnMOZ4fTDw3tHcqaHgyZolePeCxXTjuxZI +y6hR/anAat9BxXae2YtODiBZ5khDllnYSDoV1FCqf2iIqbEAqfvrdWJ+69rbx11O +yn0+v6uHCqsQObFkmtCrE/yK3Af349Q6XSxt2qWsRE2YmlvugLgg3zXnisRtLEC2 ++lNftSLEqf6e7xvUttrqRMZ64wIDAQABo0kwRzAOBgNVHQ8BAf8EBAMCBaAwHwYD +VR0jBBgwFoAUTbpH4LcSTJMLu1zL0PBE1qouQVUwFAYDVR0RBA0wC4IJbG9jYWxo +b3N0MA0GCSqGSIb3DQEBCwUAA4IBAQBJlXamVwRDqGqbsLCyKef1AXtnsr5h/bih +lHyO5YChSTiAKb/5rbZx7n1ydIlbFZ1aOCQrqXomQKKSBpW5alHHYSbWeiEit64t +wDxcqMnz+O+mOvt6NF8ceawUTLRBZLSBV7GJyTBKBAqmLv4UyYti8dEwUScsnxE3 +4nLD9DMCscsoWnG8EADnsiOwXDtZvv7Dt9B/Z8mKUXRH5egeEVNHi7ZSDlCQtadJ +QO4+Ov/gejknFn8nw4falb94vDYKaZLMHfdtVJ8by+bZ3PNJjSQrvOBC6DC8OStd +Xh0fNSnDhbKyeSIaMECfYFnCMoph6j9hlU6v1ekml1YNKj0SvAWa +-----END CERTIFICATE----- diff --git a/spec/fixtures/untrusted-server-key.pem b/spec/fixtures/untrusted-server-key.pem new file mode 100644 index 0000000..f88b43b --- /dev/null +++ b/spec/fixtures/untrusted-server-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDIIBZrCyM8Hesb +ZklBQ4HLfAwtJi2cCR3ZXvRYvVlm+hUtXqlwErS3trx7m7eESB/MyHvWhydnwVEB +Ioz+cryZoTag1vXW0vtPTD+eUnqyKO24uuXi5upJNgr/+VwEd5OIAblpmZcFyLgL +5VyES+/kDmDjQD9M1Yman+orIsNgAVLd/bDXMpPzGeH151fQVi+4MNe1dr4DSlx5 +whRU/8e4nkfrgAYJWxGl/vzgLnYmqZVVUPBobEBvA/Zd0tdI2OWAkzcFm+RranCm +fjxxxZ765MzIrTiPi6PfTMdZenVCbe5HeQYPjxDI0rEdMYS5QgTmrOnG9KXGvCqu +ud/SxBwzAgMBAAECggEBAIULF/xH5j/EIBYSFSdHKtXNfQbS98VhJi/peYY5M2NL +ZKLJ6NjyBqSP3pRKfGF71XA95F5FccP/d8vKXXOXcZys2XVqEvujPaGFLlIhwSIK +JagG0GfdXeoX/I4aB7uMh08G3m2+xvD4dKqr66qkFTJHANBzWOHKoHVkVLgin0KF +0WoQ+t1xc519Xewi/ghatNifIYKML1prkwIekWUBM7CxONfaAxYg828edgEDDgoy +Iq7lGyCj5AZfYeW7G7rSxsnMylf5XoA2c68AC0JT6uRLKYQAKzPjntKALktRwROt +2j1hOq6pw7vSKYCHHXjcB1wrIfGCGegEZISV1890kGECgYEA1xRhB6ezLd7/5yw0 +8w4nYz0YW8/QXcatRDtvvP/kX+RBZLutIivVwCKdDYknuISbcx4uTfgJCfnh9Gju +6u/EIJWe97k+YLUFeH23lGhnsWTfmJ3XAhs76Jxn/akHypRZ5c4z6tlpydxvHU4X +c52c6v+yGWuXAP1Wt/fzo9ZAiDECgYEA7jNZct+k/0tqcIdgvkv+bzObDcghyl3d +aHL1gGCCI4ZT43fp/+7RmAuPK+d+JCzHxDuXIHOZ+gAjfhw6dVjZWCMKXNlI587g +/rtIgjfZTLUDt+T/5l4hr147xgISyLtaGgvy+BBAF3GpvlhkA1LbNaV2XkUSrzop +Y5iHocOfdaMCgYEAo2NN2rzg90Xi7UC98K6d6VuuN4EFb1fQpHbqiY9zdA04SEfy +XHUkalNhL7kzvY6vcKJK1txIMZXsuvlEFqGSQpanLtVAt8KMp14Jqeoua6qP2aZ+ +gZEiz7CRpzdTPee460TcV9pV7Q1SM9bxJdlkLXmVWI5NJmlOCW+JXLsURuECgYAl +vd0eZnEuQjTLP6gEfuYBmJuow10XQ2ghdJWRkbkNB+uizw00kBKFlM9KlZNXCAFf +BlIbwjVTd1IoWTCqBznozSSHMaZrlEvyEJqch1zW2peMO6yQQ7nyn2u5I/r18zmD +hwEobOq6zDepAThXjnlNNrpalXcwbHbCYRicePJ7IQKBgQCt47xW8YWcCyKPksL5 +WHTV40eWOa8ZJotGf0LN1YKUd5f8aIzAY26CV3677T5cmDO80qZ8rFrZ01TDZ4Qj +HN5lJqVp4vddpkIJ6EXEQ0AbiSbrip6qHm/LNuxFcdcoB8FAmqvMQe8xf90+tLOy +BTH3fMe4qQzbSa3KCdNzQRM9eg== +-----END PRIVATE KEY----- diff --git a/spec/fixtures/untrusted-server.pem b/spec/fixtures/untrusted-server.pem new file mode 100644 index 0000000..c0287bc --- /dev/null +++ b/spec/fixtures/untrusted-server.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC4jCCAcqgAwIBAgIIF4RwxFmE1F4wDQYJKoZIhvcNAQELBQAwGzEZMBcGA1UE +AxMQdW50cnVzdGVkLXNlcnZlcjAgFw03MDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAw +MDAwMFowGzEZMBcGA1UEAxMQdW50cnVzdGVkLXNlcnZlcjCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAMggFmsLIzwd6xtmSUFDgct8DC0mLZwJHdle9Fi9 +WWb6FS1eqXAStLe2vHubt4RIH8zIe9aHJ2fBUQEijP5yvJmhNqDW9dbS+09MP55S +erIo7bi65eLm6kk2Cv/5XAR3k4gBuWmZlwXIuAvlXIRL7+QOYONAP0zViZqf6isi +w2ABUt39sNcyk/MZ4fXnV9BWL7gw17V2vgNKXHnCFFT/x7ieR+uABglbEaX+/OAu +diaplVVQ8GhsQG8D9l3S10jY5YCTNwWb5GtqcKZ+PHHFnvrkzMitOI+Lo99Mx1l6 +dUJt7kd5Bg+PEMjSsR0xhLlCBOas6cb0pca8Kq6539LEHDMCAwEAAaMoMCYwDgYD +VR0PAQH/BAQDAgWgMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsF +AAOCAQEAY3kMdTa4PAFVv218EFw2SoMswIn0IjnSbaP18PGPQJyeAtjInE3Y6Aza +zkZK2lOcgHF8GTJNldP+7SIMlY3ulJLTBvqgEHshGH3lvZEWCkJzheCUMnvbsz8b +ByhsHnKtLMTGQab8TxVpx4QGA2KI/7yhnVRwBCfyqJxaj98d9O62AjOJJmcOdc7t +K9CAXpjXqmU5YZJ+hb3s2KPY8v5QqAYcNCI/OtIQcHQh+8vnu1McILMljUmJHwVX +ZTmEJizVtZr+UEg2XDw9GgC+OXppFRb1ll0E5Kp+ird7hRDl3VKdh5rEYR5vMTUH +5tX5tdoGCR5cN8jxlwTgqSfz6XrYfg== +-----END CERTIFICATE----- diff --git a/spec/fixtures/valid-server-key.pem b/spec/fixtures/valid-server-key.pem new file mode 100644 index 0000000..c8e800a --- /dev/null +++ b/spec/fixtures/valid-server-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDufSZFuYLo/KCO +UnW56iKNFf9aZ1n6beRm/s6J5A8Yh48MqX+/IwQ5aKiyLjJP4grE1EMZlW4Tq+PD +0aVcxn4tFwpx1MnQrFSMwTEqOuWl/ZWtdoL6/5jRlrSS4TPEEdfWUhNUJ7XeCeXd +RJYXGQUFWT9xI0hHMVS9zB8IXaW00qVtIXhL3S58alscNbjSqTGMqWUCZEBNX6iK ++waZvx7mjbuKbnBQ7tN/ZvxOS1JXVNhtrvacFanvljnfKxw+Ipw5lN6B76AACOrB +M0Au33UW57kpwekIQfFGDpUgkXQpTS30o38YCjDsKcMB+oSghCer+ELh5eH8CjTN +nXS9zBY3AgMBAAECggEBAK2FmYc5xypGRXvIO6gd1y3YR4c7k5hGxNy7oQNrUCCE +4WxRF4W2sKgkojmiqzC8QyGbX4cJ1qGxe3NK4opyUfP0w8C3FnAiMxKGroMPf3Aa +5gDkLcD6n/I/OPt1p/iNEwH5jd65VfZMNVedQ6diqOiPWz2ycjB6kDHYhuvLV3oM +Mnj/l5B7Qr6lZoM6a47ECX4d2FSIbxBaS1sAGCN2eckwL/oEMaufyGd7H9Juj4pa +lEdALrA+AOtn6f6grXQvMwej1mFx4ac7Teidvs+cPJGJBMONMiSFjHiUFQHW3ZSq +qBhXbCHmfoqdDw5BqgvwxEc4H75BQrFyr63vush1deECgYEA8pePyYjcB4o4j2Ib +DZFXD5kDuWvA6J1mM2XReww+y/y7nW4jf6XJhcY+dA7JazYDDrwNRziDdbmjuTQ4 +XrDDqJgeklENrEubWsDtPTiH7Tp8/caQH1p0SwIEwXcrr8MAeWdv/Ixcb6+p+QCt +Wp2eAjwHYLPzEjea+8a6q2M6M8MCgYEA+6uIMBUAUZsoID+AA77+NUR1xL54M7aJ +1WjKAj7uyHe8jP58I+39GlEYLBd8vQNqUb9v9fPbIDXQXyzQGe6KWzWfSDCUoFsA +jP66qk6xqLqxb5Qlc8VXXIgcONyYCudRgvNLaKPYW7gslkwziwwCulfNHLpuPj16 +4KI3MyMe8H0CgYBqzHaszuevGhbUaOhoDLg7Ua3mD54ZylGYBxc2CKoMu/MM19Qg ++ifCEQilp2zdGiY2cmuWEzcsuNFvU6INbdx1eKLc33oZhB+c0Jqg/SY6NimYv7Xr +V7Mi4nydf41oD31B9VvD3zdCpB88VCP9ZK6PZUYKOK6mMny0o0TC9yhEaQKBgQCc +IbShr8W82vcv2nU+3bSzsz8kyc2kt3AXV6VLc2OMNsxg5Fh7qd/F/d1zLTcTxBSn +lo6NFbYx63DUOub3z4dCQqgIjysFuK9EyZtgoOWS+g+uW0hI5HroSwDHPgONcCif +hvSXfF5zuHTg4XFwqAjhNitn0Tknn9ill72LGhTNuQKBgQClALtYE5se9mU/ehfK +igu/jqEYiUfHSm8AroCK5IVnqM1tHliN9r7fLnRAfQv2gF/Mbq7/wFIRyko4WIBp +0CKz7dv4v1zmdxk/k1jaZFLVQXpgDgPEuVxTmOiZCncef/P8gYO+x5PPDoVPsPlf +zQIF+YRER5vsPJUBOG1QP97zZg== +-----END PRIVATE KEY----- diff --git a/spec/fixtures/valid-server.pem b/spec/fixtures/valid-server.pem new file mode 100644 index 0000000..b9cfe1a --- /dev/null +++ b/spec/fixtures/valid-server.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC8TCCAdmgAwIBAgIIF4RwxEzf0ogwDQYJKoZIhvcNAQELBQAwDTELMAkGA1UE +AxMCY2EwIBcNNzAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMBcxFTATBgNV +BAMTDHZhbGlkLXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AO59JkW5guj8oI5SdbnqIo0V/1pnWfpt5Gb+zonkDxiHjwypf78jBDloqLIuMk/i +CsTUQxmVbhOr48PRpVzGfi0XCnHUydCsVIzBMSo65aX9la12gvr/mNGWtJLhM8QR +19ZSE1Qntd4J5d1ElhcZBQVZP3EjSEcxVL3MHwhdpbTSpW0heEvdLnxqWxw1uNKp +MYypZQJkQE1fqIr7Bpm/HuaNu4pucFDu039m/E5LUldU2G2u9pwVqe+WOd8rHD4i +nDmU3oHvoAAI6sEzQC7fdRbnuSnB6QhB8UYOlSCRdClNLfSjfxgKMOwpwwH6hKCE +J6v4QuHl4fwKNM2ddL3MFjcCAwEAAaNJMEcwDgYDVR0PAQH/BAQDAgWgMB8GA1Ud +IwQYMBaAFE26R+C3EkyTC7tcy9DwRNaqLkFVMBQGA1UdEQQNMAuCCWxvY2FsaG9z +dDANBgkqhkiG9w0BAQsFAAOCAQEAVBgDXf3vh0U+5CK36cBArUCbT/ByQQ/4jByy +m1VRM4Mbxumpw7LPtSDUqSpyCO4LaHq+Jp76VbtyPPTZnwWnowJwXDLXykHyJ4Mp +wKVBUoHMxXcnQwE8VfWGiRi101WSx6ts2lXJjqUcjz9rsq+syE0/ZMnoM5BXIL5q +YPKQ+Apscu6VRP8Ecnz0+ivy365FVhENOrGsACau5aPAaR1jmoWtUCyjA4UmskFd +c1Ovj8AbB1HR18XGcs+EnVdAjum5kdKfOiGHmy/qqfkflHiFYu02qZ0bNgB0pU3b +EYR054dXU0Hic/5ZoasBYzFaHebqyT1rosYWENFSKxNjafn71g== +-----END CERTIFICATE----- diff --git a/spec/outputs/syslog_tls_spec.rb b/spec/outputs/syslog_tls_spec.rb new file mode 100644 index 0000000..fefd490 --- /dev/null +++ b/spec/outputs/syslog_tls_spec.rb @@ -0,0 +1,152 @@ +# encoding: utf-8 + +require "logstash/devutils/rspec/spec_helper" +require "logstash/outputs/syslog" +require "logstash/codecs/plain" +require "json" + +describe LogStash::Outputs::Syslog do + FIXTURES_PATH = File.expand_path("../fixtures", File.dirname(__FILE__)) + + subject do + plugin = LogStash::Plugin.lookup("output", "syslog").new(options) + plugin.register + plugin + end + + let(:port) do + begin + # Start high to better avoid common services + port = rand(10000..65535) + s = TCPServer.new("127.0.0.1", port) + s.close + + port + rescue Errno::EADDRINUSE + retry + end + end + + let(:server) { TCPServer.new("127.0.0.1", port) } + + shared_examples "syslog output" do + it "should write expected format" do + Thread.start { sleep 0.25; subject.receive event } + socket = secure_server.accept + read = socket.sysread(100) + expect(read.size).to be > 0 + expect(read).to match(output) + end + end + + context "connects with TLS" do + let(:event) { LogStash::Event.new({ "message" => "foo bar", "host" => "baz" }) } + let(:options) { { "host" => "localhost", "port" => port, "protocol" => "ssl-tcp", + "ssl_cacert" => File.join(FIXTURES_PATH, "ca.pem"), + "ssl_cert" => File.join(FIXTURES_PATH, "client.pem"), + "ssl_key" => File.join(FIXTURES_PATH, "client-key.pem") } } + # The output details are tested in syslog_spec.rb so simply check for message to be present. + let(:output) { /foo bar/ } + + let(:secure_server) do + # Create TLS server with given certificate and private key, and verify client certificate against CA. + ssl_context = OpenSSL::SSL::SSLContext.new + ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(server_cert_file)) + ssl_context.key = OpenSSL::PKey::read(File.read(server_pkey_file), nil) + ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER + ssl_context.cert_store = OpenSSL::X509::Store.new + ssl_context.cert_store.add_cert(OpenSSL::X509::Certificate.new(File.read(File.join(FIXTURES_PATH, "ca.pem")))) + OpenSSL::SSL::SSLServer.new(server, ssl_context) + end + + after(:each) do + secure_server.close rescue nil + end + + context "server with valid certificates" do + let(:options ) { super().merge("ssl_verify" => true) } + let(:server_cert_file) { File.join(FIXTURES_PATH, "valid-server.pem") } + let(:server_pkey_file) { File.join(FIXTURES_PATH, "valid-server-key.pem") } + + it_behaves_like "syslog output" + end + + context "server with untrusted certificates" do + let(:server_cert_file) { File.join(FIXTURES_PATH, "untrusted-server.pem") } + let(:server_pkey_file) { File.join(FIXTURES_PATH, "untrusted-server-key.pem") } + + context "ssl_verify disabled" do + let(:options ) { super().merge("ssl_verify" => false) } + + it_behaves_like "syslog output" + end + + context "ssl_verify enabled" do + let(:options ) { super().merge("ssl_verify" => true) } + + it "should refuse to connect" do + Thread.start { secure_server.accept rescue nil } + expect(subject.logger).to receive(:error).with(/SSL Error/i, hash_including(exception: OpenSSL::SSL::SSLError)).once.and_throw :TEST_DONE + expect { subject.receive event }.to throw_symbol(:TEST_DONE) + end + end + + end + + context "server with revoked certificates" do + let(:options ) { super().merge("ssl_verify" => true, "ssl_crl" => File.join(FIXTURES_PATH, "ca-crl.pem")) } + let(:server_cert_file) { File.join(FIXTURES_PATH, "revoked-server.pem") } + let(:server_pkey_file) { File.join(FIXTURES_PATH, "revoked-server-key.pem") } + + it "syslog output refuses to connect" do + Thread.start { secure_server.accept rescue nil } + expect(subject.logger).to receive(:error).with(/SSL Error/i, hash_including(exception: OpenSSL::SSL::SSLError)).once.and_throw :TEST_DONE + expect { subject.receive event }.to throw_symbol(:TEST_DONE) + end + end + end + + context "read PEM" do + let(:options) { { "host" => "localhost", "port" => port, "protocol" => "ssl-tcp", "ssl_verify" => true } } + + context "invalid client certificate" do + let(:options ) { super().merge( + "ssl_cert" => File.join(FIXTURES_PATH, "invalid.pem"), + "ssl_key" => File.join(FIXTURES_PATH, "client-key.pem"), + "ssl_cacert" => File.join(FIXTURES_PATH, "ca.pem"), + "ssl_crl" => File.join(FIXTURES_PATH, "ca-crl.pem") + ) } + + it "register raises error" do + expect { subject.register }.to raise_error(OpenSSL::X509::CertificateError, /malformed PEM data/) + end + end + + context "invalid client private key" do + let(:options ) { super().merge( + "ssl_cert" => File.join(FIXTURES_PATH, "client.pem"), + "ssl_key" => File.join(FIXTURES_PATH, "invalid.pem"), + "ssl_cacert" => File.join(FIXTURES_PATH, "ca.pem"), + "ssl_crl" => File.join(FIXTURES_PATH, "ca-crl.pem") + ) } + + it "register raises error" do + expect { subject.register }.to raise_error(OpenSSL::PKey::RSAError, /Neither PUB key nor PRIV key/) + end + end + + context "invalid CRL" do + let(:options ) { super().merge( + "ssl_cert" => File.join(FIXTURES_PATH, "client.pem"), + "ssl_key" => File.join(FIXTURES_PATH, "client-key.pem"), + "ssl_cacert" => File.join(FIXTURES_PATH, "ca.pem"), + "ssl_crl" => File.join(FIXTURES_PATH, "invalid.pem") + ) } + + it "register raises error" do + expect { subject.register }.to raise_error(OpenSSL::X509::CRLError, /malformed PEM data/) + end + end + + end +end