diff --git a/distribution/examples/ssl/README.md b/distribution/examples/ssl/README.md
index d4f13bd419..a87b0bd4ce 100644
--- a/distribution/examples/ssl/README.md
+++ b/distribution/examples/ssl/README.md
@@ -1,6 +1,7 @@
# SSL/TLS Examples
-|Example|Description|
-|---|---|
-|[to-backend](to-backend)|How to secure communication from the API Gateway to a backend server.|
-|[api-with-tls](api-with-tls)|How to protect APIs deployed on the Gateway|
\ No newline at end of file
+| Example | Description |
+|--------------------------------------------|--------------------------------------------------------------------------|
+| [to-backend](to-backend) | How to secure communication from the API Gateway to a backend server. |
+| [api-with-tls-pkcs12](api-with-tls-pkcs12) | How to protect APIs deployed on the Gateway with PKCS12 TLS certificates |
+| [api-with-tls-pem](api-with-tls-pem) | How to protect APIs deployed on the Gateway with PEM TLS certificates |
\ No newline at end of file
diff --git a/distribution/examples/ssl/api-with-tls-pem/README.md b/distribution/examples/ssl/api-with-tls-pem/README.md
new file mode 100644
index 0000000000..4374bd2a50
--- /dev/null
+++ b/distribution/examples/ssl/api-with-tls-pem/README.md
@@ -0,0 +1,75 @@
+# Protecting APIs with SSL/TLS
+
+This example describes how to secure an API with SSL/TLS.
+
+
+## Running the Example
+
+1. Run `service-proxy.bat` or `service-proxy.sh`
+2. Open the following URL in your browser. Please do not forget to use `https` instead of `http`.
+
+ `https://localhost/`
+
+ You should get a warning that the certificate is not trustworthy. Here you can ignore the warning. In production, you should use your own certificates.
+
+3. You can also access the API using `curl`. The option `-k` suppresses the check for self-signed certificates.
+
+```
+curl -k -v https://localhost/
+```
+
+The output should look like this:
+
+```
+* Trying 127.0.0.1:443...
+* Connected to localhost (127.0.0.1) port 443 (#0)
+* ALPN, offering h2
+* ALPN, offering http/1.1
+* successfully set certificate verify locations:
+* CAfile: /etc/ssl/cert.pem
+* CApath: none
+* (304) (OUT), TLS handshake, Client hello (1):
+* (304) (IN), TLS handshake, Server hello (2):
+* (304) (IN), TLS handshake, Unknown (8):
+* (304) (IN), TLS handshake, Certificate (11):
+* (304) (IN), TLS handshake, CERT verify (15):
+* (304) (IN), TLS handshake, Finished (20):
+* (304) (OUT), TLS handshake, Finished (20):
+* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
+* ALPN, server did not agree to a protocol
+* Server certificate:
+* subject: CN=membrane
+* start date: Aug 5 10:41:09 2015 GMT
+* expire date: Aug 2 10:41:09 2025 GMT
+* issuer: CN=membrane
+* SSL certificate verify result: self signed certificate (18), continuing anyway.
+> GET / HTTP/1.1
+> Host: localhost
+>
+< HTTP/1.1 200 Ok
+< Content-Type: application/json
+<
+{
+"success" : true
+}
+```
+
+## Configuration
+
+Just put an SSL element into a proxy. See the [documentation](https://www.membrane-soa.org/service-proxy-doc/4.4/configuration/reference/ssl.htm).
+
+```xml
+
+
+
+
+
+
+
+
+
+```
+
+---
+See:
+- [ssl](https://membrane-soa.org/api-gateway-doc/current/configuration/reference/ssl.htm) reference
\ No newline at end of file
diff --git a/distribution/examples/ssl/api-with-tls-pem/membrane-key.pem b/distribution/examples/ssl/api-with-tls-pem/membrane-key.pem
new file mode 100644
index 0000000000..8a512cca98
--- /dev/null
+++ b/distribution/examples/ssl/api-with-tls-pem/membrane-key.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+zalYKwYqE5Kl/6y9wIwHl261JvurgbY=
+-----END PRIVATE KEY-----
diff --git a/distribution/examples/ssl/api-with-tls-pem/membrane.pem b/distribution/examples/ssl/api-with-tls-pem/membrane.pem
new file mode 100644
index 0000000000..943acbfa37
--- /dev/null
+++ b/distribution/examples/ssl/api-with-tls-pem/membrane.pem
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIExTCCAq2gAwIBAgIEd3OJmTANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDEwht
+ZW1icmFuZTAeFw0xNTA4MDUxMDQxMDlaFw0yNTA4MDIxMDQxMDlaMBMxETAPBgNV
+BAMTCG1lbWJyYW5lMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqSsz
+wxZRZp/Wa+qxQ2VDOnnCVPjBtoAlWkjgpyA6ytOPh7mnNPPcA1WSj3J0bfdpJR86
+SzsIuDaeFMB+HNI3i+eXWrzn0zGkD73NXfKP1d9HADcXxYvuOBqqdrFYDxW6AY7R
+CLu+Vf3/jdsfIoR4qPJyNhFiocedE2+5BEUURxb02ieyQi81cIQ+PFBVoxUwUn7t
+v7Rj8nXHWm6I/6CCLOZR4G28lSrzWQGTWDgC8iSr/c19ha1KAg/afiJ63I3bzbIY
+lMDK6TIKqLyK3IRhY8FVKg633IL3QxQkakuCssT4sMIGhsgHbVqbmVyfy8rOUGeq
+sJSHO2l2cTLHkt84dL1Vvf4BB9sHSpY5y3IymvCQ4/DsCa8082PO3TpFc7IqKDey
+IJohK1gFiUqtLB5LAbPghFMs2ceVBDkymSfsT5sIIdh9bAnocWkh4bKIzokmbUnZ
+/nx4wsqTpY2yWc9yCZyD+eP3jq4PDxrs3WKBIy2fwBGweyP+Qi0IdJght+x+HMMm
+S/YsXQEuW2RKzkwPOEt+AIvsKCKke3dcedq1msrDktf8xMa2U8/fcjwmiD1No/Kl
+55h8fNICuseaXHrA8nRBqxZO7WsOv13lq0OObRszY6JCeNSmFMTOVJt/WLLiLlbL
+NGF0GLjL2Vmdcg2v66aGLy+pwgwkZeiOoDwncHECAwEAAaMhMB8wHQYDVR0OBBYE
+FE8JEAm4kPj2CQLM+lJ9YwDsyICXMA0GCSqGSIb3DQEBCwUAA4ICAQAlaRpG0SNi
+wy+PR4yQOlwgCM6OTb5eG8UqIzaqU20odRJm3vtMupI3NPiENR5iZfnY9YPC3+HC
+vaTAWCcX02Ic0ad6rKVE4AGYgjDlW/Phe86Gykg/IyEwXMTEpcDENFIYE/3QltfZ
+b9DUbUsJtQbZxSIko0xvnvCqMwWU6kLqHUwigzxboDoXiIN4fGpUUzrOxqVj2HxF
+/0B8yDBEYk1iI+JQRH5O3KC9W8AgweUBKFjTprUKvcM3AA4zGTCsv8KBrAB9xdxW
+AXiBU6SOmSM0RWpLY/5NUnRnxRtSYH/xCk4gbiH4ZtT0FiGxpWD1VWp2WXHziPjT
+wwxMYb2q1bnZt4IbnFShVFQd/oR7fVZRyvmVBKRargoUwXxQYvK0e9ptWdZr959R
+TQsmTIpP5BLqWiX9tntvNPFAvz6BL7XP+oztrqob23JfI8HTH8wfj/RVR6472mQq
+JXXq38C/HGbfrK60SGuwjQ6nTHn6RiSQ+ynbRnr8S6QlzwNd1mGoGKdwckATxTsk
+zdqfCgCcE4u6L2JX4Hx4n2aoudsh/TzPovszxiNEVmQTADY4I+gs7BGBFN8lzv+K
+VFoJUfPX2srbV1wDXJHydJgHcOBXJrd8hD0AvnVUvuclt6qWle1cePbp1UNncx2B
+GGH5p3GIokdCasDetqjiGRPa3Xn1393qbw==
+-----END CERTIFICATE-----
diff --git a/distribution/examples/ssl/api-with-tls-pem/proxies.xml b/distribution/examples/ssl/api-with-tls-pem/proxies.xml
new file mode 100644
index 0000000000..fef3852abf
--- /dev/null
+++ b/distribution/examples/ssl/api-with-tls-pem/proxies.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { "success": true }
+
+
+
+
+
+
+
+
diff --git a/distribution/examples/ssl/api-with-tls/service-proxy.bat b/distribution/examples/ssl/api-with-tls-pem/service-proxy.bat
similarity index 100%
rename from distribution/examples/ssl/api-with-tls/service-proxy.bat
rename to distribution/examples/ssl/api-with-tls-pem/service-proxy.bat
diff --git a/distribution/examples/ssl/api-with-tls/service-proxy.sh b/distribution/examples/ssl/api-with-tls-pem/service-proxy.sh
similarity index 100%
rename from distribution/examples/ssl/api-with-tls/service-proxy.sh
rename to distribution/examples/ssl/api-with-tls-pem/service-proxy.sh
diff --git a/distribution/examples/ssl/api-with-tls/README.md b/distribution/examples/ssl/api-with-tls-pkcs12/README.md
similarity index 100%
rename from distribution/examples/ssl/api-with-tls/README.md
rename to distribution/examples/ssl/api-with-tls-pkcs12/README.md
diff --git a/distribution/examples/ssl/api-with-tls/proxies.xml b/distribution/examples/ssl/api-with-tls-pkcs12/proxies.xml
similarity index 100%
rename from distribution/examples/ssl/api-with-tls/proxies.xml
rename to distribution/examples/ssl/api-with-tls-pkcs12/proxies.xml
diff --git a/distribution/examples/ssl/api-with-tls-pkcs12/service-proxy.bat b/distribution/examples/ssl/api-with-tls-pkcs12/service-proxy.bat
new file mode 100644
index 0000000000..6742f74b41
--- /dev/null
+++ b/distribution/examples/ssl/api-with-tls-pkcs12/service-proxy.bat
@@ -0,0 +1,18 @@
+@echo off
+if not "%MEMBRANE_HOME%" == "" goto homeSet
+set "MEMBRANE_HOME=%cd%\..\..\.."
+echo "%MEMBRANE_HOME%"
+if exist "%MEMBRANE_HOME%\service-proxy.bat" goto homeOk
+
+:homeSet
+if exist "%MEMBRANE_HOME%\service-proxy.bat" goto homeOk
+echo Please set the MEMBRANE_HOME environment variable to point to
+echo the directory where you have extracted the Membrane software.
+exit
+
+:homeOk
+set "CLASSPATH=%MEMBRANE_HOME%"
+set "CLASSPATH=%MEMBRANE_HOME%/conf"
+set "CLASSPATH=%CLASSPATH%;%MEMBRANE_HOME%/starter.jar"
+echo Membrane Router running...
+java -classpath "%CLASSPATH%" com.predic8.membrane.core.Starter -c proxies.xml
\ No newline at end of file
diff --git a/distribution/examples/ssl/api-with-tls-pkcs12/service-proxy.sh b/distribution/examples/ssl/api-with-tls-pkcs12/service-proxy.sh
new file mode 100644
index 0000000000..2c6c5d0d66
--- /dev/null
+++ b/distribution/examples/ssl/api-with-tls-pkcs12/service-proxy.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+homeSet() {
+ echo "MEMBRANE_HOME variable is now set"
+ CLASSPATH="$MEMBRANE_HOME/conf"
+ CLASSPATH="$CLASSPATH:$MEMBRANE_HOME/starter.jar"
+ export CLASSPATH
+ echo Membrane Router running...
+ java -classpath "$CLASSPATH" com.predic8.membrane.core.Starter -c proxies.xml
+
+}
+
+terminate() {
+ echo "Starting of Membrane Router failed."
+ echo "Please execute this script from the appropriate subfolder of MEMBRANE_HOME/examples/"
+
+}
+
+homeNotSet() {
+ echo "MEMBRANE_HOME variable is not set"
+
+ if [ -f "`pwd`/../../../starter.jar" ]
+ then
+ export MEMBRANE_HOME="`pwd`/../../.."
+ homeSet
+ else
+ terminate
+ fi
+}
+
+
+if [ "$MEMBRANE_HOME" ]
+ then homeSet
+ else homeNotSet
+fi
+
diff --git a/distribution/src/test/java/com/predic8/membrane/examples/ExampleTestsWithInternet.java b/distribution/src/test/java/com/predic8/membrane/examples/ExampleTestsWithInternet.java
index 632fa4cb63..e2d35e028b 100644
--- a/distribution/src/test/java/com/predic8/membrane/examples/ExampleTestsWithInternet.java
+++ b/distribution/src/test/java/com/predic8/membrane/examples/ExampleTestsWithInternet.java
@@ -19,7 +19,8 @@
import com.predic8.membrane.examples.tests.*;
import com.predic8.membrane.examples.tests.loadbalancing.Loadbalancing4XmlSessionTest;
import com.predic8.membrane.examples.tests.openapi.APIProxyTest;
-import com.predic8.membrane.examples.tests.ssl.SSLServerApiWithTlsTest;
+import com.predic8.membrane.examples.tests.ssl.SSLServerApiWithTlsPemTest;
+import com.predic8.membrane.examples.tests.ssl.SSLServerApiWithTlsPkcs12Test;
import com.predic8.membrane.examples.tests.ssl.ToBackendTest;
import com.predic8.membrane.examples.tests.validation.FormValidationTest;
import com.predic8.membrane.examples.tests.versioning.RoutingTest;
@@ -43,7 +44,8 @@
LoggingTest.class,
LoginTest.class,
RewriterTest.class,
- SSLServerApiWithTlsTest.class,
+ SSLServerApiWithTlsPkcs12Test.class,
+ SSLServerApiWithTlsPemTest.class,
ToBackendTest.class,
ThrottleTest.class,
XSLTTest.class,
diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsPemTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsPemTest.java
new file mode 100644
index 0000000000..d7ee98b8dd
--- /dev/null
+++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsPemTest.java
@@ -0,0 +1,26 @@
+package com.predic8.membrane.examples.tests.ssl;
+
+import com.predic8.membrane.examples.util.DistributionExtractingTestcase;
+import com.predic8.membrane.examples.util.Process2;
+import org.junit.jupiter.api.Test;
+
+import static com.predic8.membrane.test.AssertUtils.*;
+
+public class SSLServerApiWithTlsPemTest extends DistributionExtractingTestcase {
+
+ @Override
+ protected String getExampleDirName() {
+ return "ssl/api-with-tls-pem";
+ }
+
+ @Test
+ void test() throws Exception {
+ replaceInFile2("proxies.xml", "443", "3023");
+
+ try(Process2 ignored = startServiceProxyScript()) {
+ trustAnyHTTPSServer(3023);
+ assertContains("success", getAndAssert200("https://localhost:3023"));
+ }
+ }
+
+}
diff --git a/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsTest.java b/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsPkcs12Test.java
similarity index 88%
rename from distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsTest.java
rename to distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsPkcs12Test.java
index 57b4525eea..66d6cd1593 100644
--- a/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsTest.java
+++ b/distribution/src/test/java/com/predic8/membrane/examples/tests/ssl/SSLServerApiWithTlsPkcs12Test.java
@@ -21,15 +21,15 @@
import static com.predic8.membrane.test.AssertUtils.*;
-public class SSLServerApiWithTlsTest extends DistributionExtractingTestcase {
+public class SSLServerApiWithTlsPkcs12Test extends DistributionExtractingTestcase {
@Override
protected String getExampleDirName() {
- return "ssl/api-with-tls";
+ return "ssl/api-with-tls-pkcs12";
}
@Test
- public void test() throws Exception {
+ void test() throws Exception {
replaceInFile2("proxies.xml", "443", "3023");
try(Process2 ignored = startServiceProxyScript()) {