diff --git a/CHANGELOG.md b/CHANGELOG.md index c4c1d4b..55f1eb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 3.5.0 + - Feat: TLSv1.3 support [#146](https://github.com/logstash-plugins/logstash-input-http/pull/146) + ## 3.4.5 - Build: do not package log4j-api dependency [#149](https://github.com/logstash-plugins/logstash-input-http/pull/149). Logstash provides the log4j framework and the dependency is not needed except testing and compiling. diff --git a/VERSION b/VERSION index 4f5e697..1545d96 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.4.5 +3.5.0 diff --git a/docs/index.asciidoc b/docs/index.asciidoc index c70cbce..8b57367 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -134,9 +134,11 @@ and no codec for the request's content-type is found ===== `cipher_suites` * Value type is <> - * Default value is `java.lang.String[TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256]@459cfcca` + * Default value is `[TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256]` The list of ciphers suite to use, listed by priorities. +The default values applies for OpenJDK 11.0.14 and higher, for older versions the list does not include suites +not supported by the JDK, such as the ChaCha20 family of ciphers. [id="plugins-{type}s-{plugin}-ecs_compatibility"] ===== `ecs_compatibility` @@ -357,7 +359,7 @@ Time in milliseconds for an incomplete ssl handshake to timeout * There is no default value for this setting. SSL key to use. -NOTE: This key need to be in the PKCS8 format, you can convert it with https://www.openssl.org/docs/man1.1.0/apps/pkcs8.html[OpenSSL] +NOTE: This key need to be in the PKCS8 format, you can convert it with https://www.openssl.org/docs/man1.1.1/man1/openssl-pkcs8.html[OpenSSL] for more information. [id="plugins-{type}s-{plugin}-ssl_key_passphrase"] @@ -396,19 +398,19 @@ Number of threads to use for both accepting connections and handling requests ===== `tls_max_version` * Value type is <> - * Default value is `1.2` + * Default value is `1.3` -The maximum TLS version allowed for the encrypted connections. The value must be the one of the following: -1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2 +The maximum TLS version allowed for the encrypted connections. +The value must be the one of the following: 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLSv1.3 [id="plugins-{type}s-{plugin}-tls_min_version"] ===== `tls_min_version` * Value type is <> - * Default value is `1` + * Default value is `1.2` -The minimum TLS version allowed for the encrypted connections. The value must be one of the following: -1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2 +The minimum TLS version allowed for the encrypted connections. +The value must be one of the following: 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLSv1.3 [id="plugins-{type}s-{plugin}-user"] ===== `user` diff --git a/lib/logstash/inputs/http.rb b/lib/logstash/inputs/http.rb index 7ed5a8f..e2fe1de 100644 --- a/lib/logstash/inputs/http.rb +++ b/lib/logstash/inputs/http.rb @@ -87,11 +87,11 @@ class LogStash::Inputs::Http < LogStash::Inputs::Base config :ssl_handshake_timeout, :validate => :number, :default => 10000 # The minimum TLS version allowed for the encrypted connections. The value must be one of the following: - # 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2 + # 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLS 1.3 config :tls_min_version, :validate => :number, :default => TLS.min.version # The maximum TLS version allowed for the encrypted connections. The value must be the one of the following: - # 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2 + # 1.0 for TLS 1.0, 1.1 for TLS 1.1, 1.2 for TLS 1.2, 1.3 for TLS 1.3 config :tls_max_version, :validate => :number, :default => TLS.max.version # The list of ciphers suite to use, listed by priorities. diff --git a/lib/logstash/inputs/http/tls.rb b/lib/logstash/inputs/http/tls.rb index 46c3bc4..1119435 100644 --- a/lib/logstash/inputs/http/tls.rb +++ b/lib/logstash/inputs/http/tls.rb @@ -18,7 +18,8 @@ def <=>(other) TLS_PROTOCOL_OPTIONS = [ TLSOption.new("TLSv1", 1), TLSOption.new("TLSv1.1", 1.1), - TLSOption.new("TLSv1.2", 1.2) + TLSOption.new("TLSv1.2", 1.2), + TLSOption.new("TLSv1.3", 1.3) ] def self.min diff --git a/logstash-input-http.gemspec b/logstash-input-http.gemspec index 01b82b6..3636bd8 100644 --- a/logstash-input-http.gemspec +++ b/logstash-input-http.gemspec @@ -2,7 +2,7 @@ HTTP_INPUT_VERSION = File.read(File.expand_path(File.join(File.dirname(__FILE__) Gem::Specification.new do |s| s.name = 'logstash-input-http' - s.version = HTTP_INPUT_VERSION + s.version = HTTP_INPUT_VERSION s.licenses = ['Apache License (2.0)'] s.summary = "Receives events over HTTP or HTTPS" s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program" diff --git a/spec/fixtures/certs/generate.sh b/spec/fixtures/certs/generate.sh new file mode 100755 index 0000000..c1c7149 --- /dev/null +++ b/spec/fixtures/certs/generate.sh @@ -0,0 +1,40 @@ +# warning: do not use the certificates produced by this tool in production. +# This is for testing purposes only +set -e + +rm -rf generated +mkdir generated +cd generated + +echo "GENERATED CERTIFICATES FOR TESTING ONLY." >> ./README.txt +echo "DO NOT USE THESE CERTIFICATES IN PRODUCTION" >> ./README.txt + +# certificate authority +openssl genrsa -out root.key 4096 +openssl req -new -x509 -days 1826 -extensions ca -key root.key -out root.crt -subj "/C=LS/ST=NA/L=Http Input/O=Logstash/CN=root" -config ../openssl.cnf + +# server certificate from root +openssl genrsa -out server_from_root.key 4096 +openssl req -new -key server_from_root.key -out server_from_root.csr -subj "/C=LS/ST=NA/L=Http Input/O=Logstash/CN=server" -config ../openssl.cnf +openssl x509 -req -extensions server_cert -extfile ../openssl.cnf -days 1096 -in server_from_root.csr -CA root.crt -CAkey root.key -set_serial 03 -out server_from_root.crt + +# client certificate from root +openssl genrsa -out client_from_root.key 4096 +openssl req -new -key client_from_root.key -out client_from_root.csr -subj "/C=LS/ST=NA/L=Http Input/O=Logstash/CN=client" -config ../openssl.cnf +openssl x509 -req -extensions client_cert -extfile ../openssl.cnf -days 1096 -in client_from_root.csr -CA root.crt -CAkey root.key -set_serial 04 -out client_from_root.crt + +# verify :allthethings +openssl verify -CAfile root.crt server_from_root.crt + +# create pkcs8 versions of all keys +openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in client_from_root.key -out client_from_root.key.pkcs8 +openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in server_from_root.key -out server_from_root.key.pkcs8 + +# create pkcs12 keystores (pass:12345678) +openssl pkcs12 -export -in client_from_root.crt -inkey client_from_root.key -out client_from_root.p12 -name "client_from_root" -passout 'pass:12345678' + +# use java keytool to convert all pkcs12 keystores to jks-format keystores (pass:12345678) +keytool -importkeystore -srckeystore client_from_root.p12 -srcstoretype pkcs12 -srcstorepass 12345678 -destkeystore client_from_root.jks -deststorepass 12345678 -alias client_from_root + +# cleanup csr, we don't need them +rm -rf *.csr diff --git a/spec/fixtures/certs/generated/README.txt b/spec/fixtures/certs/generated/README.txt new file mode 100644 index 0000000..e4fa8b7 --- /dev/null +++ b/spec/fixtures/certs/generated/README.txt @@ -0,0 +1,2 @@ +GENERATED CERTIFICATES FOR TESTING ONLY. +DO NOT USE THESE CERTIFICATES IN PRODUCTION diff --git a/spec/fixtures/certs/generated/client_from_root.crt b/spec/fixtures/certs/generated/client_from_root.crt new file mode 100644 index 0000000..b7f43dc --- /dev/null +++ b/spec/fixtures/certs/generated/client_from_root.crt @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIGATCCA+mgAwIBAgIBBDANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJMUzEL +MAkGA1UECAwCTkExEzARBgNVBAcMCkh0dHAgSW5wdXQxETAPBgNVBAoMCExvZ3N0 +YXNoMQ0wCwYDVQQDDARyb290MB4XDTIxMTEyNDEwMjEzMloXDTI0MTEyNDEwMjEz +MlowUzELMAkGA1UEBhMCTFMxCzAJBgNVBAgMAk5BMRMwEQYDVQQHDApIdHRwIElu +cHV0MREwDwYDVQQKDAhMb2dzdGFzaDEPMA0GA1UEAwwGY2xpZW50MIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzz7tc52SXN84bP8/009HnfkDMGhqvNgi +oO+kza7PT1O7jcA3i0hh1r2N4xUIllc3cSvcfFK/sw8mAFPGE6lMIPAWHnsFipd1 +6rrk7jIVEgBE7ZUYuqWRRQ7ULV1a3LTxCn7XUrtk1bbrLgPRcoUev81L19AQZQ6R +DGv9MyFE2X71lvchj09eLh4RcR7/5Myj6ODtz5mYOIn8hqAaYCa6Zu0A54WbQd4p +xc/iuEQqpUJNcXdVJyNAzhDQq/oMImWgWs/nuMIrCV0WXttGsOnztxsftytsNtnP +SOBuULhRdDrkV16u7zMftANBWdoWIcdbc6ipr17ZrqySmioSWHk5YcsRwP6Em9Hq +SHgNXSDkb3+TPQX/XG2cmaPI+a8yTvgV1igMbzDYEznfqOhNG/28jTGo36iMt+R1 +ZrDWoIxRqSKq7WAiGmnKZKiy4xV4Ze3zekx7xse/S/OxmWvOCYN0+aLFgxNuizX5 +PpY6PhwJ/+I5JpbH2pXwuPsFMAyt5vwmcrS6k7O3vvUml7mwHQVQTqrNEvPHDwxe +H6n2LiW7Bbana12rkdMU5mXwBMMTVz1sjOZnzM1M+JEoce3UXfGuflhG7amOhPJf +Aj7vMR6kilzATFjmx1hdqqHzNARkeuxLhUzpdgKnk3nEmYPKx1MB7Y4FvpSEoTPV +K3rPkMHQm6UCAwEAAaOB4TCB3jAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIF +oDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgQ2xpZW50IENlcnRp +ZmljYXRlMB0GA1UdDgQWBBTXHNdFAtzeVD56PI6/Mu/wVzDCyzAfBgNVHSMEGDAW +gBSn18dv3u0R/O/LDPC7h+wHlcpFqDAOBgNVHQ8BAf8EBAMCBeAwHQYDVR0lBBYw +FAYIKwYBBQUHAwIGCCsGAQUFBwMEMBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAA +ATANBgkqhkiG9w0BAQsFAAOCAgEAE23qZ7HfFubCXYCzGxTq+zzMAId5rUn8Cnav +9eEGdofjkRRHJnW1yM8AmblbwxM8fs6SrQtujhGNFWEsGuXDoFFG6ID06eFsC1yC +RpKme0PRsKruBn8Na5Z2jeZ0SWKvW+1ZlvosMhQQh6QaNf7VTNVizJD+J34QxFeH +N66/Fh8/sh0ZooFy791japEtec8HJIBHNPrJprqYnzosKTRnYSLJpiCP9ksordMS +rTHWGDRnUXu1ggWanopt5wZfICG92gi8rROEk4fwFUy93E+WEzv8XCXpRxZqhdJf +V+jPoUHo4ZOnM8uFna5Y/o+DiVOdPXgn9xspe5qhEvU8upsvKRVNlfAXVGWjiG13 +ZdR3PvGITplFhNkBAuPIf1Z/xTF0e8JzQSSC2CtThGuCJz9uSB6zpnxjODKxAqFX +IbbH8Tnf8q6nEJm0RbMOyAc/HvX2eei1TV1XD9StL/M/2n0bCn/+s4peT4/qOy2T +zqQYTe45RknishUiMiv00//W5LNImjb0THHxQ1kQxi7Tlk0dZ5CPUjMfBVCt+Gdo +EQMjeGjvjfRvKtGzhtMDmkA3Oc8iOiaaR7mSU+ZjslDlRYnPKicbls673ttL3rx8 +R//PwWeZcBWkbowOYNJnjaiySpoO3WVEGMA8mUw4SEtlga6760cN4+e4pKnzo1sR +P1W1gRQ= +-----END CERTIFICATE----- diff --git a/spec/fixtures/certs/generated/client_from_root.jks b/spec/fixtures/certs/generated/client_from_root.jks new file mode 100644 index 0000000..e7cd00a Binary files /dev/null and b/spec/fixtures/certs/generated/client_from_root.jks differ diff --git a/spec/fixtures/certs/generated/client_from_root.key b/spec/fixtures/certs/generated/client_from_root.key new file mode 100644 index 0000000..674821a --- /dev/null +++ b/spec/fixtures/certs/generated/client_from_root.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/certs/generated/client_from_root.key.pkcs8 b/spec/fixtures/certs/generated/client_from_root.key.pkcs8 new file mode 100644 index 0000000..e3caa00 --- /dev/null +++ b/spec/fixtures/certs/generated/client_from_root.key.pkcs8 @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +1RNKTSMq7zpGMzQSlv8udQbWq1Kk8g== +-----END PRIVATE KEY----- diff --git a/spec/fixtures/certs/generated/client_from_root.p12 b/spec/fixtures/certs/generated/client_from_root.p12 new file mode 100644 index 0000000..4518191 Binary files /dev/null and b/spec/fixtures/certs/generated/client_from_root.p12 differ diff --git a/spec/fixtures/certs/generated/root.crt b/spec/fixtures/certs/generated/root.crt new file mode 100644 index 0000000..ec2f5e7 --- /dev/null +++ b/spec/fixtures/certs/generated/root.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFkzCCA3ugAwIBAgIUaxaJxbTdJbY8LgQDDEur7n4wqoUwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCTFMxCzAJBgNVBAgMAk5BMRMwEQYDVQQHDApIdHRwIElu +cHV0MREwDwYDVQQKDAhMb2dzdGFzaDENMAsGA1UEAwwEcm9vdDAeFw0yMTExMjQx +MDIxMjlaFw0yNjExMjQxMDIxMjlaMFExCzAJBgNVBAYTAkxTMQswCQYDVQQIDAJO +QTETMBEGA1UEBwwKSHR0cCBJbnB1dDERMA8GA1UECgwITG9nc3Rhc2gxDTALBgNV +BAMMBHJvb3QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwVfl113eq +oUSLcw0Xrp1H0UoRLrQoo4h88HtspnJwuTok2PiEIbhUebufzK0nF2ZybVJYiC0Z +JJuSqicMCm9VpznJVRNNT/a7gMcF4j0lYdT2Yuxw2yaCZcvCffVIRU0LIUjj2bXa +83ibuuphfwcm+C3bJ5xWN65F0Txe7mCh8PQ+X0v0peNjkdGHt1LFP3qFV67ssNtx +jeVB35rmKL/OD8gr9fNHFF5B5A8DXniLpohJZLrVFLw455Fyhx+GS+ZQpaHxfneI +hMfftflfabXZNO/pzbSHJShKhIboAfM/bXX5cnilIeLBwko/WPtO81M13rX+e3VF +UFxtXor2z1MhoV01+PfVtTem0iinkYJUtulfrGvolgaQhV+UhgoOuvmYQkj7pmd/ +41pRarhxKp5jRjz3TEfY6PZjGV7vF2Q9IAk2yAUvAhY8qER+eGZe5krUKBV1gLww +zOplQMerG3+Jrm1Fk6sDGw0wJIQUCu3P3nhQTqyqx8z5Sk5dWPMQBkbJMtUIdFOD +/JxJWb171xkH1VNH9zXJfAzHVpk1cgVruF1VtepceQh0rW6E7Lc+Avbg23Zr06fj +kklKNaKabScl7uE7LiGhSpV6N2MJURtJB9jI9oRdYDCBhLihDbn33MrdseOzuWgd +uWZtvUzPKWuzTLpFnnF3krwgUm8TZW81MQIDAQABo2MwYTAdBgNVHQ4EFgQUp9fH +b97tEfzvywzwu4fsB5XKRagwHwYDVR0jBBgwFoAUp9fHb97tEfzvywzwu4fsB5XK +RagwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL +BQADggIBAEC17d/UJpmABMNmV9PMbt5NjiD+dDi8rnE05zXQXhJWm2vZh0nLC3sc +QAJCep5xEHRzOSYSrOihzHF/Pk1Zdl4ly0SZHPtNdipphqWE/Vl9GaQahq8HZg1Y +CjGQvr0MFe4ikOGRkGw9Vp8lR4XXUJxv4VegpX3BRy2+hTgi21kV4X0a5eZ17Li9 +MTljj22vxlypRIu0Jw4BPT0iayc8DivPI4vshUUFc+MLB/1h8OdY19KtoscMaIjk +90xDyAeL6/xxL4ZWDrXEUsxxoakt4vRJaCQ2hCLSVk8isQfzJhkSDqEkK5Ypo+D0 +qDn8eL3w06qA1SvvtxVvKOAHHBLlb8ENoRUtBjTzBNQa2t/zDULogwTQbcY7JpwH +FAVXBfqKQ0pLuVuPeTaE6K7eE0p0/upE78FFOsmfoOL34ziw6imTyOgnmYNsmY19 +Q8rE4n3hKCd4S/Vl2In9Ly8XAQpj5BYLRqxuMkx57oYQ4byr1vVas7iUIXAZSRIi +W9f+9wZ+L99tgXVIKWaA2xD24lGKfr6WKnazUJYRRJifBE3VFgydbewVePRmPbMC +P4OAVX4ERUZXuP6zpfm5rZvgesoe0ZCDIPT2U+im8OnUq1saODBuh8Frx3BXIGVx +zUQzkIYc5+zF5a4LGN2AlCr3kTEJuE3rgEKwA/gGFqYBw3CfOrhH +-----END CERTIFICATE----- diff --git a/spec/fixtures/certs/generated/root.key b/spec/fixtures/certs/generated/root.key new file mode 100644 index 0000000..99944f5 --- /dev/null +++ b/spec/fixtures/certs/generated/root.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/certs/generated/root.key.pkcs8 b/spec/fixtures/certs/generated/root.key.pkcs8 new file mode 100644 index 0000000..1778dcc --- /dev/null +++ b/spec/fixtures/certs/generated/root.key.pkcs8 @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +4FPPlZqhsT/dPOtTFHF4qPXJbLuz6Jk= +-----END PRIVATE KEY----- diff --git a/spec/fixtures/certs/generated/server_from_root.crt b/spec/fixtures/certs/generated/server_from_root.crt new file mode 100644 index 0000000..d20c3f1 --- /dev/null +++ b/spec/fixtures/certs/generated/server_from_root.crt @@ -0,0 +1,37 @@ +-----BEGIN CERTIFICATE----- +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 +PgAX97A6xJeB4AFhXw== +-----END CERTIFICATE----- diff --git a/spec/fixtures/certs/generated/server_from_root.key b/spec/fixtures/certs/generated/server_from_root.key new file mode 100644 index 0000000..843b267 --- /dev/null +++ b/spec/fixtures/certs/generated/server_from_root.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/spec/fixtures/certs/generated/server_from_root.key.pkcs8 b/spec/fixtures/certs/generated/server_from_root.key.pkcs8 new file mode 100644 index 0000000..3bcd829 --- /dev/null +++ b/spec/fixtures/certs/generated/server_from_root.key.pkcs8 @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +2ovkeMh05cseiXfaeEaXgvoABDrwog== +-----END PRIVATE KEY----- diff --git a/spec/fixtures/certs/openssl.cnf b/spec/fixtures/certs/openssl.cnf new file mode 100644 index 0000000..ce7a5bd --- /dev/null +++ b/spec/fixtures/certs/openssl.cnf @@ -0,0 +1,47 @@ +[ req ] +distinguished_name= req_distinguished_name +attributes= req_attributes + +[ req_distinguished_name ] +countryName= Country Name (2 letter code) +countryName_min= 2 +countryName_max= 2 +stateOrProvinceName= State or Province Name (full name) +localityName= Locality Name (eg, city) +0.organizationName= Organization Name (eg, company) +organizationalUnitName= Organizational Unit Name (eg, section) +commonName= Common Name (eg, fully qualified host name) +commonName_max= 64 +emailAddress= Email Address +emailAddress_max= 64 + +[ req_attributes ] +challengePassword= A challenge password +challengePassword_min= 4 +challengePassword_max= 20 + +[ ca ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer +basicConstraints = critical, CA:true +keyUsage = critical, digitalSignature, cRLSign, keyCertSign + +[ client_cert ] +basicConstraints = CA:FALSE +nsCertType = client, email +nsComment = "OpenSSL Generated Client Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer +keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = clientAuth, emailProtection +subjectAltName = "DNS:localhost, IP:127.0.0.1" + +[ server_cert ] +basicConstraints = CA:FALSE +nsCertType = server +nsComment = "OpenSSL Generated Server Certificate" +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid,issuer:always +keyUsage = critical, digitalSignature, keyEncipherment +extendedKeyUsage = serverAuth +subjectAltName = "DNS:localhost, IP:127.0.0.1" diff --git a/spec/inputs/http_spec.rb b/spec/inputs/http_spec.rb index 3474130..37f9fe3 100644 --- a/spec/inputs/http_spec.rb +++ b/spec/inputs/http_spec.rb @@ -20,6 +20,11 @@ let(:client_options) { { } } let(:logstash_queue) { Queue.new } let(:port) { rand(5000) + 1025 } + let(:url) { "http://127.0.0.1:#{port}" } + + let(:config) { { "port" => port } } + + subject { described_class.new(config) } it_behaves_like "an interruptible input plugin" do let(:config) { { "port" => port } } @@ -32,7 +37,6 @@ end describe "request handling" do - subject { LogStash::Inputs::Http.new("port" => port) } before :each do setup_server_client @@ -49,7 +53,7 @@ "socket_timeout" => 0.1 } } - subject { described_class.new("port" => port, "threads" => threads, "max_pending_requests" => max_pending_requests) } + let(:config) { { "port" => port, "threads" => threads, "max_pending_requests" => max_pending_requests } } context "when sending more requests than queue slots" do it "should block when the queue is full" do @@ -74,7 +78,7 @@ end context "with default codec" do - subject { LogStash::Inputs::Http.new("port" => port) } + context "when receiving a text/plain request" do it "should process the request normally" do client.post("http://127.0.0.1:#{port}/meh.json", @@ -84,6 +88,7 @@ expect(event.get("message")).to eq("hello") end end + context "when receiving a deflate compressed text/plain request" do it "should process the request normally" do client.post("http://127.0.0.1:#{port}/meh.json", @@ -93,16 +98,18 @@ expect(event.get("message")).to eq("hello") end end + context "when receiving a deflate text/plain request that cannot be decompressed" do let(:response) do - response = client.post("http://127.0.0.1:#{port}/meh.json", - :headers => { "content-type" => "text/plain", "content-encoding" => "deflate" }, - :body => "hello").call + client.post("http://127.0.0.1:#{port}/meh.json", + :headers => { "content-type" => "text/plain", "content-encoding" => "deflate" }, + :body => "hello").call end it "should respond with 400" do expect(response.code).to eq(400) end end + context "when receiving a gzip compressed text/plain request" do it "should process the request normally" do wio = StringIO.new("w") @@ -118,6 +125,7 @@ expect(event.get("message")).to eq("hello") end end + context "when receiving a gzip text/plain request that cannot be decompressed" do let(:response) do client.post("http://127.0.0.1:#{port}", @@ -128,6 +136,7 @@ expect(response.code).to eq(400) end end + context "when receiving an application/json request" do it "should parse the json body" do client.post("http://127.0.0.1:#{port}/meh.json", @@ -140,16 +149,94 @@ end context "with json codec" do - subject { LogStash::Inputs::Http.new("port" => port, "codec" => "json") } + let(:config) { super().merge("codec" => "json") } + let(:url) { "http://127.0.0.1:#{port}/meh.json" } + let(:response) do + client.post(url, :body => { "message" => "Hello" }.to_json).call + end + it "should parse the json body" do - response = client.post("http://127.0.0.1:#{port}/meh.json", :body => { "message" => "Hello" }.to_json).call + expect(response.code).to eq(200) event = logstash_queue.pop expect(event.get("message")).to eq("Hello") end + + context 'with ssl' do + + let(:url) { super().sub('http://', 'https://') } + + certs_dir = File.expand_path('../fixtures/certs/generated', File.dirname(__FILE__)) + + let(:config) do + super().merge 'ssl' => true, + 'ssl_certificate_authorities' => [ File.join(certs_dir, 'root.crt') ], + 'ssl_certificate' => File.join(certs_dir, 'server_from_root.crt'), + 'ssl_key' => File.join(certs_dir, 'server_from_root.key.pkcs8'), + 'ssl_verify_mode' => 'peer' + end + + let(:client_options) do + super().merge ssl: { + verify: false, + ca_file: File.join(certs_dir, 'root.crt'), + client_cert: File.join(certs_dir, 'client_from_root.crt'), + client_key: File.join(certs_dir, 'client_from_root.key.pkcs8'), + } + end + + it "should parse the json body" do + # [DEBUG][io.netty.handler.ssl.SslHandler] [id: 0xcaf869ff, L:/127.0.0.1:5610 - R:/127.0.0.1:32890] HANDSHAKEN: protocol:TLSv1.2 cipher suite:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + # [DEBUG][org.apache.http.conn.ssl.SSLConnectionSocketFactory] Secure session established + # [DEBUG][org.apache.http.conn.ssl.SSLConnectionSocketFactory] negotiated protocol: TLSv1.2 + # [DEBUG][org.apache.http.conn.ssl.SSLConnectionSocketFactory] negotiated cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + expect(response.code).to eq(200) + event = logstash_queue.pop + expect(event.get("message")).to eq("Hello") + end + + TLS13_ENABLED_BY_DEFAULT = begin + context = javax.net.ssl.SSLContext.getInstance('TLS') + context.init nil, nil, nil + context.getDefaultSSLParameters.getProtocols.include? 'TLSv1.3' + rescue => e + warn "failed to detect TLSv1.3 support: #{e.inspect}" + nil + end + + context 'with TLSv1.3 client' do + + let(:client_options) do + super().tap do |opts| + opts.fetch(:ssl).merge! protocols: ['TLSv1.3'] + end + end + + it "should parse the json body" do + expect(response.code).to eq(200) + event = logstash_queue.pop + expect(event.get("message")).to eq("Hello") + end + + context 'enforced TLSv1.3 in plugin' do + + let(:config) { super().merge 'tls_min_version' => '1.3', 'cipher_suites' => [ 'TLS_AES_128_GCM_SHA256' ] } + + it "should parse the json body" do + expect(response.code).to eq(200) + event = logstash_queue.pop + expect(event.get("message")).to eq("Hello") + end + + end + + end if TLS13_ENABLED_BY_DEFAULT + + end + end context "with json_lines codec without final delimiter" do - subject { LogStash::Inputs::Http.new("port" => port, "codec" => "json_lines") } + let(:config) { super().merge("codec" => "json_lines") } let(:line1) { '{"foo": 1}' } let(:line2) { '{"foo": 2}' } it "should parse all json_lines in body including last one" do @@ -169,7 +256,7 @@ body = { "message" => "Hello" }.to_json client.post("http://127.0.0.1:#{port}/meh.json", :headers => { "content-type" => "application/json" }, - :body => body).call + :body => body).call event = logstash_queue.pop expect(event.get("message")).to eq(body) end @@ -388,15 +475,18 @@ end # wait until server is ready - def setup_server_client + def setup_server_client(url = self.url) subject.register - t = Thread.new { subject.run(logstash_queue) } + t = Thread.start { subject.run(logstash_queue) } ok = false until ok begin - client.post("http://127.0.0.1:#{port}", :body => '{}').call - rescue => e - # retry + client.post(url, :body => '{}').call + rescue Manticore::SocketException => e + puts "retry client.post due #{e}" if $VERBOSE + rescue Manticore::ManticoreException => e + warn e.inspect + raise e.cause ? e.cause : e else ok = true end @@ -548,8 +638,7 @@ def setup_server_client context "with invalid ssl certificate_authorities" do let(:config) do - super().merge("ssl_verify_mode" => "peer", - "ssl_certificate_authorities" => [ ssc.certificate.path, ssc.private_key.path ]) + super().merge("ssl_verify_mode" => "peer", "ssl_certificate_authorities" => [ ssc.certificate.path, ssc.private_key.path ]) end it "should raise a cert error" do diff --git a/src/main/java/org/logstash/plugins/inputs/http/util/SslHandlerProvider.java b/src/main/java/org/logstash/plugins/inputs/http/util/SslHandlerProvider.java index e887996..489ba4d 100644 --- a/src/main/java/org/logstash/plugins/inputs/http/util/SslHandlerProvider.java +++ b/src/main/java/org/logstash/plugins/inputs/http/util/SslHandlerProvider.java @@ -22,7 +22,7 @@ enum SslClientVerifyMode { NONE } - private String[] protocols = new String[] { "TLSv1.2" }; + private String[] protocols = new String[] { "TLSv1.2", "TLSv1.3" }; public SslHandlerProvider(SslContext sslContext) { this.sslContext = sslContext; @@ -58,7 +58,7 @@ public void setVerifyMode(String verifyMode) { } public void setProtocols(String[] protocols) { - if(logger.isDebugEnabled()) + if (logger.isDebugEnabled()) logger.debug("TLS: " + Arrays.toString(protocols)); this.protocols = protocols; diff --git a/src/main/java/org/logstash/plugins/inputs/http/util/SslSimpleBuilder.java b/src/main/java/org/logstash/plugins/inputs/http/util/SslSimpleBuilder.java index 8fe4fec..b305fe1 100644 --- a/src/main/java/org/logstash/plugins/inputs/http/util/SslSimpleBuilder.java +++ b/src/main/java/org/logstash/plugins/inputs/http/util/SslSimpleBuilder.java @@ -7,7 +7,6 @@ import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.security.NoSuchAlgorithmException; @@ -16,7 +15,9 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.crypto.Cipher; import javax.net.ssl.SSLException; import javax.net.ssl.SSLServerSocketFactory; @@ -25,20 +26,35 @@ public class SslSimpleBuilder implements SslBuilder { private final static Logger logger = LogManager.getLogger(SslSimpleBuilder.class); + static final Set SUPPORTED_CIPHERS = new HashSet<>(Arrays.asList( + ((SSLServerSocketFactory) SSLServerSocketFactory.getDefault()).getSupportedCipherSuites() + )); + /* - Modern Ciphers Compatibility List from - https://wiki.mozilla.org/Security/Server_Side_TLS + Ciphers Compatibility List from https://wiki.mozilla.org/Security/Server_Side_TLS */ - private final static String[] DEFAULT_CIPHERS = new String[] { + private final static String[] DEFAULT_CIPHERS; + static { + String[] defaultCipherCandidates = new String[] { + // Modern compatibility + "TLS_AES_128_GCM_SHA256", // TLS 1.3 + "TLS_AES_256_GCM_SHA384", // TLS 1.3 + "TLS_CHACHA20_POLY1305_SHA256", // TLS 1.3 (since Java 11.0.14) + // Intermediate compatibility "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", // (since Java 11.0.14) + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", // (since Java 11.0.14) "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + // Backward compatibility "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" - }; + }; + DEFAULT_CIPHERS = Arrays.stream(defaultCipherCandidates).filter(SUPPORTED_CIPHERS::contains).toArray(String[]::new); + } private final static String[] DEFAULT_CIPHERS_LIMITED = new String[] { "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", @@ -56,20 +72,18 @@ public class SslSimpleBuilder implements SslBuilder { private File sslCertificateFile; private String[] certificateAuthorities; private String passPhrase; - private String[] supportedCiphers = ((SSLServerSocketFactory)SSLServerSocketFactory - .getDefault()).getSupportedCipherSuites(); - public SslSimpleBuilder(String sslCertificateFilePath, String sslKeyFilePath, String pass) throws FileNotFoundException { + public SslSimpleBuilder(String sslCertificateFilePath, String sslKeyFilePath, String pass) { sslCertificateFile = new File(sslCertificateFilePath); sslKeyFile = new File(sslKeyFilePath); passPhrase = pass; } public SslSimpleBuilder setCipherSuites(String[] ciphersSuite) throws IllegalArgumentException { - for(String cipher : ciphersSuite) { - if(Arrays.asList(supportedCiphers).contains(cipher)) { - logger.debug("Cipher is supported: {}", cipher); - }else{ + for (String cipher : ciphersSuite) { + if (SUPPORTED_CIPHERS.contains(cipher)) { + logger.debug("{} cipher is supported", cipher); + } else { if (!isUnlimitedJCEAvailable()) { logger.warn("JCE Unlimited Strength Jurisdiction Policy not installed"); } @@ -89,14 +103,14 @@ public SslSimpleBuilder setCertificateAuthorities(String[] cert) { public SslContext build() throws Exception { SslContextBuilder builder = SslContextBuilder.forServer(sslCertificateFile, sslKeyFile, passPhrase); - if(logger.isDebugEnabled()) { - logger.debug("Available ciphers: " + Arrays.toString(supportedCiphers)); + if (logger.isDebugEnabled()) { + logger.debug("Available ciphers: " + SUPPORTED_CIPHERS); logger.debug("Ciphers: " + Arrays.toString(ciphers)); } builder.ciphers(Arrays.asList(ciphers)); - if(requireClientAuth()) { + if (requireClientAuth()) { if (logger.isDebugEnabled()) logger.debug("Certificate Authorities: " + Arrays.toString(certificateAuthorities)); @@ -145,14 +159,14 @@ private X509Certificate[] loadCertificateCollection(String[] certificates) throw } private boolean requireClientAuth() { - if(certificateAuthorities != null) { + if (certificateAuthorities != null) { return true; } return false; } - public static String[] getDefaultCiphers(){ + public static String[] getDefaultCiphers() { if (isUnlimitedJCEAvailable()){ return DEFAULT_CIPHERS; } else {