From af001b6099a392b4af7daf1c44fd85b927d26fec Mon Sep 17 00:00:00 2001 From: Sid Narayan Date: Mon, 22 Jun 2020 13:42:30 -0700 Subject: [PATCH 1/7] Add required mutual auth to gRPC Server/Client Previously we had 1 sided TLS on the server side. Data between the client and server was send over an encrypted channel, but any client could make requests to the server. This commit changes the behavior so that only clients with the matching certificates can make requests to the server when TLS is enabled. This commit does NOT add support for installing a trust manager. That must be added in the future. --- gradle.properties | 3 +- .../performanceanalyzer/net/NetServer.java | 9 ++++++ .../performanceanalyzer/net/GRPCTest.java | 3 -- src/test/resources/tls/cert.pem | 22 +++++++++++++++ src/test/resources/tls/key.pem | 28 +++++++++++++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 src/test/resources/tls/cert.pem create mode 100644 src/test/resources/tls/key.pem diff --git a/gradle.properties b/gradle.properties index dc2b47f15..2e20ae60a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,4 +13,5 @@ # permissions and limitations under the License. # -localPaDir=../performance-analyzer \ No newline at end of file +localPaDir=../performance-analyzer +org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=256m \ No newline at end of file diff --git a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/NetServer.java b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/NetServer.java index 440ac6353..886f60139 100644 --- a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/NetServer.java +++ b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/NetServer.java @@ -259,6 +259,15 @@ public void stop() { // Remove handlers. sendDataHandler = null; subscribeHandler = null; + + if (server != null) { + server.shutdown(); + try { + server.awaitTermination(1, TimeUnit.MINUTES); + } catch (InterruptedException e) { + server.shutdownNow(); + } + } } public void shutdown() { diff --git a/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/GRPCTest.java b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/GRPCTest.java index 002857cf8..7d785065a 100644 --- a/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/GRPCTest.java +++ b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/GRPCTest.java @@ -2,19 +2,16 @@ import com.amazon.opendistro.elasticsearch.performanceanalyzer.CertificateUtils; import com.amazon.opendistro.elasticsearch.performanceanalyzer.config.PluginSettings; -import com.amazon.opendistro.elasticsearch.performanceanalyzer.core.Util; import com.amazon.opendistro.elasticsearch.performanceanalyzer.grpc.MetricsRequest; import com.amazon.opendistro.elasticsearch.performanceanalyzer.grpc.MetricsResponse; import com.amazon.opendistro.elasticsearch.performanceanalyzer.rca.GradleTaskForRca; import com.amazon.opendistro.elasticsearch.performanceanalyzer.util.WaitFor; import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; - import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.AfterClass; diff --git a/src/test/resources/tls/cert.pem b/src/test/resources/tls/cert.pem new file mode 100644 index 000000000..54badc744 --- /dev/null +++ b/src/test/resources/tls/cert.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDsDCCApgCCQCbITNfiN+Z1DANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMC +VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEPMA0G +A1UECgwGQW1hem9uMQwwCgYDVQQLDANBV1MxHjAcBgNVBAMMFWNvbS5hbWF6b24u +b3BlbmRpc3RybzEiMCAGCSqGSIb3DQEJARYTc2lkbmFyYXlAYW1hem9uLmNvbTAe +Fw0yMDA2MjIxNzM1NThaFw0zMDA2MjAxNzM1NThaMIGZMQswCQYDVQQGEwJVUzET +MBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJUGFsbyBBbHRvMQ8wDQYDVQQK +DAZBbWF6b24xDDAKBgNVBAsMA0FXUzEeMBwGA1UEAwwVY29tLmFtYXpvbi5vcGVu +ZGlzdHJvMSIwIAYJKoZIhvcNAQkBFhNzaWRuYXJheUBhbWF6b24uY29tMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5UPbbOqaWHbddRJ1YrgmOKX2rPFE +5fq0qeYamYPiq9KsUJP0kX9/XqHSZUNERBxazpynX90E4HwEb9CWULji61t/Ug8K +qyDSBRTg5zGtr/0UUuoovulir3VmJdJHAq5JAKpcexac5ed91Z0PhRsvaPtTZ6Fu +k2xO/h0cFj0cWZFGpOVjSACGGjVZaTSKD8dMS+7d2KZ8SYNtWaweyLeh2BbITW/s +x/RdAsuBgcKl54Ifit78B4V2ZSOj7c3ZQ3JLRJhzO9v8c/1eraVAL0Bh8RF7FgKH +2izxBXh309CKg4f/tIYJihkJTQLwQMHMXPX6bROwuPewc/cZp6zCjBd01wIDAQAB +MA0GCSqGSIb3DQEBCwUAA4IBAQDcVmCkJHBkCR5or10huyuGArhMo2QcJg296oA7 +hioF6s/7nzS5/K0KDCpJdrg7P1swOmGG6ctFtFiNzdf3uoK91sRsDgmQBc+slymM +uy3dGkWYfPEqWFlHQ0+gbYmeuPZWDm5mWw0R26mcFR8Div+49E5/NL2d0tpawHKQ +UYBCNed6gRK56kkRIS/sjcMFcPgsJiLDZwD2sXh9F+CrOPvvHmCOebZbw/UxZARs +fh01rq96SzhPAmGxk+YqK3s7Gi9aP35QAg9Lr64pew7u1feMzk9/gxqN5zQoCM7u +Tnkl9lq6K/gHEyHoC1NfVTHBDeTol/OLUK+XNP4efbbWG60Z +-----END CERTIFICATE----- diff --git a/src/test/resources/tls/key.pem b/src/test/resources/tls/key.pem new file mode 100644 index 000000000..951c15a39 --- /dev/null +++ b/src/test/resources/tls/key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDlQ9ts6ppYdt11 +EnViuCY4pfas8UTl+rSp5hqZg+Kr0qxQk/SRf39eodJlQ0REHFrOnKdf3QTgfARv +0JZQuOLrW39SDwqrINIFFODnMa2v/RRS6ii+6WKvdWYl0kcCrkkAqlx7Fpzl533V +nQ+FGy9o+1NnoW6TbE7+HRwWPRxZkUak5WNIAIYaNVlpNIoPx0xL7t3YpnxJg21Z +rB7It6HYFshNb+zH9F0Cy4GBwqXngh+K3vwHhXZlI6PtzdlDcktEmHM72/xz/V6t +pUAvQGHxEXsWAofaLPEFeHfT0IqDh/+0hgmKGQlNAvBAwcxc9fptE7C497Bz9xmn +rMKMF3TXAgMBAAECggEAWcaTovfPDrslBxX+T3Tqyp36lUg5AZGFs03+toSVe1EY +1sjJKTxy5NybJboMfltYF7XyOLC0my8VEa/tXJi5iw4eMkTfmZlVhFXjp8SlTdfd +YIZ/BBsh4LEpGcBYvC0BOzh61FxLfh+C/+Xr0OSPUR2xUFA/m4z69bjyaabudgeW +W9wXDkwN1iRMuh/sc8pBFxvm1oqNwolhIoksHKa1JdF/+9vwXx51g/UwwA/OtEzT +OlDpfTBxbxDYLUyOeIJ/uCf4N0Ouzh+NfcHE83V6up5sjOQAUJMlXTl78JS+ANuF +jy77u9CThiFRjRLHpNYVcuSKtlv1lLuF30TpTHNKoQKBgQD+UlPuKNiuaG5p+P6T +g8wPa178MWEjcLd6ujYtPKIjiahUrzDm4eISPQKfc/jiZ+cB592S9hYZoze2Il8z +JeyBeoUHw/bNtYqDs3BtgDcadG7x7Us30Sh/xClF+BdcDoSUeJttwIrCorIlK/Yq +5SMzrDMqb2iVxvMBxaQ93yHk5wKBgQDmxzJaNsveGMMlXINEXj8zpXKVhryuLQxF +0aoCSatREorX/14xq6CBeUu+cGFDX2jsi8+qL9S06lv7D4HiREHxYqdKy+Er+QLO +E3YqRBM+Kza4K5LSBQM525TKtiOYAFhgKguEtMYYZGEYqpfuSGmphoz5YAbo84gK +4xKoWq0CkQKBgQDm3A8KOxPuxieslPVrLRG40YvIvH5kMHattollaQv53ITsUpe+ +jj+stKtD2X+M7iqZ5UOSm0aWgT4aXHs0r/FP28sUsIPCWlBhmyqsi935asYnYHOO +OJRd3tBkjn+N9jPNnungqA6N/ihea9irOZNJ3cAYfkde5tlCu4mLDJj08wKBgFUY +wsJtTkN5UgwmzuiY8Ck1KslkQ5LeXZYpN81cKOXeNoBrU+pw5OCZP4rbmaHkPqZq +74pL1N1ZRc2P7E7o6H//5rw37bHvQk+G8Z2oOIhGGwlSV/NFkej1xSnye7GC/xOG +rXSjzCAWc49K6HcfEIdIbBdQh3vCwTlyfeDCfuVhAoGAS/56UW9mKmzfxLZsi0Pt +ni+CZ8PAZixM3QZQyt9D5uFBdyjq/IogHVI8kubZmP7G6OOvrYzIKgqWUC7ZAoyZ +vHaumun26J8nb36dprRwKjMTbBe5zQFYNwlc+NYZOe1UVUmw7WqXZT/kkSEsjJPB +isivpoQQQzbq1TnL0Lw8v2g= +-----END PRIVATE KEY----- From d0b6804081c6bc40602f86400e8a0ab9edce6537 Mon Sep 17 00:00:00 2001 From: Sid Narayan Date: Wed, 1 Jul 2020 10:48:09 -0700 Subject: [PATCH 2/7] Add full mutual auth to gRPC client/server and augment tests --- gradle.properties | 3 +- .../performanceanalyzer/net/NetServer.java | 9 ------ .../rca/net/WireHopperTest.java | 3 ++ src/test/resources/tls/cert.pem | 22 --------------- src/test/resources/tls/key.pem | 28 ------------------- 5 files changed, 4 insertions(+), 61 deletions(-) delete mode 100644 src/test/resources/tls/cert.pem delete mode 100644 src/test/resources/tls/key.pem diff --git a/gradle.properties b/gradle.properties index 2e20ae60a..dc2b47f15 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,5 +13,4 @@ # permissions and limitations under the License. # -localPaDir=../performance-analyzer -org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=256m \ No newline at end of file +localPaDir=../performance-analyzer \ No newline at end of file diff --git a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/NetServer.java b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/NetServer.java index 886f60139..440ac6353 100644 --- a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/NetServer.java +++ b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/net/NetServer.java @@ -259,15 +259,6 @@ public void stop() { // Remove handlers. sendDataHandler = null; subscribeHandler = null; - - if (server != null) { - server.shutdown(); - try { - server.awaitTermination(1, TimeUnit.MINUTES); - } catch (InterruptedException e) { - server.shutdownNow(); - } - } } public void shutdown() { diff --git a/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/rca/net/WireHopperTest.java b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/rca/net/WireHopperTest.java index 39f7290b0..a59f1849c 100644 --- a/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/rca/net/WireHopperTest.java +++ b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/rca/net/WireHopperTest.java @@ -1,6 +1,9 @@ package com.amazon.opendistro.elasticsearch.performanceanalyzer.rca.net; +<<<<<<< HEAD import com.amazon.opendistro.elasticsearch.performanceanalyzer.AppContext; +======= +>>>>>>> d84454b... Add full mutual auth to gRPC client/server and augment tests import com.amazon.opendistro.elasticsearch.performanceanalyzer.grpc.FlowUnitMessage; import com.amazon.opendistro.elasticsearch.performanceanalyzer.net.GRPCConnectionManager; import com.amazon.opendistro.elasticsearch.performanceanalyzer.net.NetClient; diff --git a/src/test/resources/tls/cert.pem b/src/test/resources/tls/cert.pem deleted file mode 100644 index 54badc744..000000000 --- a/src/test/resources/tls/cert.pem +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDsDCCApgCCQCbITNfiN+Z1DANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMC -VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEPMA0G -A1UECgwGQW1hem9uMQwwCgYDVQQLDANBV1MxHjAcBgNVBAMMFWNvbS5hbWF6b24u -b3BlbmRpc3RybzEiMCAGCSqGSIb3DQEJARYTc2lkbmFyYXlAYW1hem9uLmNvbTAe -Fw0yMDA2MjIxNzM1NThaFw0zMDA2MjAxNzM1NThaMIGZMQswCQYDVQQGEwJVUzET -MBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJUGFsbyBBbHRvMQ8wDQYDVQQK -DAZBbWF6b24xDDAKBgNVBAsMA0FXUzEeMBwGA1UEAwwVY29tLmFtYXpvbi5vcGVu -ZGlzdHJvMSIwIAYJKoZIhvcNAQkBFhNzaWRuYXJheUBhbWF6b24uY29tMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5UPbbOqaWHbddRJ1YrgmOKX2rPFE -5fq0qeYamYPiq9KsUJP0kX9/XqHSZUNERBxazpynX90E4HwEb9CWULji61t/Ug8K -qyDSBRTg5zGtr/0UUuoovulir3VmJdJHAq5JAKpcexac5ed91Z0PhRsvaPtTZ6Fu -k2xO/h0cFj0cWZFGpOVjSACGGjVZaTSKD8dMS+7d2KZ8SYNtWaweyLeh2BbITW/s -x/RdAsuBgcKl54Ifit78B4V2ZSOj7c3ZQ3JLRJhzO9v8c/1eraVAL0Bh8RF7FgKH -2izxBXh309CKg4f/tIYJihkJTQLwQMHMXPX6bROwuPewc/cZp6zCjBd01wIDAQAB -MA0GCSqGSIb3DQEBCwUAA4IBAQDcVmCkJHBkCR5or10huyuGArhMo2QcJg296oA7 -hioF6s/7nzS5/K0KDCpJdrg7P1swOmGG6ctFtFiNzdf3uoK91sRsDgmQBc+slymM -uy3dGkWYfPEqWFlHQ0+gbYmeuPZWDm5mWw0R26mcFR8Div+49E5/NL2d0tpawHKQ -UYBCNed6gRK56kkRIS/sjcMFcPgsJiLDZwD2sXh9F+CrOPvvHmCOebZbw/UxZARs -fh01rq96SzhPAmGxk+YqK3s7Gi9aP35QAg9Lr64pew7u1feMzk9/gxqN5zQoCM7u -Tnkl9lq6K/gHEyHoC1NfVTHBDeTol/OLUK+XNP4efbbWG60Z ------END CERTIFICATE----- diff --git a/src/test/resources/tls/key.pem b/src/test/resources/tls/key.pem deleted file mode 100644 index 951c15a39..000000000 --- a/src/test/resources/tls/key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDlQ9ts6ppYdt11 -EnViuCY4pfas8UTl+rSp5hqZg+Kr0qxQk/SRf39eodJlQ0REHFrOnKdf3QTgfARv -0JZQuOLrW39SDwqrINIFFODnMa2v/RRS6ii+6WKvdWYl0kcCrkkAqlx7Fpzl533V -nQ+FGy9o+1NnoW6TbE7+HRwWPRxZkUak5WNIAIYaNVlpNIoPx0xL7t3YpnxJg21Z -rB7It6HYFshNb+zH9F0Cy4GBwqXngh+K3vwHhXZlI6PtzdlDcktEmHM72/xz/V6t -pUAvQGHxEXsWAofaLPEFeHfT0IqDh/+0hgmKGQlNAvBAwcxc9fptE7C497Bz9xmn -rMKMF3TXAgMBAAECggEAWcaTovfPDrslBxX+T3Tqyp36lUg5AZGFs03+toSVe1EY -1sjJKTxy5NybJboMfltYF7XyOLC0my8VEa/tXJi5iw4eMkTfmZlVhFXjp8SlTdfd -YIZ/BBsh4LEpGcBYvC0BOzh61FxLfh+C/+Xr0OSPUR2xUFA/m4z69bjyaabudgeW -W9wXDkwN1iRMuh/sc8pBFxvm1oqNwolhIoksHKa1JdF/+9vwXx51g/UwwA/OtEzT -OlDpfTBxbxDYLUyOeIJ/uCf4N0Ouzh+NfcHE83V6up5sjOQAUJMlXTl78JS+ANuF -jy77u9CThiFRjRLHpNYVcuSKtlv1lLuF30TpTHNKoQKBgQD+UlPuKNiuaG5p+P6T -g8wPa178MWEjcLd6ujYtPKIjiahUrzDm4eISPQKfc/jiZ+cB592S9hYZoze2Il8z -JeyBeoUHw/bNtYqDs3BtgDcadG7x7Us30Sh/xClF+BdcDoSUeJttwIrCorIlK/Yq -5SMzrDMqb2iVxvMBxaQ93yHk5wKBgQDmxzJaNsveGMMlXINEXj8zpXKVhryuLQxF -0aoCSatREorX/14xq6CBeUu+cGFDX2jsi8+qL9S06lv7D4HiREHxYqdKy+Er+QLO -E3YqRBM+Kza4K5LSBQM525TKtiOYAFhgKguEtMYYZGEYqpfuSGmphoz5YAbo84gK -4xKoWq0CkQKBgQDm3A8KOxPuxieslPVrLRG40YvIvH5kMHattollaQv53ITsUpe+ -jj+stKtD2X+M7iqZ5UOSm0aWgT4aXHs0r/FP28sUsIPCWlBhmyqsi935asYnYHOO -OJRd3tBkjn+N9jPNnungqA6N/ihea9irOZNJ3cAYfkde5tlCu4mLDJj08wKBgFUY -wsJtTkN5UgwmzuiY8Ck1KslkQ5LeXZYpN81cKOXeNoBrU+pw5OCZP4rbmaHkPqZq -74pL1N1ZRc2P7E7o6H//5rw37bHvQk+G8Z2oOIhGGwlSV/NFkej1xSnye7GC/xOG -rXSjzCAWc49K6HcfEIdIbBdQh3vCwTlyfeDCfuVhAoGAS/56UW9mKmzfxLZsi0Pt -ni+CZ8PAZixM3QZQyt9D5uFBdyjq/IogHVI8kubZmP7G6OOvrYzIKgqWUC7ZAoyZ -vHaumun26J8nb36dprRwKjMTbBe5zQFYNwlc+NYZOe1UVUmw7WqXZT/kkSEsjJPB -isivpoQQQzbq1TnL0Lw8v2g= ------END PRIVATE KEY----- From f545e2cc13526a22524cdc95293fb87ca38d9ed2 Mon Sep 17 00:00:00 2001 From: Sid Narayan Date: Sun, 12 Jul 2020 14:46:29 -0700 Subject: [PATCH 3/7] Implement mutual auth for the REST endpoints This commit makes the PerformanceAnalyzerWebServer authenticate clients if the user specifies a certificate authority. It also properly sets up the server's identity, so that any clients can authenticate the server. --- .../performanceanalyzer/CertificateUtils.java | 43 ++- .../PerformanceAnalyzerWebServer.java | 85 ++++-- .../config/PluginSettings.java | 5 + .../PerformanceAnalyzerWebServerTest.java | 272 ++++++++++++++++++ 4 files changed, 371 insertions(+), 34 deletions(-) create mode 100644 src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServerTest.java diff --git a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/CertificateUtils.java b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/CertificateUtils.java index 57eee09d6..49d05a2f8 100644 --- a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/CertificateUtils.java +++ b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/CertificateUtils.java @@ -21,7 +21,12 @@ import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; +import java.security.cert.X509Certificate; import javax.annotation.Nullable; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; @@ -32,7 +37,7 @@ public class CertificateUtils { - public static final String ALIAS_PRIVATE = "private"; + public static final String ALIAS_IDENTITY = "identity"; public static final String ALIAS_CERT = "cert"; // The password is not used to encrypt keys on disk. public static final String IN_MEMORY_PWD = "opendistro"; @@ -65,14 +70,46 @@ public static PrivateKey getPrivateKey(final FileReader keyReader) throws Except public static KeyStore createKeyStore() throws Exception { String certFilePath = PluginSettings.instance().getSettingValue(CERTIFICATE_FILE_PATH); String keyFilePath = PluginSettings.instance().getSettingValue(PRIVATE_KEY_FILE_PATH); + KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection( + CertificateUtils.IN_MEMORY_PWD.toCharArray()); PrivateKey pk = getPrivateKey(new FileReader(keyFilePath)); KeyStore ks = createEmptyStore(); Certificate certificate = getCertificate(new FileReader(certFilePath)); - ks.setCertificateEntry(ALIAS_CERT, certificate); - ks.setKeyEntry(ALIAS_PRIVATE, pk, IN_MEMORY_PWD.toCharArray(), new Certificate[] {certificate}); + ks.setEntry(ALIAS_IDENTITY, new KeyStore.PrivateKeyEntry(pk, new Certificate[]{certificate}), protParam); return ks; } + public static TrustManager[] getTrustManagers(boolean forServer) throws Exception { + // If a certificate authority is specified, create an authenticating trust manager + String certificateAuthority; + if (forServer) { + certificateAuthority = PluginSettings.instance().getSettingValue(TRUSTED_CAS_FILE_PATH); + } else { + certificateAuthority = PluginSettings.instance().getSettingValue(CLIENT_TRUSTED_CAS_FILE_PATH); + } + if (certificateAuthority != null && !certificateAuthority.isEmpty()) { + KeyStore ks = createEmptyStore(); + Certificate certificate = getCertificate(new FileReader(certificateAuthority)); + ks.setCertificateEntry(ALIAS_CERT, certificate); + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); + return tmf.getTrustManagers(); + } + // Otherwise, return an all-trusting TrustManager + return new TrustManager[] { + new X509TrustManager() { + + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] certs, String authType) {} + + public void checkServerTrusted(X509Certificate[] certs, String authType) {} + } + }; + } + public static KeyStore createEmptyStore() throws Exception { KeyStore ks = KeyStore.getInstance("JKS"); ks.load(null, IN_MEMORY_PWD.toCharArray()); diff --git a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServer.java b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServer.java index b8c8b5eea..19119d39e 100644 --- a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServer.java +++ b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServer.java @@ -16,22 +16,25 @@ package com.amazon.opendistro.elasticsearch.performanceanalyzer; import com.amazon.opendistro.elasticsearch.performanceanalyzer.config.PluginSettings; +import com.google.common.annotations.VisibleForTesting; import com.sun.net.httpserver.HttpServer; import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsParameters; import com.sun.net.httpserver.HttpsServer; + import java.net.InetAddress; import java.net.InetSocketAddress; import java.security.KeyStore; import java.security.Security; -import java.security.cert.X509Certificate; import java.util.concurrent.Executors; + import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bouncycastle.jce.provider.BouncyCastleProvider; @@ -40,8 +43,10 @@ public class PerformanceAnalyzerWebServer { private static final Logger LOG = LogManager.getLogger(PerformanceAnalyzerWebServer.class); public static final int WEBSERVICE_DEFAULT_PORT = 9600; - public static final String WEBSERVICE_PORT_CONF_NAME = "webservice-listener-port"; + @VisibleForTesting public static final String WEBSERVICE_BIND_HOST_NAME = "webservice-bind-host"; + @VisibleForTesting + public static final String WEBSERVICE_PORT_CONF_NAME = "webservice-listener-port"; // Use system default for max backlog. private static final int INCOMING_QUEUE_LENGTH = 1; @@ -66,8 +71,34 @@ public static HttpServer createInternalServer(String portFromSetting, String hos return null; } + /** + * ClientAuthConfigurator makes the server perform client authentication if the user has set up a + * certificate authority + */ + private static class ClientAuthConfigurator extends HttpsConfigurator { + public ClientAuthConfigurator(SSLContext sslContext) { + super(sslContext); + } + + @Override + public void configure(HttpsParameters params) { + final SSLParameters sslParams = getSSLContext().getDefaultSSLParameters(); + if (CertificateUtils.getTrustedCasFile() != null) { + LOG.debug("Enabling client auth"); + final SSLEngine sslEngine = getSSLContext().createSSLEngine(); + sslParams.setNeedClientAuth(true); + sslParams.setCipherSuites(sslEngine.getEnabledCipherSuites()); + sslParams.setProtocols(sslEngine.getEnabledProtocols()); + params.setSSLParameters(sslParams); + } else { + LOG.debug("Not enabling client auth"); + super.configure(params); + } + } + } + private static HttpServer createHttpsServer(int readerPort, String bindHost) throws Exception { - HttpsServer server = null; + HttpsServer server; if (bindHost != null && !bindHost.trim().isEmpty()) { LOG.info("Binding to Interface: {}", bindHost); server = @@ -81,38 +112,30 @@ private static HttpServer createHttpsServer(int readerPort, String bindHost) thr server = HttpsServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), readerPort), INCOMING_QUEUE_LENGTH); } - TrustManager[] trustAllCerts = - new TrustManager[] { - new X509TrustManager() { - - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - public void checkClientTrusted(X509Certificate[] certs, String authType) {} - - public void checkServerTrusted(X509Certificate[] certs, String authType) {} - } - }; - - HostnameVerifier allHostsValid = - new HostnameVerifier() { - public boolean verify(String hostname, SSLSession session) { - return true; - } - }; - // Install the all-trusting trust manager SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); KeyStore ks = CertificateUtils.createKeyStore(); KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); kmf.init(ks, CertificateUtils.IN_MEMORY_PWD.toCharArray()); - sslContext.init(kmf.getKeyManagers(), trustAllCerts, null); + sslContext.init(kmf.getKeyManagers(), CertificateUtils.getTrustManagers(true), null); + server.setHttpsConfigurator(new ClientAuthConfigurator(sslContext)); + + + // TODO ask ktkrg why this is necessary + // Try to set HttpsURLConnection defaults, our webserver can still run even if this block fails + try { + LOG.debug("Setting default SSLSocketFactory..."); + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + LOG.debug("Default SSLSocketFactory set successfully"); + HostnameVerifier allHostsValid = (hostname, session) -> true; + LOG.debug("Setting default HostnameVerifier..."); + HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); + LOG.debug("Default HostnameVerifier set successfully"); + } catch (Exception e) { // Usually AccessControlException + LOG.warn("Exception while trying to set URLConnection defaults", e); + } - HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); - HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid); - server.setHttpsConfigurator(new HttpsConfigurator(sslContext)); return server; } diff --git a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/config/PluginSettings.java b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/config/PluginSettings.java index 87bc842f6..0b5f9d036 100644 --- a/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/config/PluginSettings.java +++ b/src/main/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/config/PluginSettings.java @@ -103,6 +103,11 @@ public boolean getHttpsEnabled() { return this.httpsEnabled; } + @VisibleForTesting + public void setHttpsEnabled(boolean httpsEnabled) { + this.httpsEnabled = httpsEnabled; + } + @VisibleForTesting public void overrideProperty(String key, String value) { settings.setProperty(key, value); diff --git a/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServerTest.java b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServerTest.java new file mode 100644 index 000000000..b7a066c68 --- /dev/null +++ b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServerTest.java @@ -0,0 +1,272 @@ +package com.amazon.opendistro.elasticsearch.performanceanalyzer; + +import com.amazon.opendistro.elasticsearch.performanceanalyzer.config.PluginSettings; +import com.sun.net.httpserver.HttpServer; + +import io.grpc.netty.shaded.io.netty.handler.codec.http.HttpResponseStatus; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.KeyStore; +import java.util.Objects; +import java.util.concurrent.Executors; + +import javax.annotation.Nullable; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSocketFactory; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class PerformanceAnalyzerWebServerTest { + private static final String BIND_HOST = "localhost"; + private static final String PORT = "11021"; + private static final String MESSAGE = "hello"; + + private HttpServer server; + + @Before + public void setup() { + PluginSettings.instance().overrideProperty(PerformanceAnalyzerWebServer.WEBSERVICE_BIND_HOST_NAME, BIND_HOST); + PluginSettings.instance().overrideProperty(PerformanceAnalyzerWebServer.WEBSERVICE_PORT_CONF_NAME, PORT); + ClassLoader classLoader = getClass().getClassLoader(); + PluginSettings.instance().overrideProperty(CertificateUtils.CERTIFICATE_FILE_PATH, + Objects.requireNonNull(classLoader.getResource("tls/server/localhost.crt")).getFile()); + PluginSettings.instance().overrideProperty(CertificateUtils.PRIVATE_KEY_FILE_PATH, + Objects.requireNonNull(classLoader.getResource("tls/server/localhost.key")).getFile()); + } + + @After + public void tearDown() { + // Unset all SSL settings + PluginSettings.instance().overrideProperty(CertificateUtils.CERTIFICATE_FILE_PATH, ""); + PluginSettings.instance().overrideProperty(CertificateUtils.PRIVATE_KEY_FILE_PATH, ""); + PluginSettings.instance().overrideProperty(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH, ""); + PluginSettings.instance().overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, ""); + // Stop the server + if (server != null) { + server.stop(0); + } + } + + public void initializeServer(boolean useHttps) { + PluginSettings.instance().setHttpsEnabled(useHttps); + server = PerformanceAnalyzerWebServer.createInternalServer(PORT, BIND_HOST, useHttps); + Assert.assertNotNull(server); + server.setExecutor(Executors.newFixedThreadPool(1)); + // Setup basic /test endpoint. When the server receives any request on /test, it responds with "hello" + server.createContext("/test", exchange -> { + exchange.getRequestBody().close(); + exchange.sendResponseHeaders(HttpResponseStatus.OK.code(), 0); + OutputStream response = exchange.getResponseBody(); + response.write(MESSAGE.getBytes()); + response.close(); + }); + server.start(); + } + + /** + * Issues a basic HTTP GET request to $BIND_HOST:$PORT/test and verifies that the response says "hello" + */ + public void verifyRequest(String urlString) throws Exception { + // Build the request + URL url = new URL(urlString); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("Content-Type", "application/json"); + // Issue the request to the server + int status = connection.getResponseCode(); + BufferedReader streamReader; + if (status > 299) { + streamReader = new BufferedReader(new InputStreamReader(connection.getErrorStream())); + } else { + streamReader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + } + // Read response & verify contents + String inputLine; + StringBuilder content = new StringBuilder(); + while ((inputLine = streamReader.readLine()) != null) { + content.append(inputLine); + } + streamReader.close(); + Assert.assertEquals(MESSAGE, content.toString()); + } + + /** + * Issues a basic HTTPS GET request to $BIND_HOST:$PORT/test and verifies that the response says "hello" + */ + public void verifyHttpsRequest(String urlString, String clientCert, String clientKey, String clientCA) + throws Exception { + // Build the request + URL url = new URL(urlString); + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setSSLSocketFactory(createSSLSocketFactory(clientCert, clientKey, clientCA)); + // Issue the request to the server + int status = connection.getResponseCode(); + BufferedReader streamReader; + if (status > 299) { + streamReader = new BufferedReader(new InputStreamReader(connection.getErrorStream())); + } else { + streamReader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + } + // Read response & verify contents + String inputLine; + StringBuilder content = new StringBuilder(); + while ((inputLine = streamReader.readLine()) != null) { + content.append(inputLine); + } + streamReader.close(); + Assert.assertEquals(MESSAGE, content.toString()); + } + + /** + * testHttpServer verifies that any client can issue HTTP requests to the {@link PerformanceAnalyzerWebServer} + * when TLS is disabled + */ + @Test + public void testHttpServer() throws Exception { + // Start the HTTP server + initializeServer(false); + verifyRequest(String.format("http://%s:%s/test", BIND_HOST, PORT)); + } + + /** + * Verifies that the server accepts any client's requests when HTTPS is enabled but Auth is disabled. + */ + @Test + public void testNoAuthHttps() throws Exception { + PluginSettings.instance().overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, ""); + initializeServer(true); + verifyRequest(String.format("https://%s:%s/test", BIND_HOST, PORT)); + } + + /** + * Utility method to create an {@link SSLSocketFactory} + * @param clientCert Client identity certificate + * @param clientKey Private key for the client certificate + * @param clientCA Client certificate authority (used to verify server identity) + * Set this to null if you don't want to authenticate the server + * @return An {@link SSLSocketFactory} configured based on the given params + * @throws Exception If something goes wrong with SSL setup + */ + public SSLSocketFactory createSSLSocketFactory(String clientCert, String clientKey, @Nullable String clientCA) throws Exception { + ClassLoader classLoader = getClass().getClassLoader(); + PluginSettings instance = PluginSettings.instance(); + // Save previous settings + String certFile = instance.getSettingValue(CertificateUtils.CERTIFICATE_FILE_PATH); + String pKey = instance.getSettingValue(CertificateUtils.PRIVATE_KEY_FILE_PATH); + String rootCA = instance.getSettingValue(CertificateUtils.TRUSTED_CAS_FILE_PATH); + String prevClientCA = instance.getSettingValue(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH); + // Override client identity settings + instance.overrideProperty(CertificateUtils.CERTIFICATE_FILE_PATH, + Objects.requireNonNull(classLoader.getResource(clientCert)).getFile()); + instance.overrideProperty(CertificateUtils.PRIVATE_KEY_FILE_PATH, + Objects.requireNonNull(classLoader.getResource(clientKey)).getFile()); + instance.overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, ""); + if (clientCA != null) { + instance.getSettingValue(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH, clientCA); + } + // Setup SSLContext for the client + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + KeyStore ks = CertificateUtils.createKeyStore(); + KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); + kmf.init(ks, CertificateUtils.IN_MEMORY_PWD.toCharArray()); + sslContext.init(kmf.getKeyManagers(), CertificateUtils.getTrustManagers(false), null); + // Restore previous settings + instance.overrideProperty(CertificateUtils.CERTIFICATE_FILE_PATH, + certFile); + instance.overrideProperty(CertificateUtils.PRIVATE_KEY_FILE_PATH, + pKey); + instance.overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, rootCA); + if (prevClientCA == null) { + instance.overrideProperty(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH, ""); + } + return sslContext.getSocketFactory(); + } + + /** + * Verifies that the HTTPS server responds to an authenticated client's requests. + */ + @Test + public void testAuthenticatedClientGetsResponse() throws Exception { + ClassLoader classLoader = getClass().getClassLoader(); + PluginSettings.instance().overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, + Objects.requireNonNull(classLoader.getResource("tls/rootca/RootCA.pem")).getFile()); + initializeServer(true); + // Build the request + verifyHttpsRequest(String.format("https://%s:%s/test", BIND_HOST, PORT), + "tls/client/localhost.crt", "tls/client/localhost.key", "tls/rootca/RootCA.pem"); + } + + /** + * Verifies that the HTTPS server doesn't respond to an unauthenticated client's requests. + */ + @Test + public void testUnauthenticatedClientGetsRejected() throws Exception { + ClassLoader classLoader = getClass().getClassLoader(); + PluginSettings.instance().overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, + Objects.requireNonNull(classLoader.getResource("tls/rootca/RootCA.pem")).getFile()); + initializeServer(true); + // Build the request + try { + verifyHttpsRequest(String.format("https://%s:%s/test", BIND_HOST, PORT), + "tls/attacker/attack_cert.pem", "tls/attacker/attack_key.pem", + "tls/rootca/RootCA.pem"); + throw new AssertionError("An unauthenticated client was able to talk to the server"); + } catch (SSLException e) { // Unauthenticated client is rejected! + assert true; + } catch (Exception e) { // Treat unexpected errors as a failure + throw new AssertionError("Received unexpected error when making unauthed REST call to server", e); + } + } + + /** + * Verifies that a client properly authenticates a trusted server + */ + @Test + public void testClientAuth() throws Exception { + ClassLoader classLoader = getClass().getClassLoader(); + PluginSettings.instance().overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, + Objects.requireNonNull(classLoader.getResource("tls/rootca/RootCA.pem")).getFile()); + PluginSettings.instance().overrideProperty(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH, + Objects.requireNonNull(classLoader.getResource("tls/rootca/RootCA.pem")).getFile()); + initializeServer(true); + // Build the request + verifyHttpsRequest(String.format("https://%s:%s/test", BIND_HOST, PORT), + "tls/client/localhost.crt", "tls/client/localhost.key", "tls/rootca/RootCA.pem"); + } + + /** + * Verifies that a client doesn't authenticate a server with unknown credentials + */ + @Test + public void testThatClientRejectsUntrustedServer() { + ClassLoader classLoader = getClass().getClassLoader(); + PluginSettings.instance().overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, + Objects.requireNonNull(classLoader.getResource("tls/rootca/RootCA.pem")).getFile()); + // Setup client CA that doesn't trust the server's identity + PluginSettings.instance().overrideProperty(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH, + Objects.requireNonNull(classLoader.getResource("tls/rootca/root2ca.pem")).getFile()); + initializeServer(true); + // Build the request + try { + verifyHttpsRequest(String.format("https://%s:%s/test", BIND_HOST, PORT), + "tls/client/localhost.crt", "tls/client/localhost.key", "tls/rootca/root2ca.pem"); + throw new AssertionError("The client accepted a response from an untrusted server"); + } catch (SSLException e) { // Unauthenticated server is rejected! + assert true; + } catch (Exception e) { // Treat unexpected errors as a failure + throw new AssertionError("Received unexpected error in testThatClientRejectsUntrustedServer", e); + } + } +} From de2cb4db6329563d33ac2beff2708e4e59304dfc Mon Sep 17 00:00:00 2001 From: Sid Narayan Date: Thu, 16 Jul 2020 10:58:40 -0700 Subject: [PATCH 4/7] Fix merge issue with WireHopperTest --- .../performanceanalyzer/rca/net/WireHopperTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/rca/net/WireHopperTest.java b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/rca/net/WireHopperTest.java index a59f1849c..39f7290b0 100644 --- a/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/rca/net/WireHopperTest.java +++ b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/rca/net/WireHopperTest.java @@ -1,9 +1,6 @@ package com.amazon.opendistro.elasticsearch.performanceanalyzer.rca.net; -<<<<<<< HEAD import com.amazon.opendistro.elasticsearch.performanceanalyzer.AppContext; -======= ->>>>>>> d84454b... Add full mutual auth to gRPC client/server and augment tests import com.amazon.opendistro.elasticsearch.performanceanalyzer.grpc.FlowUnitMessage; import com.amazon.opendistro.elasticsearch.performanceanalyzer.net.GRPCConnectionManager; import com.amazon.opendistro.elasticsearch.performanceanalyzer.net.NetClient; From 28033f241ced960acb4a06af77f2c87335388ea6 Mon Sep 17 00:00:00 2001 From: Sid Narayan Date: Fri, 17 Jul 2020 13:42:58 -0700 Subject: [PATCH 5/7] Fixing up PerformanceAnalyzerWebServerTest --- .../PerformanceAnalyzerWebServerTest.java | 53 +++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServerTest.java b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServerTest.java index b7a066c68..2d0f818b7 100644 --- a/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServerTest.java +++ b/src/test/java/com/amazon/opendistro/elasticsearch/performanceanalyzer/PerformanceAnalyzerWebServerTest.java @@ -31,10 +31,31 @@ public class PerformanceAnalyzerWebServerTest { private static final String PORT = "11021"; private static final String MESSAGE = "hello"; + private String oldBindHost; + private String oldPort; + private String oldCertificateFilePath; + private String oldPrivateKeyFilePath; + private String oldTrustedCasFilePath; + private String oldClientCertificateFilePath; + private String oldClientPrivateKeyFilePath; + private String oldClientTrustedCasFilePath; + private boolean oldHttpsEnabled; + private HttpServer server; @Before public void setup() { + // Save old PluginSettings values + oldBindHost = PluginSettings.instance().getSettingValue(PerformanceAnalyzerWebServer.WEBSERVICE_BIND_HOST_NAME); + oldPort = PluginSettings.instance().getSettingValue(PerformanceAnalyzerWebServer.WEBSERVICE_PORT_CONF_NAME); + oldCertificateFilePath = PluginSettings.instance().getSettingValue(CertificateUtils.CERTIFICATE_FILE_PATH); + oldPrivateKeyFilePath = PluginSettings.instance().getSettingValue(CertificateUtils.PRIVATE_KEY_FILE_PATH); + oldTrustedCasFilePath = PluginSettings.instance().getSettingValue(CertificateUtils.TRUSTED_CAS_FILE_PATH); + oldClientCertificateFilePath = PluginSettings.instance().getSettingValue(CertificateUtils.CLIENT_CERTIFICATE_FILE_PATH); + oldClientPrivateKeyFilePath = PluginSettings.instance().getSettingValue(CertificateUtils.CLIENT_PRIVATE_KEY_FILE_PATH); + oldClientTrustedCasFilePath = PluginSettings.instance().getSettingValue(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH); + oldHttpsEnabled = PluginSettings.instance().getHttpsEnabled(); + // Update bind host, port, and server certs for the test PluginSettings.instance().overrideProperty(PerformanceAnalyzerWebServer.WEBSERVICE_BIND_HOST_NAME, BIND_HOST); PluginSettings.instance().overrideProperty(PerformanceAnalyzerWebServer.WEBSERVICE_PORT_CONF_NAME, PORT); ClassLoader classLoader = getClass().getClassLoader(); @@ -47,10 +68,32 @@ public void setup() { @After public void tearDown() { // Unset all SSL settings - PluginSettings.instance().overrideProperty(CertificateUtils.CERTIFICATE_FILE_PATH, ""); - PluginSettings.instance().overrideProperty(CertificateUtils.PRIVATE_KEY_FILE_PATH, ""); - PluginSettings.instance().overrideProperty(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH, ""); - PluginSettings.instance().overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, ""); + if (oldBindHost != null) { + PluginSettings.instance().overrideProperty(PerformanceAnalyzerWebServer.WEBSERVICE_BIND_HOST_NAME, oldBindHost); + } + if (oldPort != null) { + PluginSettings.instance().overrideProperty(PerformanceAnalyzerWebServer.WEBSERVICE_PORT_CONF_NAME, oldPort); + } + if (oldCertificateFilePath != null) { + PluginSettings.instance().overrideProperty(CertificateUtils.CERTIFICATE_FILE_PATH, oldCertificateFilePath); + } + if (oldPrivateKeyFilePath != null) { + PluginSettings.instance().overrideProperty(CertificateUtils.PRIVATE_KEY_FILE_PATH, oldPrivateKeyFilePath); + } + if (oldTrustedCasFilePath != null) { + PluginSettings.instance().overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, oldTrustedCasFilePath); + } + if (oldClientCertificateFilePath != null) { + PluginSettings.instance().overrideProperty(CertificateUtils.CLIENT_CERTIFICATE_FILE_PATH, oldClientCertificateFilePath); + } + if (oldClientPrivateKeyFilePath != null) { + PluginSettings.instance().overrideProperty(CertificateUtils.CLIENT_PRIVATE_KEY_FILE_PATH, oldClientPrivateKeyFilePath); + } + if (oldClientTrustedCasFilePath != null) { + PluginSettings.instance().overrideProperty(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH, oldClientTrustedCasFilePath); + } + PluginSettings.instance().setHttpsEnabled(oldHttpsEnabled); + // Stop the server if (server != null) { server.stop(0); @@ -202,6 +245,8 @@ public void testAuthenticatedClientGetsResponse() throws Exception { ClassLoader classLoader = getClass().getClassLoader(); PluginSettings.instance().overrideProperty(CertificateUtils.TRUSTED_CAS_FILE_PATH, Objects.requireNonNull(classLoader.getResource("tls/rootca/RootCA.pem")).getFile()); + PluginSettings.instance().overrideProperty(CertificateUtils.CLIENT_TRUSTED_CAS_FILE_PATH, + Objects.requireNonNull(classLoader.getResource("tls/rootca/RootCA.pem")).getFile()); initializeServer(true); // Build the request verifyHttpsRequest(String.format("https://%s:%s/test", BIND_HOST, PORT), From 8894129c2a17e1fa2cc1c6acdf395f82c1aebf21 Mon Sep 17 00:00:00 2001 From: Sid Narayan Date: Tue, 21 Jul 2020 11:02:42 -0700 Subject: [PATCH 6/7] Modify gradle.yml for testing --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 6d8cacf76..68923fcc4 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -32,7 +32,7 @@ jobs: java-version: 1.12 - name: Build RCA with Gradle working-directory: ./tmp/rca - run: ./gradlew build + run: ./gradlew build --info --stacktrace - name: Generate Jacoco coverage report working-directory: ./tmp/rca run: ./gradlew jacocoTestReport From dea63c469011a2236be81bbe071b0bde83ca6dd7 Mon Sep 17 00:00:00 2001 From: Sid Narayan Date: Tue, 21 Jul 2020 11:31:05 -0700 Subject: [PATCH 7/7] Remove info log flooding from testing gradle.yml --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 68923fcc4..9579881d0 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -32,7 +32,7 @@ jobs: java-version: 1.12 - name: Build RCA with Gradle working-directory: ./tmp/rca - run: ./gradlew build --info --stacktrace + run: ./gradlew build --stacktrace - name: Generate Jacoco coverage report working-directory: ./tmp/rca run: ./gradlew jacocoTestReport