diff --git a/.tool-versions b/.tool-versions
index 81a1df3..9fdaa96 100644
--- a/.tool-versions
+++ b/.tool-versions
@@ -1,2 +1,2 @@
erlang 21.3.8
-rebar 3.9.1
+ruby 2.6.3
diff --git a/.travis.yml b/.travis.yml
index cc8885a..494dbc1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,15 @@ language: erlang
otp_release:
- 21.3.8
+ruby:
+ - 2.6.3
+
+install:
+ - "rebar3 as test get-deps"
+ - "/bin/bash -l -c \"cd apps/epp_proxy/priv/test_backend_app && bundle install\""
+
script:
- - "rebar3 eunit"
- - "rebar3 ct --sys_config config/test.config --readable=false --cover"
+ - "/bin/bash -l -c \"cd apps/epp_proxy/priv/test_backend_app && bundle exec rackup --pid pidfile -D\""
+ - "rebar3 as test compile"
+ - "DEBUG=1 rebar3 ct --sys_config config/test.config --readable=false --cover --verbose=true"
- "rebar3 cover --verbose"
diff --git a/Dockerfile b/Dockerfile
index 7a9d07e..c4fcd8e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -54,6 +54,8 @@ WORKDIR /opt/erlang/epp_proxy
COPY .tool-versions ./
RUN asdf plugin-add erlang
RUN asdf install
+RUN asdf plugin-add ruby
+RUN asdf install
RUN curl https://s3.amazonaws.com/rebar3/rebar3 -o /rebar3
RUN mv /rebar3 /usr/local/bin
diff --git a/README.md b/README.md
index bb2f9e1..a83acaa 100644
--- a/README.md
+++ b/README.md
@@ -82,10 +82,10 @@ of Erlang property list.
| `epp_session_url` | `https://example.com/epp/session` | EppSessionRoot | HTTP address of the session endpoints including schema and port.
| `epp_command_url` | `https://example.com/epp/command` | EppCommandRoot | HTTP address of the command endpoints including schema and port.
| `epp_error_url` | `https://example.com/epp/error` | EppErrorRoot | HTTP address of the error endpoints including schema and port.
-| `cacertfile_path` | `/opt/ca/ca.crt.pem` | SSLCACertificateFile | Where is the client root CA located.
-| `certfile_path` | `/opt/ca/server.crt.pem` | SSLCertificateFile | Where is the server certificate located.
-| `keyfile_path` | `/opt/ca/server.key.pem` | SSLCertificateKeyFile | Where is the server key located.
-| `crlfile_path` | `/opt/ca/crl.pem` | SSLCARevocationFile | Where is the CRL file located.
+| `cacertfile_path` | `/opt/ca/ca.crt.pem` | SSLCACertificateFile | Where is the client root CA located. Can be inside apps/epp_proxy/priv or absolute path.
+| `certfile_path` | `/opt/ca/server.crt.pem` | SSLCertificateFile | Where is the server certificate located. Can be inside apps/epp_proxy/priv or absolute path.
+| `keyfile_path` | `/opt/ca/server.key.pem` | SSLCertificateKeyFile | Where is the server key located. Can be inside apps/epp_proxy/priv or absolute path.
+| `crlfile_path` | `/opt/ca/crl.pem` | SSLCARevocationFile | Where is the CRL file located. Can be inside apps/epp_proxy/priv or absolute path.
Migrating from mod_epp
@@ -100,6 +100,27 @@ Checklist of steps to perform if you want to migrate from mod_epp, but still use
5. If you do not feel comfortable using Erlang configuration file, you can use command line arguments and flags in format of `/epp_proxy/rel/bin/epp_proxy -epp_proxy tls_port 444`, where `-epp_proxy` is name of application,
followed by configuration parameter name and value.
+Testing
+----
+The application comes with test suite written with common_test. For integration
+tests, there is a small Roda application located in `apps/epp_proxy/priv/test_backend_app`.
+It has been written with Ruby 2.6.3.
+
+There is also a number of generated ssl certificates that are used only for testing. Those are
+valid until 2029 and they are located in `apps/epp_proxy/priv/test_ca`.
+
+You need to start the backend application before running the test suite. To start it as a deamon,
+from the root folder of the project, execute:
+
+```bash
+$ /bin/bash -l -c "cd apps/epp_proxy/priv/test_backend_app && bundle install"
+$ /bin/bash -l -c "cd apps/epp_proxy/priv/test_backend_app && bundle exec rackup --pid pidfile -D"
+```
+
+After you finish testing, you can stop the process by reading the stored pid:
+
+ $ kill `cat apps/epp_proxy/priv/test_backend_app/pidfile`
+
TODO
----
diff --git a/apps/epp_proxy/priv/test_backend_app/Gemfile b/apps/epp_proxy/priv/test_backend_app/Gemfile
new file mode 100644
index 0000000..8f5818a
--- /dev/null
+++ b/apps/epp_proxy/priv/test_backend_app/Gemfile
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "puma"
+gem "roda"
+gem "rack-unreloader"
+gem "tilt"
diff --git a/apps/epp_proxy/priv/test_backend_app/Gemfile.lock b/apps/epp_proxy/priv/test_backend_app/Gemfile.lock
new file mode 100644
index 0000000..082e166
--- /dev/null
+++ b/apps/epp_proxy/priv/test_backend_app/Gemfile.lock
@@ -0,0 +1,23 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ nio4r (2.4.0)
+ puma (4.0.0)
+ nio4r (~> 2.0)
+ rack (2.0.7)
+ rack-unreloader (1.7.0)
+ roda (3.21.0)
+ rack
+ tilt (2.0.9)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ puma
+ rack-unreloader
+ roda
+ tilt
+
+BUNDLED WITH
+ 1.17.2
diff --git a/apps/epp_proxy/priv/test_backend_app/config.ru b/apps/epp_proxy/priv/test_backend_app/config.ru
new file mode 100644
index 0000000..7de4012
--- /dev/null
+++ b/apps/epp_proxy/priv/test_backend_app/config.ru
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require "rack/unreloader"
+
+Unreloader = Rack::Unreloader.new() { EppServer }
+Unreloader.require("epp_server.rb") { "EppServer" }
+
+run(Unreloader)
diff --git a/apps/epp_proxy/priv/test_backend_app/epp_server.rb b/apps/epp_proxy/priv/test_backend_app/epp_server.rb
new file mode 100644
index 0000000..d1b6e4a
--- /dev/null
+++ b/apps/epp_proxy/priv/test_backend_app/epp_server.rb
@@ -0,0 +1,37 @@
+require 'roda'
+
+class EppServer < Roda
+ plugin :render
+
+ route do |r|
+ response['Content-Type'] = 'application/xml'
+
+ r.on "session" do
+ r.get "hello" do
+ render("session/hello")
+ end
+
+ r.post "login" do
+ render("session/login")
+ end
+
+ r.post "logout" do
+ render("session/logout")
+ end
+ end
+
+ r.on "command" do
+ r.post "poll" do
+ render("command/poll")
+ end
+
+ end
+
+ r.get "error" do
+ @code = r.params['code']
+ @msg = r.params['msg']
+
+ render("error")
+ end
+ end
+end
diff --git a/apps/epp_proxy/priv/test_backend_app/views/command/poll.erb b/apps/epp_proxy/priv/test_backend_app/views/command/poll.erb
new file mode 100644
index 0000000..001c25f
--- /dev/null
+++ b/apps/epp_proxy/priv/test_backend_app/views/command/poll.erb
@@ -0,0 +1,12 @@
+
+
+
+
+ Command completed successfully; no messages
+
+
+ foo bar baz
+ ccReg-8688842425
+
+
+
diff --git a/apps/epp_proxy/priv/test_backend_app/views/error.erb b/apps/epp_proxy/priv/test_backend_app/views/error.erb
new file mode 100644
index 0000000..60c11ab
--- /dev/null
+++ b/apps/epp_proxy/priv/test_backend_app/views/error.erb
@@ -0,0 +1,13 @@
+
+
+
+
+
+ <%= @msg %>
+
+
+
+ ccReg-4018856528
+
+
+
diff --git a/apps/epp_proxy/priv/test_backend_app/views/session/hello.erb b/apps/epp_proxy/priv/test_backend_app/views/session/hello.erb
new file mode 100644
index 0000000..02373ba
--- /dev/null
+++ b/apps/epp_proxy/priv/test_backend_app/views/session/hello.erb
@@ -0,0 +1,36 @@
+
+
+
+ EPP server (EIS)
+ 2019-07-11T09:35:29Z
+
+ 1.0
+ en
+ https://epp.tld.ee/schema/domain-eis-1.0.xsd
+ https://epp.tld.ee/schema/contact-ee-1.1.xsd
+ urn:ietf:params:xml:ns:host-1.0
+ urn:ietf:params:xml:ns:keyrelay-1.0
+
+ urn:ietf:params:xml:ns:secDNS-1.1
+ https://epp.tld.ee/schema/eis-1.0.xsd
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/epp_proxy/priv/test_backend_app/views/session/login.erb b/apps/epp_proxy/priv/test_backend_app/views/session/login.erb
new file mode 100644
index 0000000..fb228cb
--- /dev/null
+++ b/apps/epp_proxy/priv/test_backend_app/views/session/login.erb
@@ -0,0 +1,11 @@
+
+
+
+
+ Command completed successfully
+
+
+ ccReg-5886259930
+
+
+
diff --git a/apps/epp_proxy/priv/test_backend_app/views/session/logout.erb b/apps/epp_proxy/priv/test_backend_app/views/session/logout.erb
new file mode 100644
index 0000000..cb5dccc
--- /dev/null
+++ b/apps/epp_proxy/priv/test_backend_app/views/session/logout.erb
@@ -0,0 +1,11 @@
+
+
+
+
+ Command completed successfully; ending session
+
+
+ ccReg-3475281342
+
+
+
diff --git a/apps/epp_proxy/priv/test_ca/certs/apache.crt b/apps/epp_proxy/priv/test_ca/certs/apache.crt
new file mode 100644
index 0000000..60874ec
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/certs/apache.crt
@@ -0,0 +1,31 @@
+-----BEGIN CERTIFICATE-----
+MIIFPTCCAyWgAwIBAgIJAIcovwhumxzlMA0GCSqGSIb3DQEBCwUAMIGVMQswCQYD
+VQQGEwJFRTERMA8GA1UECAwISGFyanVtYWExEDAOBgNVBAcMB1RhbGxpbm4xIzAh
+BgNVBAoMGkVlc3RpIEludGVybmV0aSBTaWh0YXN1dHVzMRowGAYDVQQDDBFlcHBf
+cHJveHkgdGVzdCBjYTEgMB4GCSqGSIb3DQEJARYRaGVsbG9AaW50ZXJuZXQuZWUw
+HhcNMTkwNzExMTM0MTQyWhcNMjkwNzA4MTM0MTQyWjCBkjELMAkGA1UEBhMCRUUx
+ETAPBgNVBAgMCEhhcmp1bWFhMRAwDgYDVQQHDAdUYWxsaW5uMRkwFwYDVQQKDBBF
+ZXN0aUludGVybmV0aVNBMRAwDgYDVQQLDAdBcmVuZHVzMSAwHgYJKoZIhvcNAQkB
+FhFoZWxsb0BpbnRlcm5ldC5lZTEPMA0GA1UEAwwGKi50ZXN0MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqoZLIpFR96bIwxk9GvzTeTnsPMpTJ/fI+SWX
+Qh5UflAIG74Hl+aBW+k8jIZ+VxwXwn7uwY7fdtemu9CzCqYK4pqZg168IEC00Vne
+C7gifaMWgBd/DNiv3FafNpTihdMZrZi8xLJIuNw8XLaDebGQrrfOWw1Cewum/MJa
+IFnIBttsBq+jFwKtAJ9RgNg6Ul2xOGpqtrLmU21HmIzm9hqbeaWINIX1QDVC2ZWd
+gVXgoEID/RLUc8A+riVUdaKzG9kCrtuzGO8PhXoF5BJWtsrAcYFQev3jVRKplSFh
+whijh2MY14qA21wseNMF7+fSCjhuvEomxpzNQSH0UADHW0p17wIDAQABo4GQMIGN
+MB8GA1UdIwQYMBaAFP135kpzvaU8ZbO5z7UVlVkIZGgQMAkGA1UdEwQCMAAwCwYD
+VR0PBAQDAgTwMFIGA1UdEQRLMEmCBHRlc3SCDXJlZ2lzdHJ5LnRlc3SCDGF1Y3Rp
+b24udGVzdIIPcmVzdC13aG9pcy50ZXN0gghlcHAudGVzdIIJcmVwcC50ZXN0MA0G
+CSqGSIb3DQEBCwUAA4ICAQBvi2Uy0iYuMWyS8hdZOvp3jdTqq/HI0JfFlT5YUwv0
+ezkjyBLw4A9+dMvy8HELyzhUeHd09nmB+/TJ9RWQBCgIcHilQ5nFXd0h5hNX+rtC
+kdDd8x9QRBHN82EFIwXQ6/FXLz92DZ4Z5ZQOEGM5AFi02GwFI9fhvZg2vGL3aD5Q
+2V4OPulECPgVR/U6kbXQz6/Rg9DXbbMgHukLuglFIj3+dtvepp6DXYNZz6AhM64E
+4/K/55yKKFKRvOzw+K+CIX3qytTvYDutDfCA593Dp2BXjMb9CVGN+nKZr9sVrDlt
+qR9ya04MK/Ti0Nk8NN3ZHRASUJU3xk06/KriOj5tvVRgcqn/Jfh1JhOSULrKdx8B
+4u53pRn1SCCCWiXvUAnJL3TAi6TaXKoFN6GxQZMBCl0U0wQ2XIYOCzBs74YkWqOM
+1Mgq2dcX3m8GlZWzkKExc1wM+MlUmk0et8vJIgrTcIQGw0fn/TdvWy+iLNNYp0P9
+YkB0rGqN0KwkAHhKt+BrRtRHkEOxQcumgvLDkwTZpAJsbrPDMOajbzwpgwSQOE1i
+Z+RuZQktmZVJNJ3NPwloHZBolMnb9zDg3k3GP9+Lh1k6pDiFCf1A1QZKl52h3+kG
+IDFPCaoYexOLN86ebApMWglxPPvPnfQpi9F+PWYjR02DbgSWR+/EGxygOnzjOYmS
+gQ==
+-----END CERTIFICATE-----
diff --git a/apps/epp_proxy/priv/test_ca/certs/ca.crt.pem b/apps/epp_proxy/priv/test_ca/certs/ca.crt.pem
new file mode 100644
index 0000000..f03e09f
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/certs/ca.crt.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGDDCCA/SgAwIBAgIJAKaLNUIy97o1MA0GCSqGSIb3DQEBCwUAMIGVMQswCQYD
+VQQGEwJFRTERMA8GA1UECAwISGFyanVtYWExEDAOBgNVBAcMB1RhbGxpbm4xIzAh
+BgNVBAoMGkVlc3RpIEludGVybmV0aSBTaWh0YXN1dHVzMRowGAYDVQQDDBFlcHBf
+cHJveHkgdGVzdCBjYTEgMB4GCSqGSIb3DQEJARYRaGVsbG9AaW50ZXJuZXQuZWUw
+HhcNMTkwNzExMTMwMDEzWhcNMjAwNzEwMTMwMDEzWjCBlTELMAkGA1UEBhMCRUUx
+ETAPBgNVBAgMCEhhcmp1bWFhMRAwDgYDVQQHDAdUYWxsaW5uMSMwIQYDVQQKDBpF
+ZXN0aSBJbnRlcm5ldGkgU2lodGFzdXR1czEaMBgGA1UEAwwRZXBwX3Byb3h5IHRl
+c3QgY2ExIDAeBgkqhkiG9w0BCQEWEWhlbGxvQGludGVybmV0LmVlMIICIjANBgkq
+hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0PBwqZUeXZaR3mk3VTm7S78Xs4WDCfyi
+RocHDU7cWhrBvFD5ZXzmbUJPPJHmljYAOLWLEyMzw0bvYVz2FSOCkBerxGFA4T17
+RhjDEAmMMWiBAoFj6tNmxj3bq7nZfwaOY6KIxGiZcqx4usOQ3tQ+cxvrqzFVyX24
+KScmx4l2HlmJu2boF8/C4LSYvGPys+2WKXlLr73gL+cmM7Z2Y+mNgURCKT9ODpFp
+VdX9iTpmnF0UFmYq/cN8QFSNv0ErsMFDZWxAnDoy6gZzsUz3ZnznOdjB96PFV9aA
+Rm5BYr7jMhu7rJPOyQNd9SfD6QhlyCSjd68p6nMFvYLG5lL5QxJSTotr3VuH1uqJ
+kfFwlMPJZAj/SmFUnoIvWGCyujqx6ajVX8zBvmcalSp35LyDDCnlohorUuP9TNrI
+U+k/Ap6vxfxSSIOPhq6BoFxMYASp8jo+8HdFOWce5krQh/h3vvEhu015yEXH4Vgb
+6lL+nvUex35He1IQFERvRSj5IB1Yw6HpwYb7LIfjXYsfas3FuSxXz9Geb23dybYd
+2MlmKeGvTyjM60BNW2ZKKQ00KgnqR62bPALbDZ/AnkzxnLd7NLVqKiSBzOOkZfaO
+V7hDD78VzSklA2cSV1qaBPHUW4AgQkmDJIF/1H/K9nN/F6OWKSJ0Ug3XGwDjY3Ry
+X//K+E1UNWMCAwEAAaNdMFswHQYDVR0OBBYEFP135kpzvaU8ZbO5z7UVlVkIZGgQ
+MB8GA1UdIwQYMBaAFP135kpzvaU8ZbO5z7UVlVkIZGgQMAwGA1UdEwQFMAMBAf8w
+CwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQDF3s887Qj2eLeJln1Z/Nem
+ZR2tj0PvYEHEYKq9R8N8IM1ooZt475MgyYo7XDPcuG3MMaGY9WdjqoXlWSM7T518
+U9ajFLqwNEnlfjZ33SdVDskfoRsKiDKUlvTNngn19KtAp3SBmQS6fgghlgha3tb+
+W1fOgzCRwaVG4XcQfR+wijSSovFOp+5CY/FL6XUwtFCz4ZwnHgXciG91SjhEPB+J
+P8iHFr4f0qV4kKv0hPfjQ7tneeho0AzI4BXOgbRJmur6+SP/gmsgBeKr1sUHuD+d
+nIAlz4T2reV8FujcW3u8yT4PFIhi0mdnXKC6xKDFlmD9AQa7eUO1DHJiSZ7zAsLS
+drsqMu3GhM70Uw0Oqv2aInv8N4vwF6CJ6p/wEUXTVjkjH3U/ZzuOGcl1/5sAao0r
+APwRazSMcqrjc+JicpFZ6NGTwTs0G6KD0dqhhqoyoZzB/1UDR2cG5SsgSTqBUeGb
+0VMW4EYU+DG1HV+OdNrFA0RgDn5o0VF3LxwAs5ErItlojFPeBDYMJvPGsMEarNHN
+03JeeEK081gzLJQzFPQV1n6kE6CiGGTx4X3ptUtvvQBD/u6KNUwN5b6p5jOQBEdZ
+F4PJOVZePI/dBHr98/jlcHfCOmySc+7uzPhB86OtdF/yYabImpvQ0cypZkXwzL6l
+VgOJJfHQrIhSmCRVxCEJoQ==
+-----END CERTIFICATE-----
diff --git a/apps/epp_proxy/priv/test_ca/certs/ca.srl b/apps/epp_proxy/priv/test_ca/certs/ca.srl
new file mode 100644
index 0000000..7c1fd1b
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/certs/ca.srl
@@ -0,0 +1 @@
+8728BF086E9B1CE5
diff --git a/apps/epp_proxy/priv/test_ca/certs/webclient.crt.pem b/apps/epp_proxy/priv/test_ca/certs/webclient.crt.pem
new file mode 100644
index 0000000..cc960f5
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/certs/webclient.crt.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIGIjCCBAqgAwIBAgICEAcwDQYJKoZIhvcNAQELBQAwgZUxCzAJBgNVBAYTAkVF
+MREwDwYDVQQIDAhIYXJqdW1hYTEQMA4GA1UEBwwHVGFsbGlubjEjMCEGA1UECgwa
+RWVzdGkgSW50ZXJuZXRpIFNpaHRhc3V0dXMxGjAYBgNVBAMMEWVwcF9wcm94eSB0
+ZXN0IGNhMSAwHgYJKoZIhvcNAQkBFhFoZWxsb0BpbnRlcm5ldC5lZTAeFw0xOTA3
+MTExMzQxMDNaFw0yOTA3MDgxMzQxMDNaMIGFMQswCQYDVQQGEwJFRTERMA8GA1UE
+CAwISGFyanVtYWExIzAhBgNVBAoMGkVlc3RpIEludGVybmV0aSBTaWh0YXN1dHVz
+MRwwGgYDVQQDDBNsb2NhbGhvc3Qgd2ViY2xpZW50MSAwHgYJKoZIhvcNAQkBFhFo
+ZWxsb0BpbnRlcm5ldC5lZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AJ69aNDgwI4bFSDoMB6WEqL7/zcMBQnVPj3fYEBLYxpo9TEvFlkybgs2JncC5tgW
+biIoE7fE/ObNt0bLnY/IKdRnMmOltnttbcAO/WmKQE2PPv/VVfGrfHi68IuVEN2b
+E9YZ7GNp3cudKl4dpGW6VQkyP9Kp2Gxa3a0+2WecSNrESNXzTWre9MRI0upjIwCD
+HZ9ip/4F6Lg0Z4zBa7rKXqRqR7rw8YM2LN9UvmBL6feCQdKExaJqAx0bp6ychwti
+s78tOVX47pdQxL3rRPmBuXjWMjpbSAPEdL/LhAh7LpD4EJk50s1K6qq8EZPCagta
+Crws2qu89MPD8MekIiM3Ygm+ouZbqySBjCHlSlVbLQ2aCpMHlSdaPWskYSJ1IXlb
+lqhdgIrUehfuthR/znFZ/L6Fkqzg0MauaF7aqsrg0UAuBrZ6TOxBZLCuftPnY8qN
+BUyEveKGI5Rij3JMaLuT9samBScbrOncWngFIsDrCUqpGNzkEIZQgECJtcKz1UW0
+RaXOibO3KQ8PMAlwGTQFqwg6VBdH1YxmnAlunvgh/biBV6vZWLeZWpN3bx1o6FcN
+30W44WQ7Hqrs58Qqq9pdlW4252iQ9XpVYP1Ps7adv9BoNX9pTxH7THUEo1y/wehh
+DcQ1FnuFAMeWGU2FpBwxBasiJTBCoWQp8zMlI+4ws7V7AgMBAAGjgYkwgYYwCQYD
+VR0TBAIwADALBgNVHQ8EBAMCBeAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2Vu
+ZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBT7jUyzkYvC9H8s8kS7lr4jp4C9
+DjAfBgNVHSMEGDAWgBT9d+ZKc72lPGWzuc+1FZVZCGRoEDANBgkqhkiG9w0BAQsF
+AAOCAgEAwNXs6lvOexo/pmSzU1fqokxfxHbOSqxhH1R7x0+sfY6YufJmp2yhvb1j
+Kbw/YzVhxDA4UpcwS3Cm703tb4K9Lby6DWOlaIniqEIyctldNbK8ZUPLOMCDe9mx
+G4U366KtVqWt/rC7CZmDSIz8I0tXzIrMOM3xY51PY62xz8IDIILC0xkzUz30Set2
+IjwWQzzfakrE+xz9rdCX//BP3kyr3+HP9Aq7DJ7mxnzlV0YmdT6kyhVTSc3Im4eG
+GbtrFqLbb1AeX3tBpT/2gUuxRgYVVpY3oqVLBQMuUil1LnBH6JyO61KAgAYijwwP
+gOwmp7mE9QuIpXY8Sm2+Cre4MXBqdzybJ5syyI985bp9BT0EEXuCO2cKNzUMEOub
+FuNkIezW4FyApU5wdA6kn7mwELAk01hAQirh7+FQxGXAfZfTs4Bwg3F43t7KSdbO
+ayjKLYg7sS+yAMsSxUMkji0fKdal6Vq1qViKSOHV/85Ou2xa9pYFpv8jypJ2igF8
+LYREauAQiSMQTi5u2/pUqmPEUpC9mUjgRmoDnlHoKHM+Ma88NdpPHHdrFH4pEPVZ
+ul9kwg3yLbfeO1UECtdv79j5j6yS4OUxnNErqdvoFYlQfc8DOHgB853Ym0iOBEQ/
+KDNiD159/hn20mgmc5LMwY0+aPOanJpZ30AHOA9/yLpIE0/VkN0=
+-----END CERTIFICATE-----
diff --git a/apps/epp_proxy/priv/test_ca/crl/crl.pem b/apps/epp_proxy/priv/test_ca/crl/crl.pem
new file mode 100644
index 0000000..7efffce
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/crl/crl.pem
@@ -0,0 +1,21 @@
+-----BEGIN X509 CRL-----
+MIIDfTCCAWUCAQEwDQYJKoZIhvcNAQELBQAwgZUxCzAJBgNVBAYTAkVFMREwDwYD
+VQQIDAhIYXJqdW1hYTEQMA4GA1UEBwwHVGFsbGlubjEjMCEGA1UECgwaRWVzdGkg
+SW50ZXJuZXRpIFNpaHRhc3V0dXMxGjAYBgNVBAMMEWVwcF9wcm94eSB0ZXN0IGNh
+MSAwHgYJKoZIhvcNAQkBFhFoZWxsb0BpbnRlcm5ldC5lZRcNMTkwNzExMTMxMTM0
+WhcNMjkwNzA4MTMxMTM0WjBpMBMCAhACFw0xOTA1MjkwNjM5MTJaMBMCAhADFw0x
+OTA1MjkwODQxMDJaMBMCAhAEFw0xOTA1MzExMTI0NTJaMBMCAhAFFw0xOTA1MzEx
+MTQyMjJaMBMCAhAGFw0xOTA1MzExMjQzNDlaoDAwLjAfBgNVHSMEGDAWgBT9d+ZK
+c72lPGWzuc+1FZVZCGRoEDALBgNVHRQEBAICEAgwDQYJKoZIhvcNAQELBQADggIB
+ACv4opvBcQoCEkiKhVlr5bSq0vAVaTu1FloKTay0xsgDGSqQDnPR/B7ELSyoYo2A
+iBuSrQREyvXOtZhlQyTHwCDnAjpgGDGdRbRJAhhbWA9/MC4oqyJLjOFxLspX2S7E
+Fq4F/DbUZaW8niGGCcAUf8QnilaJLEhUT7qIJW2DpyFLd/1qLK81PBO8VW4fbKQI
+z2LsrA3NijW+W192LMvHLKnE47ifW1PLM0dJimkVNrkS42ACuwnCOLfLJsIg9aRe
+QsI1CY+L1F2tROedUFo6noffnm+SyMapna4SEXlQTaA1kfLtLOGVhXpBAgcewIsY
+DQQCTn4oEAhZroZMPYJXYXC/pNSMUEBifXR2akO7eE5kLBgf11ZfhuEUqperviiJ
+yLNzoakh3eMazIo5Qr8ZinMWP8HHZJI8GmOvJtVKAvOFmXkVm++Cnl/Ovp8skrTD
+AibySMZSTgoAc+ynZYI5q6HZxJWXN/PQ/++hFyOW9aG1DTLGpV6rO+O4zNldmUIO
+DTu+dUmKNamp1a6GcaY5xLSQTfV8InetxwF+gazvcmtEnqagH64EseSz4RZQLtRc
+kAZLho1rPE35Ok/2eswMvQ9hOkQ7tX9dO35HYoHoVKUzdiBaPP3PCDeCC/Ei5C2n
+Z1rfbtOFwF/36qyz7o+YqHaWHVc9W/koRjtrmXA1soJ2
+-----END X509 CRL-----
diff --git a/apps/epp_proxy/priv/test_ca/crlnumber b/apps/epp_proxy/priv/test_ca/crlnumber
new file mode 100644
index 0000000..83b33d2
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/crlnumber
@@ -0,0 +1 @@
+1000
diff --git a/apps/epp_proxy/priv/test_ca/csrs/webclient.csr.pem b/apps/epp_proxy/priv/test_ca/csrs/webclient.csr.pem
new file mode 100644
index 0000000..49dcbe3
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/csrs/webclient.csr.pem
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIE3TCCAsUCAQAwgZcxCzAJBgNVBAYTAkVFMREwDwYDVQQIDAhIYXJqdW1hYTEQ
+MA4GA1UEBwwHVGFsbGlubjEjMCEGA1UECgwaRWVzdGkgSW50ZXJuZXRpIFNpaHRh
+c3V0dXMxHDAaBgNVBAMME2xvY2FsaG9zdCB3ZWJjbGllbnQxIDAeBgkqhkiG9w0B
+CQEWEWhlbGxvQGludGVybmV0LmVlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAnr1o0ODAjhsVIOgwHpYSovv/NwwFCdU+Pd9gQEtjGmj1MS8WWTJuCzYm
+dwLm2BZuIigTt8T85s23Rsudj8gp1GcyY6W2e21twA79aYpATY8+/9VV8at8eLrw
+i5UQ3ZsT1hnsY2ndy50qXh2kZbpVCTI/0qnYbFrdrT7ZZ5xI2sRI1fNNat70xEjS
+6mMjAIMdn2Kn/gXouDRnjMFruspepGpHuvDxgzYs31S+YEvp94JB0oTFomoDHRun
+rJyHC2Kzvy05Vfjul1DEvetE+YG5eNYyOltIA8R0v8uECHsukPgQmTnSzUrqqrwR
+k8JqC1oKvCzaq7z0w8Pwx6QiIzdiCb6i5lurJIGMIeVKVVstDZoKkweVJ1o9ayRh
+InUheVuWqF2AitR6F+62FH/OcVn8voWSrODQxq5oXtqqyuDRQC4GtnpM7EFksK5+
+0+djyo0FTIS94oYjlGKPckxou5P2xqYFJxus6dxaeAUiwOsJSqkY3OQQhlCAQIm1
+wrPVRbRFpc6Js7cpDw8wCXAZNAWrCDpUF0fVjGacCW6e+CH9uIFXq9lYt5lak3dv
+HWjoVw3fRbjhZDsequznxCqr2l2VbjbnaJD1elVg/U+ztp2/0Gg1f2lPEftMdQSj
+XL/B6GENxDUWe4UAx5YZTYWkHDEFqyIlMEKhZCnzMyUj7jCztXsCAwEAAaAAMA0G
+CSqGSIb3DQEBCwUAA4ICAQBWZgoSw7JO5gaIziRqRqXPzxN+TLHps4ryYKyO31+F
+VvoC7mAhdUbVSEHEXRTQckIdlwnaYPAIeoWCQCZHDcvA3BbW5TC/KLoPCsJH/zhI
+OeoB2C3QDAifplNjZ/Una4tMyN4jOXDiwW2UKoCtjraXAyLI89q48k5e06xnTYpc
+zX23F/mZhheZoeaidqbdRtPemGDQg9KRp99f7ER10OqP5Les7TwVa9xZlyAg/ef8
+40sRVH+pPkYY14AccsPrGMr6dSphcPy1koQUp2ov6aUMJbDVs+sinoqBc8ixicLq
+AX+lLs/CZmf0LBjAdzg1P29R/tPS76zPv6bRUpp49H9sd/fJONR+6lgq3tSkvd+s
+MM9OK7zbs+1GUIiYEbCTdYe7UqSh6wfWfg7qrncWlLWFz+P6Yp7N+92hisDuDwTM
+en8fOG5029aqnq+SodYnfD8Idh+9YTza8S1qKi3u4Vf7PKsEr/0byAnm1rybOxyI
+PGGQ+H6kRQ+gCgZlD0NpVoOZvD3qriN0vxGSQUnsceMYAvRaf7v8i2FcaqsK6oK8
+YFnjpgxeY7Oowv5zEbeXJiqxLJBMj0AJYg8TUxkQofWKyZBEcxzeTzCQbkc4Dr0E
+6hqAqbAss6trTJXWOh4Ir3izT9Zb4oT+4i6u1NVxqou6dAWlqeh98dPBmh98Uy5q
+Ww==
+-----END CERTIFICATE REQUEST-----
diff --git a/apps/epp_proxy/priv/test_ca/generate_certificates.sh b/apps/epp_proxy/priv/test_ca/generate_certificates.sh
new file mode 100755
index 0000000..29625e0
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/generate_certificates.sh
@@ -0,0 +1,9 @@
+# !/bin/sh
+# Use localhost as common name.
+openssl genrsa -out private/webclient.key.pem 4096
+openssl req -sha256 -config openssl.cnf -new -days 3650 -key private/webclient.key.pem -out csrs/webclient.csr.pem
+openssl ca -config openssl.cnf -keyfile private/ca.key.pem -cert certs/ca.crt.pem -extensions usr_cert -notext -md sha256 -in csrs/webclient.csr.pem -days 3650 -out certs/webclient.crt.pem
+openssl ca -keyfile private/ca.key.pem -cert certs/ca.crt.pem -gencrl -out crl/crl.pem
+openssl ca -config openssl.cnf -keyfile private/ca.key.pem -cert certs/ca.crt.pem -crldays 3650 -gencrl -out crl/crl.pem
+openssl req -config openssl.cnf -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout private/apache.key -config server.csr.cnf
+openssl x509 -req -in server.csr -CA certs/ca.crt.pem -CAkey private/ca.key.pem -CAcreateserial -out certs/apache.crt -days 3650 -sha256 -extfile v3.ext
diff --git a/apps/epp_proxy/priv/test_ca/index.txt b/apps/epp_proxy/priv/test_ca/index.txt
new file mode 100644
index 0000000..e69de29
diff --git a/apps/epp_proxy/priv/test_ca/openssl.cnf b/apps/epp_proxy/priv/test_ca/openssl.cnf
new file mode 100644
index 0000000..0397357
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/openssl.cnf
@@ -0,0 +1,348 @@
+#
+# OpenSSL example configuration file.
+# This is mostly being used for generation of certificate requests.
+#
+
+# This definition stops the following lines choking if HOME isn't
+# defined.
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+# Extra OBJECT IDENTIFIER info:
+#oid_file = $ENV::HOME/.oid
+oid_section = new_oids
+
+# To use this configuration file with the "-extfile" option of the
+# "openssl x509" utility, name here the section containing the
+# X.509v3 extensions to use:
+# extensions =
+# (Alternatively, use a configuration file that has only
+# X.509v3 extensions in its main [= default] section.)
+
+[ new_oids ]
+
+# We can add new OIDs in here for use by 'ca', 'req' and 'ts'.
+# Add a simple OID like this:
+# testoid1=1.2.3.4
+# Or use config file substitution like this:
+# testoid2=${testoid1}.5.6
+
+# Policies used by the TSA examples.
+tsa_policy1 = 1.2.3.4.1
+tsa_policy2 = 1.2.3.4.5.6
+tsa_policy3 = 1.2.3.4.5.7
+
+####################################################################
+[ ca ]
+default_ca = CA_default # The default ca section
+
+####################################################################
+[ CA_default ]
+
+dir = /opt/ca # Where everything is kept
+certs = $dir/certs # Where the issued certs are kept
+crl_dir = $dir/crl # Where the issued crl are kept
+database = $dir/index.txt # database index file.
+#unique_subject = no # Set to 'no' to allow creation of
+ # several certs with same subject.
+new_certs_dir = $dir/newcerts # default place for new certs.
+
+certificate = $dir/cacert.pem # The CA certificate
+serial = $dir/serial # The current serial number
+crlnumber = $dir/crlnumber # the current crl number
+ # must be commented out to leave a V1 CRL
+crl = $dir/crl.pem # The current CRL
+private_key = $dir/private/cakey.pem# The private key
+RANDFILE = $dir/private/.rand # private random number file
+
+x509_extensions = usr_cert # The extensions to add to the cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default # Subject Name options
+cert_opt = ca_default # Certificate field options
+
+# Extension copying option: use with caution.
+# copy_extensions = copy
+
+# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
+# so this is commented out by default to leave a V1 CRL.
+# crlnumber must also be commented out to leave a V1 CRL.
+crl_extensions = crl_ext
+
+default_days = 365 # how long to certify for
+default_crl_days= 30 # how long before next CRL
+default_md = default # use public key default MD
+preserve = no # keep passed DN ordering
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = optional
+stateOrProvinceName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 2048
+default_keyfile = privkey.pem
+distinguished_name = req_distinguished_name
+attributes = req_attributes
+x509_extensions = v3_ca # The extensions to add to the self signed cert
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString (PKIX recommendation before 2004)
+# utf8only: only UTF8Strings (PKIX recommendation after 2004).
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: ancient versions of Netscape crash on BMPStrings or UTF8Strings.
+string_mask = utf8only
+
+# req_extensions = v3_req # The extensions to add to a certificate request
+
+[ req_distinguished_name ]
+countryName = Country Name (2 letter code)
+countryName_default = EE
+countryName_min = 2
+countryName_max = 2
+
+stateOrProvinceName = State or Province Name (full name)
+stateOrProvinceName_default = Harjumaa
+
+localityName = Locality Name (eg, city)
+localityName_default = Tallinn
+
+0.organizationName = Organization Name (eg, company)
+0.organizationName_default = Eesti Interneti Sihtasutus
+
+# we can do this but it is not needed normally :-)
+#1.organizationName = Second Organization Name (eg, company)
+#1.organizationName_default = World Wide Web Pty Ltd
+
+organizationalUnitName = Organizational Unit Name (eg, section)
+#organizationalUnitName_default =
+
+commonName = Common Name (e.g. server FQDN or YOUR name)
+commonName_max = 64
+
+emailAddress = Email Address
+emailAddress_default = hello@internet.ee
+emailAddress_max = 64
+
+# SET-ex3 = SET extension number 3
+
+[ req_attributes ]
+challengePassword = A challenge password
+challengePassword_min = 4
+challengePassword_max = 20
+
+unstructuredName = An optional company name
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This is required for TSA certificates.
+# extendedKeyUsage = critical,timeStamping
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+
+# PKIX recommendation.
+
+subjectKeyIdentifier=hash
+
+authorityKeyIdentifier=keyid:always,issuer
+
+basicConstraints = CA:true
+
+# Key usage: this is typical for a CA certificate. However since it will
+# prevent it being used as an test self-signed certificate it is best
+# left out by default.
+keyUsage = cRLSign, keyCertSign
+
+# Some might want this also
+# nsCertType = sslCA, emailCA
+
+# Include email address in subject alt name: another PKIX recommendation
+# subjectAltName=email:copy
+# Copy issuer details
+# issuerAltName=issuer:copy
+
+# DER hex encoding of an extension: beware experts only!
+# obj=DER:02:03
+# Where 'obj' is a standard or added object
+# You can even override a supported extension:
+# basicConstraints= critical, DER:30:03:01:01:FF
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always
+
+[ proxy_cert_ext ]
+# These extensions should be added when creating a proxy certificate
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# Here are some examples of the usage of nsCertType. If it is omitted
+# the certificate can be used for anything *except* object signing.
+
+# This is OK for an SSL server.
+# nsCertType = server
+
+# For an object signing certificate this would be used.
+# nsCertType = objsign
+
+# For normal client use this is typical
+# nsCertType = client, email
+
+# and for everything including object signing:
+# nsCertType = client, email, objsign
+
+# This is typical in keyUsage for a client certificate.
+# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+# This will be displayed in Netscape's comment listbox.
+nsComment = "OpenSSL Generated Certificate"
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+
+# This stuff is for subjectAltName and issuerAltname.
+# Import the email address.
+# subjectAltName=email:copy
+# An alternative to produce certificates that aren't
+# deprecated according to PKIX.
+# subjectAltName=email:move
+
+# Copy subject details
+# issuerAltName=issuer:copy
+
+#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+# This really needs to be in place for it to be a proxy certificate.
+proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
+
+####################################################################
+[ tsa ]
+
+default_tsa = tsa_config1 # the default TSA section
+
+[ tsa_config1 ]
+
+# These are used by the TSA reply generation only.
+dir = /opt/ca # TSA root directory
+serial = $dir/tsaserial # The current serial number (mandatory)
+crypto_device = builtin # OpenSSL engine to use for signing
+signer_cert = $dir/tsacert.pem # The TSA signing certificate
+ # (optional)
+certs = $dir/cacert.pem # Certificate chain to include in reply
+ # (optional)
+signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
+signer_digest = sha256 # Signing digest to use. (Optional)
+default_policy = tsa_policy1 # Policy if request did not specify it
+ # (optional)
+other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
+digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory)
+accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
+clock_precision_digits = 0 # number of digits after dot. (optional)
+ordering = yes # Is ordering defined for timestamps?
+ # (optional, default: no)
+tsa_name = yes # Must the TSA name be included in the reply?
+ # (optional, default: no)
+ess_cert_id_chain = no # Must the ESS cert id chain be included?
+ # (optional, default: no)
diff --git a/apps/epp_proxy/priv/test_ca/prepare_root_ca.sh b/apps/epp_proxy/priv/test_ca/prepare_root_ca.sh
new file mode 100755
index 0000000..41725eb
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/prepare_root_ca.sh
@@ -0,0 +1,8 @@
+# Prepare required files
+touch index.txt
+echo 1000 > serial
+echo 1000 > crlnumber
+
+# Generate Root CA.
+openssl genrsa -aes256 -out private/ca.key.pem 4096
+openssl req -config openssl.cnf -new -x509 -days 365 -key private/ca.key.pem -sha256 -extensions v3_ca -out certs/ca.crt.pem
diff --git a/apps/epp_proxy/priv/test_ca/private/apache.key b/apps/epp_proxy/priv/test_ca/private/apache.key
new file mode 100644
index 0000000..07aefa6
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/private/apache.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCqhksikVH3psjD
+GT0a/NN5Oew8ylMn98j5JZdCHlR+UAgbvgeX5oFb6TyMhn5XHBfCfu7Bjt9216a7
+0LMKpgrimpmDXrwgQLTRWd4LuCJ9oxaAF38M2K/cVp82lOKF0xmtmLzEski43Dxc
+toN5sZCut85bDUJ7C6b8wlogWcgG22wGr6MXAq0An1GA2DpSXbE4amq2suZTbUeY
+jOb2Gpt5pYg0hfVANULZlZ2BVeCgQgP9EtRzwD6uJVR1orMb2QKu27MY7w+FegXk
+Ela2ysBxgVB6/eNVEqmVIWHCGKOHYxjXioDbXCx40wXv59IKOG68SibGnM1BIfRQ
+AMdbSnXvAgMBAAECggEASSYcevKdl7+a5V4hQT9tM9ZuCVG9RCrdskq2zO0Xz6tj
+HwtwVG/T0+qER7+12IY7hvpOTweLwn4VjwGinBHIH5az/Y+Y4bkAF8IWJy7Q1NYt
+47qwjIEzRzB9UbuiREfe/wHDEBluaqZG2nqMgZpy9w/v3E0e1IuWEV0JrlD1JkMs
+nW3RC2unrHjB1ySIdyV6otd/EOHkyd73fygjkA96sVLnv/olyaiW4n7Hlqn1j4it
+5Zuqdcaf/AqP+2ADPK+QeISEGYLM9dUeuBEYONkaEH7h5G0ojuxNz5cU7n6l0Hu7
+mWOhJFOgA/KRZVsHf+VsPOLGUizY5TjnIS0gyq/wQQKBgQDRkx7ufhYqa81PgQ9X
+r0D+D7NuJJxNxA7unU42fa86FWpjnBIxz8tlPM302g+cR6qSWygXcEaxr1CezkcX
+db/4MaiN3NWst7z2/dkOEO5Bv+54SzckxZt1QhkoUznxDMOqPdWIKIgjQEroIlHz
+TyHT+oF+zEBrNqKGexS11IYczwKBgQDQTKj4C0yfyuXIjwnhEJFqMFqGJsFD/mbL
+ca6mx5i/0tsN/HKCSWPza7gh0wiP28f1EULk2UkScHqvt5XBCDofPbr3bkipGy0V
+6x2NlOcdCMiFfcK15AIMMddiL9Be1pSTqUIQ1thUu4k0vfbu8LurchZIqjBtWaQK
+nrYNI5Oc4QKBgFR5+iDmQCcPVy3x9u5AXXFLgOcn6L1MBzzVub4rQWOnWEAYnBjq
+CrGfJeHJuDslhDMEfY+dGVHsOhIZUfy54Qy5b5jnaFX7pjblMgYCexeTtxtULkEr
+SjOk1iE0EwoAPCq2TAlbVSzocIlLtD7gKeGZe3NR/7F3z2Fn4Xw902VvAoGBAMQd
+GQ0IXmkn97Yfbha3qaFHy0L45AdnU1MCQoSF8bvRAysk3o7qGC/L4H4AGdSQAbAr
+Q0cBiLnSqsAb4ePvIgHd9dUVwVVt38H+LkHpyrrcVSbR4+uqs37VwkqQZ+eSsipg
+NnJyRRVpx+GfZQlMH/VoIbDig1vBBSB2k0LFlyohAoGBAIwt5E07ez+B0JihGE7F
+390gH57xS3M7G4iB1bEr4VyZmStOzNmA4hhz+pz8pnKxMu1bwZdsgvtmQDh59j3I
+AUaldDULGfSLQ5YJZ1apyAk2kIDF0Buhe2UtkHtnWG6PFSwEs0AKZeliyIpgZ9R4
+86eWGoSuHznP2faVslscZSyE
+-----END PRIVATE KEY-----
diff --git a/apps/epp_proxy/priv/test_ca/private/ca.key.pem b/apps/epp_proxy/priv/test_ca/private/ca.key.pem
new file mode 100644
index 0000000..c60b8a8
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/private/ca.key.pem
@@ -0,0 +1,54 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,AEB2DBECCB8452DE1D6E3F46B4AD32A8
+
+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
+-----END RSA PRIVATE KEY-----
diff --git a/apps/epp_proxy/priv/test_ca/private/webclient.key.pem b/apps/epp_proxy/priv/test_ca/private/webclient.key.pem
new file mode 100644
index 0000000..dc5ad8a
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/private/webclient.key.pem
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/apps/epp_proxy/priv/test_ca/serial b/apps/epp_proxy/priv/test_ca/serial
new file mode 100644
index 0000000..83b33d2
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/serial
@@ -0,0 +1 @@
+1000
diff --git a/apps/epp_proxy/priv/test_ca/server.csr b/apps/epp_proxy/priv/test_ca/server.csr
new file mode 100644
index 0000000..1020d46
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/server.csr
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIC2DCCAcACAQAwgZIxCzAJBgNVBAYTAkVFMREwDwYDVQQIDAhIYXJqdW1hYTEQ
+MA4GA1UEBwwHVGFsbGlubjEZMBcGA1UECgwQRWVzdGlJbnRlcm5ldGlTQTEQMA4G
+A1UECwwHQXJlbmR1czEgMB4GCSqGSIb3DQEJARYRaGVsbG9AaW50ZXJuZXQuZWUx
+DzANBgNVBAMMBioudGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKqGSyKRUfemyMMZPRr803k57DzKUyf3yPkll0IeVH5QCBu+B5fmgVvpPIyGflcc
+F8J+7sGO33bXprvQswqmCuKamYNevCBAtNFZ3gu4In2jFoAXfwzYr9xWnzaU4oXT
+Ga2YvMSySLjcPFy2g3mxkK63zlsNQnsLpvzCWiBZyAbbbAavoxcCrQCfUYDYOlJd
+sThqaray5lNtR5iM5vYam3mliDSF9UA1QtmVnYFV4KBCA/0S1HPAPq4lVHWisxvZ
+Aq7bsxjvD4V6BeQSVrbKwHGBUHr941USqZUhYcIYo4djGNeKgNtcLHjTBe/n0go4
+brxKJsaczUEh9FAAx1tKde8CAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQAkJkKR
+jqptkp2vkHUH/Nnmqh9SCPD5wETGtGLZzS/ZnWAyRPHZ8Kw3XnCvyZj41EnWifWC
++0kKSpQTvhED8RPmgfE1piQtSPuFJ9f26vyag5sGPfUkBaBl6zaxpK3fDHpCercy
+N5J6b1FAoWj/rhtRCMJx8OYCmurBp4BUtyYbduk0FWhdcX8uyRiLOOxaGO7ZpkEf
+CEUhEarperXPqhm9NtNbPrEP15tunf5otM6FjpIoc0wFtlOUdrZBT9dE+67F8WlT
+qlXUSXucrhWt/WXEiuzaj6w/J7prDr9ua/xO9qUo5aWA6QlPsSsaQl9KF9ST0qXG
+hm/lggFVtkCvKv5L
+-----END CERTIFICATE REQUEST-----
diff --git a/apps/epp_proxy/priv/test_ca/server.csr.cnf b/apps/epp_proxy/priv/test_ca/server.csr.cnf
new file mode 100644
index 0000000..b4b38b4
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/server.csr.cnf
@@ -0,0 +1,14 @@
+[req]
+default_bits = 2048
+prompt = no
+default_md = sha256
+distinguished_name = dn
+
+[dn]
+C=EE
+ST=Harjumaa
+L=Tallinn
+O=EestiInternetiSA
+OU=Arendus
+emailAddress=hello@internet.ee
+CN = *.test
diff --git a/apps/epp_proxy/priv/test_ca/v3.ext b/apps/epp_proxy/priv/test_ca/v3.ext
new file mode 100644
index 0000000..82646bc
--- /dev/null
+++ b/apps/epp_proxy/priv/test_ca/v3.ext
@@ -0,0 +1,8 @@
+authorityKeyIdentifier=keyid,issuer
+basicConstraints=CA:FALSE
+keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
+subjectAltName = @alt_names
+
+[alt_names]
+DNS.1 = test
+DNS.2 = registry.test
diff --git a/apps/epp_proxy/src/epp_http_client.erl b/apps/epp_proxy/src/epp_http_client.erl
index c24e521..2f0e837 100644
--- a/apps/epp_proxy/src/epp_http_client.erl
+++ b/apps/epp_proxy/src/epp_http_client.erl
@@ -77,26 +77,6 @@ request_from_map(#{command := Command,
cookies = [Cookie], headers = Headers,
epp_verb = Command},
lager:info("Request from map: [~p]~n", [Request]),
- Request;
-request_from_map(#{command := Command,
- session_id := SessionId, raw_frame := RawFrame,
- common_name := CommonName, client_cert := ClientCert,
- peer_ip := PeerIp, cl_trid := ClTRID}) ->
- URL = epp_router:route_request(Command),
- RequestMethod = epp_router:request_method(Command),
- Cookie = hackney_cookie:setcookie("session", SessionId,
- []),
- Body = request_body(Command, RawFrame, ClTRID),
- Headers = [{"SSL_CLIENT_CERT", ClientCert},
- {"SSL_CLIENT_S_DN_CN", CommonName},
- {"User-Agent", <<"EPP proxy">>},
- {"X-Forwarded-for", epp_util:readable_ip(PeerIp)}],
- Request = #epp_request{url = URL,
- method = RequestMethod, payload = Body,
- cookies = [Cookie], headers = Headers,
- epp_verb = Command},
- lager:info("Unified Request from map: [~p]~n",
- [Request]),
Request.
%% Return form data or an empty list.
diff --git a/apps/epp_proxy/src/epp_tls_acceptor.erl b/apps/epp_proxy/src/epp_tls_acceptor.erl
index d1e8b44..fd2bd9e 100644
--- a/apps/epp_proxy/src/epp_tls_acceptor.erl
+++ b/apps/epp_proxy/src/epp_tls_acceptor.erl
@@ -68,23 +68,23 @@ create_worker(Socket) ->
ca_cert_file() ->
case application:get_env(epp_proxy, cacertfile_path) of
undefined -> undefined;
- {ok, CaCertFile} -> CaCertFile
+ {ok, CaCertFile} -> epp_util:path_for_file(CaCertFile)
end.
cert_file() ->
case application:get_env(epp_proxy, certfile_path) of
undefined -> undefined;
- {ok, CertFile} -> CertFile
+ {ok, CertFile} -> epp_util:path_for_file(CertFile)
end.
key_file() ->
case application:get_env(epp_proxy, keyfile_path) of
undefined -> undefined;
- {ok, KeyFile} -> KeyFile
+ {ok, KeyFile} -> epp_util:path_for_file(KeyFile)
end.
crl_file() ->
case application:get_env(epp_proxy, crlfile_path) of
undefined -> undefined;
- {ok, CrlFile} -> CrlFile
+ {ok, CrlFile} -> epp_util:path_for_file(CrlFile)
end.
diff --git a/apps/epp_proxy/src/epp_util.erl b/apps/epp_proxy/src/epp_util.erl
index 9573990..aa6c18a 100644
--- a/apps/epp_proxy/src/epp_util.erl
+++ b/apps/epp_proxy/src/epp_util.erl
@@ -2,7 +2,8 @@
-export([create_map/1, create_session_id/1,
frame_length/1, frame_length_to_receive/1,
- frame_length_to_send/1, readable_ip/1, session_id/1]).
+ frame_length_to_send/1, path_for_file/1, readable_ip/1,
+ session_id/1]).
-define(OFFSET, 4).
@@ -67,3 +68,11 @@ readable_ip({FirstOctet, SecondOctet, ThirdOctet,
integer_to_list(FourthOctet)],
Binary = list_to_binary(List),
Binary.
+
+path_for_file(Filename) ->
+ case filename:pathtype(Filename) of
+ absolute -> Filename;
+ relative ->
+ CWD = code:priv_dir(epp_proxy),
+ filename:join(CWD, Filename)
+ end.
diff --git a/apps/epp_proxy/test/certs/epp-proxy-test.crt.pem b/apps/epp_proxy/test/certs/epp-proxy-test.crt.pem
deleted file mode 100644
index a45d959..0000000
--- a/apps/epp_proxy/test/certs/epp-proxy-test.crt.pem
+++ /dev/null
@@ -1,36 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGWzCCBEOgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgaoxCzAJBgNVBAYTAkVF
-MREwDwYDVQQIDAhIYXJqdW1hYTEQMA4GA1UEBwwHVGFsbGlubjEjMCEGA1UECgwa
-RWVzdGkgSW50ZXJuZXRpIFNpaHRhc3V0dXMxLzAtBgNVBAMMJk1hY2llaidzIGRl
-dmVsb3BtZW50IGNlcnRpZmljYXRlIChFSVMpMSAwHgYJKoZIhvcNAQkBFhFoZWxs
-b0BpbnRlcm5ldC5lZTAeFw0xOTA1MjMxMjUwMzFaFw0yMDA1MjIxMjUwMzFaMIGp
-MQswCQYDVQQGEwJFRTERMA8GA1UECAwISGFyanVtYWExIzAhBgNVBAoMGkVlc3Rp
-IEludGVybmV0aSBTaWh0YXN1dHVzMSMwIQYDVQQLDBpFUFAgUHJveHkgdGVzdCBj
-ZXJ0aWZpY2F0ZTEXMBUGA1UEAwwORXBwIFByb3h5IFRlc3QxJDAiBgkqhkiG9w0B
-CQEWFWVwcC1wcm94eUBpbnRlcm5ldC5lZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBAMQalaRFIgknGeQ5iuoBju+cviOksq85azQRIwDaxwwjpFwmRwt2
-smPa/0GMyG3/FBGNpUBtb+0ngVMCw5h4aUeWhs9Y9d1kMqaEgpdLm0hWpUIIqOMO
-wQpHugPQGJiz75Y4tIUbdazODTvEChDNPZ7Ut8jVzsoRFIgPV4abcoqTqD0wNYZb
-TQ0MzOulB2PsxzKrT9MzWkdyju3FYtDxXRGKP3vXC3YhN4EXLqoDzMU51NoYQcPc
-Fk5j+1aQKXfNwJcLEvHGlHce9MIEakl5sJt+u8REmp43uy//DNa7mzACfu4xHAW+
-heuH+xhEZAT40oxFi0Goa2rhMjz7hx5GM8KPFvJ0vlkR74pRnz1/XNqpx5PundYY
-RK0swk+E+z3oFqClsjFiBVZQSPnYdGhid3qDaSqTsVO4G07rzh54SrBm7AsU8CQF
-45OOngr1razw5jKnWH6qzNLFKcZBchOSmW31ZpTqfbol6UhThEM6qZr5Dsk+QZbd
-kVZ5v3YZs72HL5Fxn/Ix5WOL886fSBOOHyg9rkFoypXZxfyZZehbhY3alszqJFbj
-bJ4f+tt2+ObCbkUiN3huP+i+41l+eIBobtsaQhtdzp/44KWR5u4kk2OexO4oZPFN
-futAsemo/sxU8E9KvjS02j2zIXTNyV/8Axp30LhHFQvey8QtNbhM2YClAgMBAAGj
-gYkwgYYwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwLAYJYIZIAYb4QgENBB8WHU9w
-ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSec3EaCPVAovnz
-u01SwyEoc9Kt6zAfBgNVHSMEGDAWgBRF1wL+I61d2uBQ1467prsu2SYRGTANBgkq
-hkiG9w0BAQsFAAOCAgEAPks4fHoAvzjidw8aJB+nX1pDzbWEbeWOl4xvYizvCN/c
-rWeFp6+BnaUuQK5lXTS1z9m2bf70sSFOFTl6JHbpYdU7xr5Qfn69gfdIqeC2k52g
-R29oYYRQSjMxufHW9IMufJ/FL1PW6EIlahx01WWla/wg6EC3Bygvnz5oCsDaNTwO
-eWKSFVwnE1l6kOoxSparvOdrKpbqvmhUGy8qCRwvLtF2CRQihYSHnnU18oe78REP
-Hkyqfjr/GxHn8senKJcN9AQ4RjxMeH/X1wr7Z+0OTpQh61AMEzzyO9sHy9uvxQoN
-FREhTs53T10Br5Ppx7hp9S6jmiYgL8wtJwJIWFowq87VfuyeqEKhFXqjybeAXIlv
-o4dpUd3woW5rBWhmo6tVs04vNtD6LFktbgkRIV8PPeb1M4QkJ8eD6z7tJNEHVGmK
-S0vlDrdTzERwJlhh52d7a6vPXGG1/S7Mji/xyyDuWClaoJXy5NVr8DnKb1WudAXH
-nspSoh4YApK4oWTKxYWuhs7rshxFu5A2T03RzJbgsAA/9wrZ4BZz4OCtEVUYoIhV
-Qv4f2eOKB8d//vYJWon4R6ukYDZZnYNGplmxl47rzcEam1K88IeaBLN1hirvb9G9
-Xk+wDNgZwJmHtYeJSOZHjiQCl2YJCiVn4gbuDxjrEJvye4s6n8fdn4sv2kX06MU=
------END CERTIFICATE-----
diff --git a/apps/epp_proxy/test/certs/epp-proxy-test.key.pem b/apps/epp_proxy/test/certs/epp-proxy-test.key.pem
deleted file mode 100644
index 0a42e2e..0000000
--- a/apps/epp_proxy/test/certs/epp-proxy-test.key.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-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
------END RSA PRIVATE KEY-----
diff --git a/apps/epp_proxy/test/epp_certs_SUITE.erl b/apps/epp_proxy/test/epp_certs_SUITE.erl
index 5100abc..5519f34 100644
--- a/apps/epp_proxy/test/epp_certs_SUITE.erl
+++ b/apps/epp_proxy/test/epp_certs_SUITE.erl
@@ -1,13 +1,79 @@
-module(epp_certs_SUITE).
--include_lib("common_test/include/ct.hrl").
+-include_lib("public_key/include/public_key.hrl").
-export([all/0]).
--export([run_eunit/1]).
+-export([der_certificate_test_case/1, subject_from_otp_certificate_test_case/1,
+ common_name_from_subject_test_case/1]).
-all() -> [run_eunit].
+all() -> [der_certificate_test_case, subject_from_otp_certificate_test_case,
+ common_name_from_subject_test_case].
%% Run Unit tests.
%% Todo: these should be property tests, not unit tests.
-run_eunit(_Config) ->
- ok = eunit:test(epp_certs_tests).
+der_certificate_test_case(_Config) ->
+ PemEntries = public_key:pem_decode(certificate_pem()),
+ {value, CertEntry} = lists:keysearch('Certificate', 1, PemEntries),
+ {_, DerCert, _} = CertEntry,
+ Certificate = epp_certs:der_certificate(DerCert),
+ true = is_record(Certificate, 'OTPCertificate'),
+ ok.
+
+subject_from_otp_certificate_test_case(_Config) ->
+ Certificate = test_certificate(),
+ Subject = epp_certs:subject_from_otp_certificate(Certificate),
+ {rdnSequence, _ListOfAttributes} = Subject,
+ ok.
+
+common_name_from_subject_test_case(_Config) ->
+ Certificate = test_certificate(),
+ Subject = epp_certs:subject_from_otp_certificate(Certificate),
+ CommonName = epp_certs:common_name_from_subject(Subject),
+ <<"Epp Proxy Test">> = CommonName,
+ ok.
+
+%% Helper functions
+test_certificate() ->
+ PemEntries = public_key:pem_decode(certificate_pem()),
+ {value, CertEntry} = lists:keysearch('Certificate', 1, PemEntries),
+ {_, DerCert, _} = CertEntry,
+ Decoded = public_key:pkix_decode_cert(DerCert, otp),
+ Decoded.
+
+certificate_pem() ->
+ <<"-----BEGIN CERTIFICATE-----\n"
+ "MIIGWzCCBEOgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgaoxCzAJBgNVBAYTAkVF\n"
+ "MREwDwYDVQQIDAhIYXJqdW1hYTEQMA4GA1UEBwwHVGFsbGlubjEjMCEGA1UECgwa\n"
+ "RWVzdGkgSW50ZXJuZXRpIFNpaHRhc3V0dXMxLzAtBgNVBAMMJk1hY2llaidzIGRl\n"
+ "dmVsb3BtZW50IGNlcnRpZmljYXRlIChFSVMpMSAwHgYJKoZIhvcNAQkBFhFoZWxs\n"
+ "b0BpbnRlcm5ldC5lZTAeFw0xOTA1MjMxMjUwMzFaFw0yMDA1MjIxMjUwMzFaMIGp\n"
+ "MQswCQYDVQQGEwJFRTERMA8GA1UECAwISGFyanVtYWExIzAhBgNVBAoMGkVlc3Rp\n"
+ "IEludGVybmV0aSBTaWh0YXN1dHVzMSMwIQYDVQQLDBpFUFAgUHJveHkgdGVzdCBj\n"
+ "ZXJ0aWZpY2F0ZTEXMBUGA1UEAwwORXBwIFByb3h5IFRlc3QxJDAiBgkqhkiG9w0B\n"
+ "CQEWFWVwcC1wcm94eUBpbnRlcm5ldC5lZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP\n"
+ "ADCCAgoCggIBAMQalaRFIgknGeQ5iuoBju+cviOksq85azQRIwDaxwwjpFwmRwt2\n"
+ "smPa/0GMyG3/FBGNpUBtb+0ngVMCw5h4aUeWhs9Y9d1kMqaEgpdLm0hWpUIIqOMO\n"
+ "wQpHugPQGJiz75Y4tIUbdazODTvEChDNPZ7Ut8jVzsoRFIgPV4abcoqTqD0wNYZb\n"
+ "TQ0MzOulB2PsxzKrT9MzWkdyju3FYtDxXRGKP3vXC3YhN4EXLqoDzMU51NoYQcPc\n"
+ "Fk5j+1aQKXfNwJcLEvHGlHce9MIEakl5sJt+u8REmp43uy//DNa7mzACfu4xHAW+\n"
+ "heuH+xhEZAT40oxFi0Goa2rhMjz7hx5GM8KPFvJ0vlkR74pRnz1/XNqpx5PundYY\n"
+ "RK0swk+E+z3oFqClsjFiBVZQSPnYdGhid3qDaSqTsVO4G07rzh54SrBm7AsU8CQF\n"
+ "45OOngr1razw5jKnWH6qzNLFKcZBchOSmW31ZpTqfbol6UhThEM6qZr5Dsk+QZbd\n"
+ "kVZ5v3YZs72HL5Fxn/Ix5WOL886fSBOOHyg9rkFoypXZxfyZZehbhY3alszqJFbj\n"
+ "bJ4f+tt2+ObCbkUiN3huP+i+41l+eIBobtsaQhtdzp/44KWR5u4kk2OexO4oZPFN\n"
+ "futAsemo/sxU8E9KvjS02j2zIXTNyV/8Axp30LhHFQvey8QtNbhM2YClAgMBAAGj\n"
+ "gYkwgYYwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwLAYJYIZIAYb4QgENBB8WHU9w\n"
+ "ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSec3EaCPVAovnz\n"
+ "u01SwyEoc9Kt6zAfBgNVHSMEGDAWgBRF1wL+I61d2uBQ1467prsu2SYRGTANBgkq\n"
+ "hkiG9w0BAQsFAAOCAgEAPks4fHoAvzjidw8aJB+nX1pDzbWEbeWOl4xvYizvCN/c\n"
+ "rWeFp6+BnaUuQK5lXTS1z9m2bf70sSFOFTl6JHbpYdU7xr5Qfn69gfdIqeC2k52g\n"
+ "R29oYYRQSjMxufHW9IMufJ/FL1PW6EIlahx01WWla/wg6EC3Bygvnz5oCsDaNTwO\n"
+ "eWKSFVwnE1l6kOoxSparvOdrKpbqvmhUGy8qCRwvLtF2CRQihYSHnnU18oe78REP\n"
+ "Hkyqfjr/GxHn8senKJcN9AQ4RjxMeH/X1wr7Z+0OTpQh61AMEzzyO9sHy9uvxQoN\n"
+ "FREhTs53T10Br5Ppx7hp9S6jmiYgL8wtJwJIWFowq87VfuyeqEKhFXqjybeAXIlv\n"
+ "o4dpUd3woW5rBWhmo6tVs04vNtD6LFktbgkRIV8PPeb1M4QkJ8eD6z7tJNEHVGmK\n"
+ "S0vlDrdTzERwJlhh52d7a6vPXGG1/S7Mji/xyyDuWClaoJXy5NVr8DnKb1WudAXH\n"
+ "nspSoh4YApK4oWTKxYWuhs7rshxFu5A2T03RzJbgsAA/9wrZ4BZz4OCtEVUYoIhV\n"
+ "Qv4f2eOKB8d//vYJWon4R6ukYDZZnYNGplmxl47rzcEam1K88IeaBLN1hirvb9G9\n"
+ "Xk+wDNgZwJmHtYeJSOZHjiQCl2YJCiVn4gbuDxjrEJvye4s6n8fdn4sv2kX06MU=\n"
+ "-----END CERTIFICATE-----">>.
diff --git a/apps/epp_proxy/test/epp_certs_tests.erl b/apps/epp_proxy/test/epp_certs_tests.erl
deleted file mode 100644
index 68b7c54..0000000
--- a/apps/epp_proxy/test/epp_certs_tests.erl
+++ /dev/null
@@ -1,67 +0,0 @@
--module(epp_certs_tests).
-
--include_lib("eunit/include/eunit.hrl").
--include_lib("public_key/include/public_key.hrl").
-
-der_certificate_test() ->
- PemEntries = public_key:pem_decode(certificate_pem()),
- {value, CertEntry} = lists:keysearch('Certificate', 1, PemEntries),
- {_, DerCert, _} = CertEntry,
- Certificate = epp_certs:der_certificate(DerCert),
- ?assert(is_record(Certificate, 'OTPCertificate')).
-
-subject_from_otp_certificate_test() ->
- Certificate = test_certificate(),
- Subject = epp_certs:subject_from_otp_certificate(Certificate),
- {rdnSequence, _ListOfAttributes} = Subject.
-
-common_name_from_subject_test() ->
- Certificate = test_certificate(),
- Subject = epp_certs:subject_from_otp_certificate(Certificate),
- CommonName = epp_certs:common_name_from_subject(Subject),
- ?assertEqual(<<"Epp Proxy Test">>, CommonName).
-
-test_certificate() ->
- PemEntries = public_key:pem_decode(certificate_pem()),
- {value, CertEntry} = lists:keysearch('Certificate', 1, PemEntries),
- {_, DerCert, _} = CertEntry,
- Decoded = public_key:pkix_decode_cert(DerCert, otp),
- Decoded.
-
-certificate_pem() ->
- <<"-----BEGIN CERTIFICATE-----\n"
- "MIIGWzCCBEOgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgaoxCzAJBgNVBAYTAkVF\n"
- "MREwDwYDVQQIDAhIYXJqdW1hYTEQMA4GA1UEBwwHVGFsbGlubjEjMCEGA1UECgwa\n"
- "RWVzdGkgSW50ZXJuZXRpIFNpaHRhc3V0dXMxLzAtBgNVBAMMJk1hY2llaidzIGRl\n"
- "dmVsb3BtZW50IGNlcnRpZmljYXRlIChFSVMpMSAwHgYJKoZIhvcNAQkBFhFoZWxs\n"
- "b0BpbnRlcm5ldC5lZTAeFw0xOTA1MjMxMjUwMzFaFw0yMDA1MjIxMjUwMzFaMIGp\n"
- "MQswCQYDVQQGEwJFRTERMA8GA1UECAwISGFyanVtYWExIzAhBgNVBAoMGkVlc3Rp\n"
- "IEludGVybmV0aSBTaWh0YXN1dHVzMSMwIQYDVQQLDBpFUFAgUHJveHkgdGVzdCBj\n"
- "ZXJ0aWZpY2F0ZTEXMBUGA1UEAwwORXBwIFByb3h5IFRlc3QxJDAiBgkqhkiG9w0B\n"
- "CQEWFWVwcC1wcm94eUBpbnRlcm5ldC5lZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP\n"
- "ADCCAgoCggIBAMQalaRFIgknGeQ5iuoBju+cviOksq85azQRIwDaxwwjpFwmRwt2\n"
- "smPa/0GMyG3/FBGNpUBtb+0ngVMCw5h4aUeWhs9Y9d1kMqaEgpdLm0hWpUIIqOMO\n"
- "wQpHugPQGJiz75Y4tIUbdazODTvEChDNPZ7Ut8jVzsoRFIgPV4abcoqTqD0wNYZb\n"
- "TQ0MzOulB2PsxzKrT9MzWkdyju3FYtDxXRGKP3vXC3YhN4EXLqoDzMU51NoYQcPc\n"
- "Fk5j+1aQKXfNwJcLEvHGlHce9MIEakl5sJt+u8REmp43uy//DNa7mzACfu4xHAW+\n"
- "heuH+xhEZAT40oxFi0Goa2rhMjz7hx5GM8KPFvJ0vlkR74pRnz1/XNqpx5PundYY\n"
- "RK0swk+E+z3oFqClsjFiBVZQSPnYdGhid3qDaSqTsVO4G07rzh54SrBm7AsU8CQF\n"
- "45OOngr1razw5jKnWH6qzNLFKcZBchOSmW31ZpTqfbol6UhThEM6qZr5Dsk+QZbd\n"
- "kVZ5v3YZs72HL5Fxn/Ix5WOL886fSBOOHyg9rkFoypXZxfyZZehbhY3alszqJFbj\n"
- "bJ4f+tt2+ObCbkUiN3huP+i+41l+eIBobtsaQhtdzp/44KWR5u4kk2OexO4oZPFN\n"
- "futAsemo/sxU8E9KvjS02j2zIXTNyV/8Axp30LhHFQvey8QtNbhM2YClAgMBAAGj\n"
- "gYkwgYYwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwLAYJYIZIAYb4QgENBB8WHU9w\n"
- "ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBSec3EaCPVAovnz\n"
- "u01SwyEoc9Kt6zAfBgNVHSMEGDAWgBRF1wL+I61d2uBQ1467prsu2SYRGTANBgkq\n"
- "hkiG9w0BAQsFAAOCAgEAPks4fHoAvzjidw8aJB+nX1pDzbWEbeWOl4xvYizvCN/c\n"
- "rWeFp6+BnaUuQK5lXTS1z9m2bf70sSFOFTl6JHbpYdU7xr5Qfn69gfdIqeC2k52g\n"
- "R29oYYRQSjMxufHW9IMufJ/FL1PW6EIlahx01WWla/wg6EC3Bygvnz5oCsDaNTwO\n"
- "eWKSFVwnE1l6kOoxSparvOdrKpbqvmhUGy8qCRwvLtF2CRQihYSHnnU18oe78REP\n"
- "Hkyqfjr/GxHn8senKJcN9AQ4RjxMeH/X1wr7Z+0OTpQh61AMEzzyO9sHy9uvxQoN\n"
- "FREhTs53T10Br5Ppx7hp9S6jmiYgL8wtJwJIWFowq87VfuyeqEKhFXqjybeAXIlv\n"
- "o4dpUd3woW5rBWhmo6tVs04vNtD6LFktbgkRIV8PPeb1M4QkJ8eD6z7tJNEHVGmK\n"
- "S0vlDrdTzERwJlhh52d7a6vPXGG1/S7Mji/xyyDuWClaoJXy5NVr8DnKb1WudAXH\n"
- "nspSoh4YApK4oWTKxYWuhs7rshxFu5A2T03RzJbgsAA/9wrZ4BZz4OCtEVUYoIhV\n"
- "Qv4f2eOKB8d//vYJWon4R6ukYDZZnYNGplmxl47rzcEam1K88IeaBLN1hirvb9G9\n"
- "Xk+wDNgZwJmHtYeJSOZHjiQCl2YJCiVn4gbuDxjrEJvye4s6n8fdn4sv2kX06MU=\n"
- "-----END CERTIFICATE-----">>.
diff --git a/apps/epp_proxy/test/epp_http_client_SUITE.erl b/apps/epp_proxy/test/epp_http_client_SUITE.erl
new file mode 100644
index 0000000..3f3f8c8
--- /dev/null
+++ b/apps/epp_proxy/test/epp_http_client_SUITE.erl
@@ -0,0 +1,81 @@
+-module(epp_http_client_SUITE).
+
+-include("epp_proxy.hrl").
+-include_lib("common_test/include/ct.hrl").
+
+-export([all/0]).
+-export([init_per_suite/1, end_per_suite/1]).
+-export([hello_request_builder_test_case/1,
+ error_request_builder_test_case/1,
+ command_request_builder_test_case/1,
+ registry_unreachable_test_case/1]).
+
+all() ->
+ [hello_request_builder_test_case,
+ error_request_builder_test_case,
+ command_request_builder_test_case,
+ registry_unreachable_test_case].
+
+init_per_suite(Config) ->
+ application:ensure_all_started(hackney),
+ Config.
+
+end_per_suite(Config) ->
+ application:stop(hackney),
+ Config.
+
+hello_request_builder_test_case(_Config) ->
+ RequestMap = #{command => "hello", session_id => "Random",
+ cl_trid => "EE-123456789", raw_frame => "",
+ headers => [{"User-Agent", <<"EPP proxy">>}]},
+ Request = epp_http_client:request_builder(RequestMap),
+ ExpectedTuple = {epp_request,get,"http://localhost:9292/session/hello",
+ [],
+ [<<"session=Random; Version=1">>],
+ [{"User-Agent",<<"EPP proxy">>}], "hello"},
+ true = is_record(Request, epp_request),
+ ExpectedTuple = Request.
+
+error_request_builder_test_case(_Config) ->
+ RequestMap = #{command => "error", session_id => "Random",
+ cl_trid => "EE-123456789", code => <<"2001">>,
+ message => <<"Expected better XML">>,
+ headers => [{"User-Agent", <<"EPP proxy">>}]},
+ Request = epp_http_client:request_builder(RequestMap),
+ ExpectedTuple = {epp_request,get,"http://localhost:9292/error",
+ [{<<"code">>,<<"2001">>},
+ {<<"msg">>,<<"Expected better XML">>},
+ {<<"clTRID">>,"EE-123456789"}],
+ [<<"session=Random; Version=1">>],
+ [{"User-Agent",<<"EPP proxy">>}], "error"},
+ true = is_record(Request, epp_request),
+ ExpectedTuple = Request,
+ ok.
+
+command_request_builder_test_case(_Config) ->
+ RequestMap = #{command => "create", session_id => "Random",
+ cl_trid => "EE-123456789", raw_frame => "Some XML here",
+ headers => [{"User-Agent", <<"EPP proxy">>}]},
+ Request = epp_http_client:request_builder(RequestMap),
+ ExpectedTuple = {epp_request,post,
+ "http://localhost:9292/command/create",
+ {multipart,
+ [{<<"raw_frame">>,"Some XML here"},
+ {<<"clTRID">>,"EE-123456789"}]},
+ [<<"session=Random; Version=1">>],
+ [{"User-Agent",<<"EPP proxy">>}], "create"},
+ true = is_record(Request, epp_request),
+ ExpectedTuple = Request,
+ ok.
+
+registry_unreachable_test_case(_Config) ->
+ Request = {epp_request,
+ post,
+ "http://localhost:9999/someurl",
+ {multipart,
+ [{<<"raw_frame">>,"Some XML here"},
+ {<<"clTRID">>,"EE-123456789"}]},
+ [<<"session=Random; Version=1">>],
+ [{"User-Agent",<<"EPP proxy">>}], "create"},
+ {2400, _CannedResponse} = epp_http_client:request(Request),
+ ok.
diff --git a/apps/epp_proxy/test/epp_http_client_tests.erl b/apps/epp_proxy/test/epp_http_client_tests.erl
deleted file mode 100644
index 4b6fe2c..0000000
--- a/apps/epp_proxy/test/epp_http_client_tests.erl
+++ /dev/null
@@ -1,46 +0,0 @@
--module(epp_http_client_tests).
-
--include_lib("eunit/include/eunit.hrl").
--include("epp_proxy.hrl").
-
-hello_request_builder_test() ->
- RequestMap = #{command => "hello", session_id => "Random",
- cl_trid => "EE-123456789", raw_frame => "",
- headers => [{"User-Agent", <<"EPP proxy">>}]},
- Request = epp_http_client:request_builder(RequestMap),
- ExpectedTuple = {epp_request,get,"https://registry.test/epp/session/hello",
- [],
- [<<"session=Random; Version=1">>],
- [{"User-Agent",<<"EPP proxy">>}], "hello"},
- ?assert(is_record(Request, epp_request)),
- ?assertEqual(ExpectedTuple, Request).
-
-error_request_builder_test() ->
- RequestMap = #{command => "error", session_id => "Random",
- cl_trid => "EE-123456789", code => <<"2001">>,
- message => <<"Expected better XML">>,
- headers => [{"User-Agent", <<"EPP proxy">>}]},
- Request = epp_http_client:request_builder(RequestMap),
- ExpectedTuple = {epp_request,get,"https://registry.test/epp/error",
- [{<<"code">>,<<"2001">>},
- {<<"msg">>,<<"Expected better XML">>},
- {<<"clTRID">>,"EE-123456789"}],
- [<<"session=Random; Version=1">>],
- [{"User-Agent",<<"EPP proxy">>}], "error"},
- ?assert(is_record(Request, epp_request)),
- ?assertEqual(ExpectedTuple, Request).
-
-command_request_builder_test() ->
- RequestMap = #{command => "create", session_id => "Random",
- cl_trid => "EE-123456789", raw_frame => "Some XML here",
- headers => [{"User-Agent", <<"EPP proxy">>}]},
- Request = epp_http_client:request_builder(RequestMap),
- ExpectedTuple = {epp_request,post,
- "https://registry.test/epp/command/create",
- {multipart,
- [{<<"raw_frame">>,"Some XML here"},
- {<<"clTRID">>,"EE-123456789"}]},
- [<<"session=Random; Version=1">>],
- [{"User-Agent",<<"EPP proxy">>}], "create"},
- ?assert(is_record(Request, epp_request)),
- ?assertEqual(ExpectedTuple, Request).
diff --git a/apps/epp_proxy/test/epp_router_SUITE.erl b/apps/epp_proxy/test/epp_router_SUITE.erl
index d6e1441..a49bd1b 100644
--- a/apps/epp_proxy/test/epp_router_SUITE.erl
+++ b/apps/epp_proxy/test/epp_router_SUITE.erl
@@ -3,10 +3,83 @@
-include_lib("common_test/include/ct.hrl").
-export([all/0]).
--export([run_eunit/1]).
+-export([request_method_test_case/1, hello_url_test_case/1, login_url_test_case/1,
+ logout_url_test_case/1, check_url_test_case/1, info_url_test_case/1, poll_url_test_case/1,
+ create_url_test_case/1, delete_url_test_case/1, renew_url_test_case/1,
+ update_url_test_case/1, transfer_url_test_case/1, error_url_test_case/1]).
-all() -> [run_eunit].
+all() -> [request_method_test_case, hello_url_test_case, login_url_test_case,
+ logout_url_test_case, check_url_test_case, info_url_test_case, poll_url_test_case,
+ create_url_test_case, delete_url_test_case, renew_url_test_case,
+ update_url_test_case, transfer_url_test_case, error_url_test_case].
%% Run Unit tests
-run_eunit(_Config) ->
- ok = eunit:test(epp_router_tests).
+request_method_test_case(_Config) ->
+ get = epp_router:request_method("hello"),
+ get = epp_router:request_method(<<"hello">>),
+ get = epp_router:request_method("error"),
+ get = epp_router:request_method(<<"error">>),
+ post = epp_router:request_method("create"),
+ post = epp_router:request_method(123),
+ ok.
+
+%% TODO: Make less verbose and repetitive
+hello_url_test_case(_Config) ->
+ "http://localhost:9292/session/hello" = epp_router:route_request("hello"),
+ "http://localhost:9292/session/hello" = epp_router:route_request(<<"hello">>),
+ ok.
+
+login_url_test_case(_Config) ->
+ "http://localhost:9292/session/login" = epp_router:route_request("login"),
+ "http://localhost:9292/session/login" = epp_router:route_request(<<"login">>),
+ ok.
+
+logout_url_test_case(_Config) ->
+ "http://localhost:9292/session/logout" = epp_router:route_request("logout"),
+ "http://localhost:9292/session/logout" = epp_router:route_request(<<"logout">>),
+ ok.
+
+check_url_test_case(_Config) ->
+ "http://localhost:9292/command/check" = epp_router:route_request("check"),
+ "http://localhost:9292/command/check" = epp_router:route_request(<<"check">>),
+ ok.
+
+info_url_test_case(_Config) ->
+ "http://localhost:9292/command/info" = epp_router:route_request("info"),
+ "http://localhost:9292/command/info" = epp_router:route_request(<<"info">>),
+ ok.
+
+poll_url_test_case(_Config) ->
+ "http://localhost:9292/command/poll" = epp_router:route_request("poll"),
+ "http://localhost:9292/command/poll" = epp_router:route_request(<<"poll">>),
+ ok.
+
+create_url_test_case(_Config) ->
+ "http://localhost:9292/command/create" = epp_router:route_request("create"),
+ "http://localhost:9292/command/create" = epp_router:route_request(<<"create">>),
+ ok.
+
+delete_url_test_case(_Config) ->
+ "http://localhost:9292/command/delete" = epp_router:route_request("delete"),
+ "http://localhost:9292/command/delete" = epp_router:route_request(<<"delete">>),
+ ok.
+
+renew_url_test_case(_Config) ->
+ "http://localhost:9292/command/renew" = epp_router:route_request("renew"),
+ "http://localhost:9292/command/renew" = epp_router:route_request(<<"renew">>),
+ ok.
+
+update_url_test_case(_Config) ->
+ "http://localhost:9292/command/update" = epp_router:route_request("update"),
+ "http://localhost:9292/command/update" = epp_router:route_request(<<"update">>),
+ ok.
+
+transfer_url_test_case(_Config) ->
+ "http://localhost:9292/command/transfer" = epp_router:route_request("transfer"),
+ "http://localhost:9292/command/transfer" = epp_router:route_request(<<"transfer">>),
+ ok.
+
+error_url_test_case(_Config) ->
+ "http://localhost:9292/error" = epp_router:route_request("error"),
+ "http://localhost:9292/error" = epp_router:route_request(<<"error">>),
+ ok.
diff --git a/apps/epp_proxy/test/epp_router_tests.erl b/apps/epp_proxy/test/epp_router_tests.erl
deleted file mode 100644
index 6bf75e3..0000000
--- a/apps/epp_proxy/test/epp_router_tests.erl
+++ /dev/null
@@ -1,60 +0,0 @@
--module(epp_router_tests).
-
--include_lib("eunit/include/eunit.hrl").
-
-request_method_test() ->
- ?assertEqual(get, epp_router:request_method("hello")),
- ?assertEqual(get, epp_router:request_method(<<"hello">>)),
- ?assertEqual(get, epp_router:request_method("error")),
- ?assertEqual(get, epp_router:request_method(<<"error">>)),
- ?assertEqual(post, epp_router:request_method("create")),
- ?assertEqual(post, epp_router:request_method(123)).
-
-%% TODO: Make less verbose and repetitive
-hello_url_test() ->
- ?assertEqual("https://registry.test/epp/session/hello", epp_router:route_request("hello")),
- ?assertEqual("https://registry.test/epp/session/hello", epp_router:route_request(<<"hello">>)).
-
-login_url_test() ->
- ?assertEqual("https://registry.test/epp/session/login", epp_router:route_request("login")),
- ?assertEqual("https://registry.test/epp/session/login", epp_router:route_request(<<"login">>)).
-
-logout_url_test() ->
- ?assertEqual("https://registry.test/epp/session/logout", epp_router:route_request("logout")),
- ?assertEqual("https://registry.test/epp/session/logout", epp_router:route_request(<<"logout">>)).
-
-check_url_test() ->
- ?assertEqual("https://registry.test/epp/command/check", epp_router:route_request("check")),
- ?assertEqual("https://registry.test/epp/command/check", epp_router:route_request(<<"check">>)).
-
-info_url_test() ->
- ?assertEqual("https://registry.test/epp/command/info", epp_router:route_request("info")),
- ?assertEqual("https://registry.test/epp/command/info", epp_router:route_request(<<"info">>)).
-
-poll_url_test() ->
- ?assertEqual("https://registry.test/epp/command/poll", epp_router:route_request("poll")),
- ?assertEqual("https://registry.test/epp/command/poll", epp_router:route_request(<<"poll">>)).
-
-create_url_test() ->
- ?assertEqual("https://registry.test/epp/command/create", epp_router:route_request("create")),
- ?assertEqual("https://registry.test/epp/command/create", epp_router:route_request(<<"create">>)).
-
-delete_url_test() ->
- ?assertEqual("https://registry.test/epp/command/delete", epp_router:route_request("delete")),
- ?assertEqual("https://registry.test/epp/command/delete", epp_router:route_request(<<"delete">>)).
-
-renew_url_test() ->
- ?assertEqual("https://registry.test/epp/command/renew", epp_router:route_request("renew")),
- ?assertEqual("https://registry.test/epp/command/renew", epp_router:route_request(<<"renew">>)).
-
-update_url_test() ->
- ?assertEqual("https://registry.test/epp/command/update", epp_router:route_request("update")),
- ?assertEqual("https://registry.test/epp/command/update", epp_router:route_request(<<"update">>)).
-
-transfer_url_test() ->
- ?assertEqual("https://registry.test/epp/command/transfer", epp_router:route_request("transfer")),
- ?assertEqual("https://registry.test/epp/command/transfer", epp_router:route_request(<<"transfer">>)).
-
-error_url_test() ->
- ?assertEqual("https://registry.test/epp/error", epp_router:route_request("error")),
- ?assertEqual("https://registry.test/epp/error", epp_router:route_request(<<"error">>)).
diff --git a/apps/epp_proxy/test/epp_util_SUITE.erl b/apps/epp_proxy/test/epp_util_SUITE.erl
index 9294d3d..dd0e252 100644
--- a/apps/epp_proxy/test/epp_util_SUITE.erl
+++ b/apps/epp_proxy/test/epp_util_SUITE.erl
@@ -3,11 +3,77 @@
-include_lib("common_test/include/ct.hrl").
-export([all/0]).
--export([run_eunit/1]).
+-export([session_id_test_case/1,
+ create_map_test_case/1,
+ create_session_id_test_case/1,
+ frame_length_test_case/1,
+ frame_length_to_receive_test_case/1,
+ frame_length_to_send_test_case/1,
+ readable_ip_test_case/1,
+ path_for_file_test_case/1]).
-all() -> [run_eunit].
+all() -> [session_id_test_case,
+ create_map_test_case,
+ create_session_id_test_case,
+ frame_length_test_case,
+ frame_length_to_receive_test_case,
+ frame_length_to_send_test_case,
+ readable_ip_test_case,
+ path_for_file_test_case].
-%% Run Unit tests.
%% Todo: these should be property tests, not unit tests.
-run_eunit(_Config) ->
- ok = eunit:test(epp_util_tests).
+session_id_test_case(_Config) ->
+ Pid = spawn(fun () -> ok end),
+ SessionId = epp_util:session_id(Pid),
+ true = is_list(SessionId),
+ true = length(SessionId) > 0,
+ ok.
+
+create_map_test_case(_Config) ->
+ Pid = spawn(fun () -> ok end),
+ Map = epp_util:create_map(Pid),
+ Pid = maps:get("pid", Map),
+ true = is_list(maps:get("timestamp", Map)),
+ true = is_float(maps:get("random", Map)),
+ ok.
+
+create_session_id_test_case(_Config) ->
+ Pid = list_to_pid("<0.130.0>"),
+ Random = 0.7131518292439796,
+ Time = "2019-05-23T14:47:52+03:00",
+ Map = #{"pid" => Pid, "random" => Random, "timestamp" => Time},
+ Hash = epp_util:create_session_id(Map),
+ true = is_list(Hash),
+ "88F49C2B1BDD6F2355BF4424A67C928DA7C5616B30F7C5B35F17747348AF61EF8723ED6BE6012D879CB3D6A7EC7A187660A56910ED896AE67DE533C212D" = Hash,
+ ok.
+
+frame_length_test_case(_Config) ->
+ 2 = epp_util:frame_length("aa"),
+ 2 = epp_util:frame_length(<<"aa">>),
+ 2 = epp_util:frame_length(<<"OÜ">>),
+ ok.
+
+frame_length_to_receive_test_case(_Config) ->
+ 2 = epp_util:frame_length_to_receive(6),
+ 0 = epp_util:frame_length_to_receive(4),
+ {'EXIT', {function_clause, _}} =
+ (catch epp_util:frame_length_to_receive(-22)),
+ ok.
+
+frame_length_to_send_test_case(_Config) ->
+ 18 = epp_util:frame_length_to_send(""),
+ 4 = epp_util:frame_length_to_send(""),
+ ok.
+
+readable_ip_test_case(_Config) ->
+ <<"127.0.0.1">> = epp_util:readable_ip({127,0,0,1}),
+ {'EXIT', {function_clause, _}}
+ = (catch epp_util:readable_ip({127,0,0,1,0})),
+ ok.
+
+path_for_file_test_case(_Config) ->
+ AbsoluteFilename = "/usr/bin",
+ AbsoluteFilename = epp_util:path_for_file(AbsoluteFilename),
+ RelativeFilename = "usr/bin",
+ RelativeFilename =:= epp_util:path_for_file(RelativeFilename),
+ ok.
diff --git a/apps/epp_proxy/test/epp_util_tests.erl b/apps/epp_proxy/test/epp_util_tests.erl
deleted file mode 100644
index 0e0fd48..0000000
--- a/apps/epp_proxy/test/epp_util_tests.erl
+++ /dev/null
@@ -1,43 +0,0 @@
--module(epp_util_tests).
-
--include_lib("eunit/include/eunit.hrl").
-
-session_id_test() ->
- Pid = spawn(fun () -> ok end),
- SessionId = epp_util:session_id(Pid),
- ?assert(is_list(SessionId)),
- ?assert(length(SessionId) > 0).
-
-create_map_test() ->
- Pid = spawn(fun () -> ok end),
- Map = epp_util:create_map(Pid),
- ?assertEqual(Pid, maps:get("pid", Map)),
- ?assert(is_list(maps:get("timestamp", Map))),
- ?assert(is_float(maps:get("random", Map))).
-
-create_session_id_test() ->
- Pid = list_to_pid("<0.130.0>"),
- Random = 0.7131518292439796,
- Time = "2019-05-23T14:47:52+03:00",
- Map = #{"pid" => Pid, "random" => Random, "timestamp" => Time},
- Hash = epp_util:create_session_id(Map),
- ?assert(is_list(Hash)),
- ?assertEqual("88F49C2B1BDD6F2355BF4424A67C928DA7C5616B30F7C5B35F17747348AF61EF8723ED6BE6012D879CB3D6A7EC7A187660A56910ED896AE67DE533C212D", Hash).
-
-frame_length_test() ->
- ?assertEqual(2, epp_util:frame_length("aa")),
- ?assertEqual(2, epp_util:frame_length(<<"aa">>)),
- ?assertEqual(2, epp_util:frame_length(<<"OÜ">>)).
-
-frame_length_to_receive_test() ->
- ?assertEqual(2, epp_util:frame_length_to_receive(6)),
- ?assertEqual(0, epp_util:frame_length_to_receive(4)),
- ?assertError(function_clause, epp_util:frame_length_to_receive(-22)).
-
-frame_length_to_send_test() ->
- ?assertEqual(18, epp_util:frame_length_to_send("")),
- ?assertEqual(4, epp_util:frame_length_to_send("")).
-
-readable_ip_test() ->
- ?assertEqual(<<"127.0.0.1">>, epp_util:readable_ip({127,0,0,1})),
- ?assertError(function_clause, epp_util:readable_ip({127,0,0,1,0})).
diff --git a/apps/epp_proxy/test/epp_xml_SUITE.erl b/apps/epp_proxy/test/epp_xml_SUITE.erl
index cabc12c..9341817 100644
--- a/apps/epp_proxy/test/epp_xml_SUITE.erl
+++ b/apps/epp_proxy/test/epp_xml_SUITE.erl
@@ -2,11 +2,125 @@
-include_lib("common_test/include/ct.hrl").
+%% This is required for parse tests.
+-include_lib("xmerl/include/xmerl.hrl").
+
+-define(sampleCommandList,
+ "
+
+
+ test
+ test
+
+ sample1trid
+
+ ").
+
+-define(validXMLNotEPPList,
+ "
+ test
+ test@test.com
+ ").
+
-export([all/0]).
--export([run_eunit/1]).
+-export([parse_not_a_list_or_binary_test_case/1,
+ parse_sample_valid_xml_binary_test_case/1,
+ parse_sample_valid_xml_list_test_case/1,
+ parse_sample_invalid_xml_binary_test_case/1,
+ parse_sample_invalid_xml_list_test_case/1,
+ find_cltrid_binary_test_case/1,
+ find_cltrid_empty_binary_test_case/1,
+ find_cltrid_empty_list_test_case/1,
+ find_cltrid_list_test_case/1,
+ find_cltrid_atom_test_case/1,
+ get_command_success_test_case/1,
+ get_command_xml_not_epp_failure_test_case/1,
+ get_command_failure_test_case/1]).
-all() -> [run_eunit].
+all() -> [parse_not_a_list_or_binary_test_case,
+ parse_sample_valid_xml_binary_test_case,
+ parse_sample_valid_xml_list_test_case,
+ parse_sample_invalid_xml_binary_test_case,
+ parse_sample_invalid_xml_list_test_case,
+ find_cltrid_binary_test_case,
+ find_cltrid_empty_binary_test_case,
+ find_cltrid_empty_list_test_case,
+ find_cltrid_list_test_case,
+ find_cltrid_atom_test_case,
+ get_command_success_test_case,
+ get_command_xml_not_epp_failure_test_case,
+ get_command_failure_test_case].
-%% Run Unit tests
-run_eunit(_Config) ->
- ok = eunit:test(epp_xml_tests).
+parse_not_a_list_or_binary_test_case(_Config) ->
+ Input = 1234,
+ ExpectedOutput = {error, {fatal, {expected_binary_or_list}}},
+ ExpectedOutput = epp_xml:parse(Input),
+ ok.
+
+parse_sample_valid_xml_list_test_case(_Config) ->
+ Input = ?sampleCommandList,
+ {ok, Record} = epp_xml:parse(Input),
+ true = is_record(Record, xmlElement),
+ ok.
+
+parse_sample_valid_xml_binary_test_case(_Config) ->
+ Input = list_to_binary(?sampleCommandList),
+ {ok, Record} = epp_xml:parse(Input),
+ true = is_record(Record, xmlElement),
+ ok.
+
+parse_sample_invalid_xml_list_test_case(_Config) ->
+ Input = "Some text",
+ {error, {fatal, _Details}} = epp_xml:parse(Input),
+ ok.
+
+parse_sample_invalid_xml_binary_test_case(_Config) ->
+ Input = list_to_binary("Some text"),
+ {error, {fatal, _Details}} = epp_xml:parse(Input),
+ ok.
+
+%% find_cltrid
+find_cltrid_empty_list_test_case(_Config) ->
+ Input = "",
+ nomatch = epp_xml:find_cltrid(Input),
+ ok.
+
+find_cltrid_list_test_case(_Config) ->
+ Input = list_to_binary(?sampleCommandList),
+ <<"sample1trid">> = epp_xml:find_cltrid(Input),
+ ok.
+
+find_cltrid_empty_binary_test_case(_Config) ->
+ Input = <<"">>,
+ nomatch = epp_xml:find_cltrid(Input),
+ ok.
+
+find_cltrid_binary_test_case(_Config) ->
+ Input = ?sampleCommandList,
+ <<"sample1trid">> = epp_xml:find_cltrid(Input),
+ ok.
+
+find_cltrid_atom_test_case(_Config) ->
+ Input = atom,
+ nomatch = epp_xml:find_cltrid(Input),
+ ok.
+
+%% get_command
+get_command_success_test_case(_Config) ->
+ %% We require an existing xlmElement record to pass around.
+ {ok, XMLElement} = epp_xml:parse(?sampleCommandList),
+ Command = epp_xml:get_command(XMLElement),
+ "login" = Command,
+ ok.
+
+get_command_xml_not_epp_failure_test_case(_Config) ->
+ {ok, XMLElement} = epp_xml:parse(?validXMLNotEPPList),
+ Command = epp_xml:get_command(XMLElement),
+ undefined = Command,
+ ok.
+
+get_command_failure_test_case(_Config) ->
+ %% Can pass any garbage, should get back undefined.,
+ Command = epp_xml:get_command("Some random string"),
+ undefined = Command,
+ ok.
diff --git a/apps/epp_proxy/test/epp_xml_tests.erl b/apps/epp_proxy/test/epp_xml_tests.erl
deleted file mode 100644
index 260625d..0000000
--- a/apps/epp_proxy/test/epp_xml_tests.erl
+++ /dev/null
@@ -1,80 +0,0 @@
--module(epp_xml_tests).
-
--include_lib("eunit/include/eunit.hrl").
-%% This is required for parse tests.
--include_lib("xmerl/include/xmerl.hrl").
-
--define(sampleCommandList,
- "
-
-
- test
- test
-
- sample1trid
-
- ").
-
--define(validXMLNotEPPList,
- "
- test
- test@test.com
- ").
-
-%% parse
-parse_not_a_list_or_binary_test() ->
- Input = 1234,
- ExpectedOutput = {error, {fatal, {expected_binary_or_list}}},
- ?assertEqual(ExpectedOutput, epp_xml:parse(Input)).
-
-parse_sample_valid_xml_list_test() ->
- Input = ?sampleCommandList,
- {ok, Record} = epp_xml:parse(Input),
- ?assert(is_record(Record, xmlElement)).
-
-parse_sample_valid_xml_binary_test() ->
- Input = list_to_binary(?sampleCommandList),
- {ok, Record} = epp_xml:parse(Input),
- ?assert(is_record(Record, xmlElement)).
-
-parse_sample_invalid_xml_list_test() ->
- Input = "Some text",
- {error, {fatal, _Details}} = epp_xml:parse(Input).
-
-parse_sample_invalid_xml_binary_test() ->
- Input = list_to_binary("Some text"),
- {error, {fatal, _Details}} = epp_xml:parse(Input).
-
-%% find_cltrid
-find_cltrid_empty_list_test() ->
- Input = "",
- ?assertEqual(nomatch, epp_xml:find_cltrid(Input)).
-
-find_cltrid_list_test() ->
- Input = list_to_binary(?sampleCommandList),
- ?assertEqual(<<"sample1trid">>, epp_xml:find_cltrid(Input)).
-
-find_cltrid_empty_binary_test() ->
- Input = <<"">>,
- ?assertEqual(nomatch, epp_xml:find_cltrid(Input)).
-
-find_cltrid_binary_test() ->
- Input = ?sampleCommandList,
- ?assertEqual(<<"sample1trid">>, epp_xml:find_cltrid(Input)).
-
-%% get_command
-get_command_success_test() ->
- %% We require an existing xlmElement record to pass around.
- {ok, XMLElement} = epp_xml:parse(?sampleCommandList),
- Command = epp_xml:get_command(XMLElement),
- ?assertEqual("login", Command).
-
-get_command_xml_not_epp_failure_test() ->
- {ok, XMLElement} = epp_xml:parse(?validXMLNotEPPList),
- Command = epp_xml:get_command(XMLElement),
- ?assertEqual(undefined, Command).
-
-get_command_failure_test() ->
- %% Can pass any garbage, should get back undefined.,
- Command = epp_xml:get_command("Some random string"),
- ?assertEqual(undefined, Command).
diff --git a/apps/epp_proxy/test/tcp_client_SUITE.erl b/apps/epp_proxy/test/tcp_client_SUITE.erl
new file mode 100644
index 0000000..f4384ec
--- /dev/null
+++ b/apps/epp_proxy/test/tcp_client_SUITE.erl
@@ -0,0 +1,184 @@
+-module(tcp_client_SUITE).
+
+-include("epp_proxy.hrl").
+-include_lib("common_test/include/ct.hrl").
+
+-export([all/0]).
+-export([init_per_suite/1, end_per_suite/1]).
+-export([frame_size_test_case/1,
+ greetings_test_case/1,
+ session_test_case/1,
+ valid_command_test_case/1,
+ invalid_command_test_case/1,
+ error_test_case/1]).
+
+all() ->
+ [frame_size_test_case,
+ greetings_test_case,
+ session_test_case,
+ valid_command_test_case,
+ invalid_command_test_case,
+ error_test_case].
+
+init_per_suite(Config) ->
+ application:ensure_all_started(epp_proxy),
+ application:ensure_all_started(hackney),
+ Options = [binary,
+ {active, false}],
+ [{tcp_options, Options} | Config].
+
+end_per_suite(Config) ->
+ application:stop(epp_proxy),
+ application:stop(hackney),
+ Config.
+
+%% Test Cases
+frame_size_test_case(Config) ->
+ Options = proplists:get_value(tcp_options, Config),
+ {ok, Socket} = gen_tcp:connect("localhost", 1180, Options, 2000),
+ {ok, Data} = gen_tcp:recv(Socket, 0, 1200),
+ true = (byte_size(Data) =:= length_of_data(Data)),
+ ok.
+
+greetings_test_case(Config) ->
+ Options = proplists:get_value(tcp_options, Config),
+ {ok, Socket} = gen_tcp:connect("localhost", 1180, Options, 2000),
+ Data = receive_data(Socket),
+ match_data(Data, ""),
+ ok.
+
+session_test_case(Config) ->
+ Options = proplists:get_value(tcp_options, Config),
+ {ok, Socket} = gen_tcp:connect("localhost", 1180, Options, 2000),
+ _Data = receive_data(Socket),
+ ok = send_data(login_command(), Socket),
+ LoginResponse = receive_data(Socket),
+ match_data(LoginResponse, "Command completed successfully"),
+ match_data(LoginResponse, "ccReg-5886259930"),
+ LogoutCommand =
+ <<"\n"
+ "\n"
+ "\n"
+ "\n"
+ "test_bestnames\n"
+ "testtest\n"
+ "\n"
+ "1.0\n"
+ "en\n"
+ "\n"
+ "\n"
+ "https://epp.tld.ee/schema/domain-eis-1.0.xsd\n"
+ "https://epp.tld.ee/schema/contact-ee-1.1.xsd\n"
+ "urn:ietf:params:xml:ns:host-1.0\n"
+ "urn:ietf:params:xml:ns:keyrelay-1.0\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n">>,
+ ok = send_data(LogoutCommand, Socket),
+ LogoutResponse = receive_data(Socket),
+ match_data(LogoutResponse,
+ "Command completed successfully; ending session"),
+ %% After receiving logout, connection should be closed.
+ {error, closed} = receive_data(Socket),
+ ok.
+
+valid_command_test_case(Config) ->
+ Options = proplists:get_value(tcp_options, Config),
+ {ok, Socket} = gen_tcp:connect("localhost", 1180, Options, 2000),
+ _Data = receive_data(Socket),
+ ok = send_data(login_command(), Socket),
+ _LoginResponse = receive_data(Socket),
+ PollCommand =
+ <<"\n"
+ "\n"
+ "\n"
+ "\n"
+ "foo bar baz\n"
+ "\n"
+ "\n">>,
+ ok = send_data(PollCommand, Socket),
+ PollResponse = receive_data(Socket),
+ match_data(PollResponse,
+ "Command completed successfully; no messages"),
+ ok.
+
+%% Sending an invalid command frame should close the connection.
+%% It also crashes the process.
+invalid_command_test_case(Config) ->
+ Options = proplists:get_value(tcp_options, Config),
+ {ok, Socket} = gen_tcp:connect("localhost", 1180, Options, 2000),
+ _Data = receive_data(Socket),
+ ok = send_data(login_command(), Socket),
+ _LoginResponse = receive_data(Socket),
+ InvalidCommand =
+ <<"\n"
+ "\n"
+ "\n"
+ "\n"
+ "foo bar baz\n"
+ "\n"
+ "\n">>,
+ ok = send_data(InvalidCommand, Socket),
+ {error, closed} = receive_data(Socket),
+ ok.
+
+error_test_case(Config) ->
+ Options = proplists:get_value(tcp_options, Config),
+ {ok, Socket} = gen_tcp:connect("localhost", 1180, Options, 2000),
+ _Data = receive_data(Socket),
+ ok = send_data(login_command(), Socket),
+ _LoginResponse = receive_data(Socket),
+ InvalidXml =
+ <<"\n">>,
+ ok = send_data(InvalidXml, Socket),
+ ErrorResponse = receive_data(Socket),
+ match_data(ErrorResponse,
+ "Command syntax error."),
+ ok.
+
+%% Helper functions:
+length_of_data(Data) ->
+ EPPEnvelope = binary:part(Data, {0, 4}),
+ ReportedLength = binary:decode_unsigned(EPPEnvelope, big),
+ ReportedLength.
+
+send_data(Message, Socket) ->
+ Length = epp_util:frame_length_to_send(Message),
+ ByteSize = <>,
+ CompleteMessage = <>,
+ ok = gen_tcp:send(Socket, CompleteMessage).
+
+receive_data(Socket) ->
+ case gen_tcp:recv(Socket, 0, 1200) of
+ {error, Reason} -> {error, Reason};
+ {ok, Data } ->
+ EppEnvelope = binary:part(Data, {0, 4}),
+ ReportedLength = binary:decode_unsigned(EppEnvelope, big),
+ binary:part(Data, {byte_size(Data), 4 - ReportedLength})
+ end.
+
+match_data(Data, Pattern) ->
+ {ok, MatchPattern} = re:compile(Pattern),
+ {match, _Captured} = re:run(Data, MatchPattern).
+
+login_command() ->
+ <<"\n"
+ "\n"
+ "\n"
+ "\n"
+ "test_bestnames\n"
+ "testtest\n"
+ "\n"
+ "1.0\n"
+ "en\n"
+ "\n"
+ "\n"
+ "https://epp.tld.ee/schema/domain-eis-1.0.xsd\n"
+ "https://epp.tld.ee/schema/contact-ee-1.1.xsd\n"
+ "urn:ietf:params:xml:ns:host-1.0\n"
+ "urn:ietf:params:xml:ns:keyrelay-1.0\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n">>.
diff --git a/apps/epp_proxy/test/tls_client_SUITE.erl b/apps/epp_proxy/test/tls_client_SUITE.erl
new file mode 100644
index 0000000..0c60217
--- /dev/null
+++ b/apps/epp_proxy/test/tls_client_SUITE.erl
@@ -0,0 +1,187 @@
+-module(tls_client_SUITE).
+
+-include("epp_proxy.hrl").
+-include_lib("common_test/include/ct.hrl").
+
+-export([all/0]).
+-export([init_per_suite/1, end_per_suite/1]).
+-export([frame_size_test_case/1,
+ greetings_test_case/1,
+ session_test_case/1,
+ valid_command_test_case/1,
+ invalid_command_test_case/1,
+ error_test_case/1]).
+
+all() ->
+ [frame_size_test_case,
+ greetings_test_case,
+ session_test_case,
+ valid_command_test_case,
+ invalid_command_test_case,
+ error_test_case].
+
+init_per_suite(Config) ->
+ application:ensure_all_started(epp_proxy),
+ application:ensure_all_started(hackney),
+ CWD = code:priv_dir(epp_proxy),
+ Options = [binary,
+ {certfile, filename:join(CWD, "test_ca/certs/webclient.crt.pem")},
+ {keyfile, filename:join(CWD, "test_ca/private/webclient.key.pem")},
+ {active, false}],
+ [{ssl_options, Options} | Config].
+
+end_per_suite(Config) ->
+ application:stop(epp_proxy),
+ application:stop(hackney),
+ Config.
+
+%% Test Cases
+frame_size_test_case(Config) ->
+ Options = proplists:get_value(ssl_options, Config),
+ {ok, Socket} = ssl:connect("localhost", 1443, Options, 2000),
+ {ok, Data} = ssl:recv(Socket, 0, 1200),
+ true = (byte_size(Data) =:= length_of_data(Data)),
+ ok.
+
+greetings_test_case(Config) ->
+ Options = proplists:get_value(ssl_options, Config),
+ {ok, Socket} = ssl:connect("localhost", 1443, Options, 2000),
+ Data = receive_data(Socket),
+ match_data(Data, ""),
+ ok.
+
+session_test_case(Config) ->
+ Options = proplists:get_value(ssl_options, Config),
+ {ok, Socket} = ssl:connect("localhost", 1443, Options, 2000),
+ _Data = receive_data(Socket),
+ ok = send_data(login_command(), Socket),
+ LoginResponse = receive_data(Socket),
+ match_data(LoginResponse, "Command completed successfully"),
+ match_data(LoginResponse, "ccReg-5886259930"),
+ LogoutCommand =
+ <<"\n"
+ "\n"
+ "\n"
+ "\n"
+ "test_bestnames\n"
+ "testtest\n"
+ "\n"
+ "1.0\n"
+ "en\n"
+ "\n"
+ "\n"
+ "https://epp.tld.ee/schema/domain-eis-1.0.xsd\n"
+ "https://epp.tld.ee/schema/contact-ee-1.1.xsd\n"
+ "urn:ietf:params:xml:ns:host-1.0\n"
+ "urn:ietf:params:xml:ns:keyrelay-1.0\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n">>,
+ ok = send_data(LogoutCommand, Socket),
+ LogoutResponse = receive_data(Socket),
+ match_data(LogoutResponse,
+ "Command completed successfully; ending session"),
+ %% After receiving logout, connection should be closed.
+ {error, closed} = receive_data(Socket),
+ ok.
+
+valid_command_test_case(Config) ->
+ Options = proplists:get_value(ssl_options, Config),
+ {ok, Socket} = ssl:connect("localhost", 1443, Options, 2000),
+ _Data = receive_data(Socket),
+ ok = send_data(login_command(), Socket),
+ _LoginResponse = receive_data(Socket),
+ PollCommand =
+ <<"\n"
+ "\n"
+ "\n"
+ "\n"
+ "foo bar baz\n"
+ "\n"
+ "\n">>,
+ ok = send_data(PollCommand, Socket),
+ PollResponse = receive_data(Socket),
+ match_data(PollResponse,
+ "Command completed successfully; no messages"),
+ ok.
+
+%% Sending an invalid command frame should close the connection.
+%% It also crashes the process.
+invalid_command_test_case(Config) ->
+ Options = proplists:get_value(ssl_options, Config),
+ {ok, Socket} = ssl:connect("localhost", 1443, Options, 2000),
+ _Data = receive_data(Socket),
+ ok = send_data(login_command(), Socket),
+ _LoginResponse = receive_data(Socket),
+ InvalidCommand =
+ <<"\n"
+ "\n"
+ "\n"
+ "\n"
+ "foo bar baz\n"
+ "\n"
+ "\n">>,
+ ok = send_data(InvalidCommand, Socket),
+ {error, closed} = receive_data(Socket),
+ ok.
+
+error_test_case(Config) ->
+ Options = proplists:get_value(ssl_options, Config),
+ {ok, Socket} = ssl:connect("localhost", 1443, Options, 2000),
+ _Data = receive_data(Socket),
+ ok = send_data(login_command(), Socket),
+ _LoginResponse = receive_data(Socket),
+ InvalidXml =
+ <<"\n">>,
+ ok = send_data(InvalidXml, Socket),
+ ErrorResponse = receive_data(Socket),
+ match_data(ErrorResponse,
+ "Command syntax error."),
+ ok.
+
+%% Helper functions:
+length_of_data(Data) ->
+ EPPEnvelope = binary:part(Data, {0, 4}),
+ ReportedLength = binary:decode_unsigned(EPPEnvelope, big),
+ ReportedLength.
+
+send_data(Message, Socket) ->
+ Length = epp_util:frame_length_to_send(Message),
+ ByteSize = <>,
+ CompleteMessage = <>,
+ ok = ssl:send(Socket, CompleteMessage).
+
+receive_data(Socket) ->
+ case ssl:recv(Socket, 0, 1200) of
+ {error, Reason} -> {error, Reason};
+ {ok, Data } ->
+ EppEnvelope = binary:part(Data, {0, 4}),
+ ReportedLength = binary:decode_unsigned(EppEnvelope, big),
+ binary:part(Data, {byte_size(Data), 4 - ReportedLength})
+ end.
+
+match_data(Data, Pattern) ->
+ {ok, MatchPattern} = re:compile(Pattern),
+ {match, _Captured} = re:run(Data, MatchPattern).
+
+login_command() ->
+ <<"\n"
+ "\n"
+ "\n"
+ "\n"
+ "test_bestnames\n"
+ "testtest\n"
+ "\n"
+ "1.0\n"
+ "en\n"
+ "\n"
+ "\n"
+ "https://epp.tld.ee/schema/domain-eis-1.0.xsd\n"
+ "https://epp.tld.ee/schema/contact-ee-1.1.xsd\n"
+ "urn:ietf:params:xml:ns:host-1.0\n"
+ "urn:ietf:params:xml:ns:keyrelay-1.0\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n">>.
diff --git a/config/docker.config b/config/docker.config
index 1b97d6c..e3073a5 100644
--- a/config/docker.config
+++ b/config/docker.config
@@ -3,9 +3,9 @@
{dev_mode, true},
{tcp_port, 3333},
{tls_port, 700},
- {epp_session_url, "http://httpd:3000/epp/session/"},
- {epp_command_url, "http://httpd:3000/epp/command/"},
- {epp_error_url, "http://httpd:3000/epp/error/"},
+ {epp_session_url, "http://epp:3000/epp/session/"},
+ {epp_command_url, "http://epp:3000/epp/command/"},
+ {epp_error_url, "http://epp:3000/epp/error/"},
{cacertfile_path, "/opt/ca/certs/ca.crt.pem"},
{certfile_path, "/opt/ca/certs/apache.crt"},
{keyfile_path, "/opt/ca/private/apache.key"},
diff --git a/config/test.config b/config/test.config
index dae8f0c..921619e 100644
--- a/config/test.config
+++ b/config/test.config
@@ -1,11 +1,22 @@
[
- {epp_proxy, [{dev_mode, false},
- {tcp_port, 3333},
- {tls_port, 4444},
- {epp_session_url, "https://registry.test/epp/session/"},
- {epp_command_url, "https://registry.test/epp/command/"},
- {epp_error_url, "https://registry.test/epp/error/"},
- {cacertfile_path, "/opt/shared/ca/certs/ca.crt.pem"},
- {certfile_path, "/opt/shared/ca/certs/apache.crt"},
- {keyfile_path, "/opt/shared/ca/private/apache.key"}]}
+ {epp_proxy, [{dev_mode, true},
+ {tcp_port, 1180},
+ {tls_port, 1443},
+
+ {epp_session_url, "http://localhost:9292/session/"},
+ {epp_command_url, "http://localhost:9292/command/"},
+ {epp_error_url, "http://localhost:9292/error/"},
+ %% Path to root CA that should check the client certificates.
+ {cacertfile_path, "test_ca/certs/ca.crt.pem"},
+ {certfile_path, "test_ca/certs/apache.crt"},
+ {keyfile_path, "test_ca/private/apache.key"},
+ {crlfile_path, "test_ca/crl/crl.pem"}]},
+
+
+ {lager, [
+ {handlers, [
+ {lager_console_backend, [{level, warning}]}
+ %% {lager_syslog_backend, ["epp_proxy", local0, debug]}
+ ]}
+ ]}
].