You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2020/08/31 15:53:40 UTC

[ignite] 01/02: IGNITE-12718 pyignite: added SSL keyfile password argument. (#7480)

This is an automated email from the ASF dual-hosted git repository.

alexpl pushed a commit to branch ignite-2.9
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit 455bb285509e811bbbbdac3cbd32261fb9deebaa
Author: Andrey Kuznetsov <st...@gmail.com>
AuthorDate: Mon Aug 31 15:16:25 2020 +0300

    IGNITE-12718 pyignite: added SSL keyfile password argument. (#7480)
    
    Co-authored-by: Nikolay Izhikov <ni...@apache.org>
    (cherry picked from commit baf8c673c41a1790ef0a244862e6abfbd4eadbf5)
---
 .../config/ssl/generate_certificates.sh            |  18 +++++--
 .../python/pyignite/connection/__init__.py         |   4 ++
 .../platforms/python/pyignite/connection/ssl.py    |  40 ++++++++------
 modules/platforms/python/tests/config/ssl.xml      |  58 +++++++++++++++++++++
 .../platforms/python/tests/config/ssl/README.txt   |   3 ++
 .../python/tests/config/ssl/client_full.pem        |  52 ++++++++++++++++++
 .../tests/config/ssl/client_with_pass_full.pem     |  54 +++++++++++++++++++
 .../platforms/python/tests/config/ssl/server.jks   | Bin 0 -> 2380 bytes
 .../platforms/python/tests/config/ssl/trust.jks    | Bin 0 -> 1346 bytes
 modules/platforms/python/tests/conftest.py         |  11 +++-
 modules/platforms/python/tests/test_handshake.py   |   3 +-
 11 files changed, 221 insertions(+), 22 deletions(-)

diff --git a/modules/platforms/cpp/thin-client-test/config/ssl/generate_certificates.sh b/modules/platforms/cpp/thin-client-test/config/ssl/generate_certificates.sh
index 5e8303a..e4f41e2 100755
--- a/modules/platforms/cpp/thin-client-test/config/ssl/generate_certificates.sh
+++ b/modules/platforms/cpp/thin-client-test/config/ssl/generate_certificates.sh
@@ -34,7 +34,7 @@ function generate_ca {
     $OSSL req \
         -newkey rsa:2048 -nodes -sha256 -keyout $CA_KEY \
         -subj "/C=US/ST=Massachusetts/L=Wakefield/CN=ignite.apache.org/O=The Apache Software Foundation/OU=$OU/emailAddress=dev@ignite.apache.org" \
-        -x509 -days=3650 -out $CA_CRT
+        -x509 -days 3650 -out $CA_CRT
 }
 
 function generate_client_key_and_crt {
@@ -55,10 +55,15 @@ function generate_client_key_and_crt {
     # Signing client cerificate
     $OSSL x509 -req \
         -in $CLIENT_CSR -CA $CA_CRT -CAkey $CA_KEY -CAcreateserial \
-        -days=3650 -sha256 -out $CLIENT_CRT
+        -days 3650 -sha256 -out $CLIENT_CRT
 
     # Cleaning up.
     rm -f $CLIENT_CSR
+
+    # Protecting key with the password if required
+    if [ "$4" == "1" ]; then
+      openssl rsa -aes256 -in $CLIENT_KEY -passout pass:654321 -out $CLIENT_KEY
+    fi
 }
 
 function generate_jks {
@@ -89,13 +94,15 @@ function generate_jks {
 
 CA='ca'
 CLIENT='client'
+CLIENT_WITH_PASS='client_with_pass'
 SERVER='server'
 CA_UNKNOWN='ca_unknown'
 CLIENT_UNKNOWN='client_unknown'
 
 generate_ca $CA 'Apache Ignite CA'
-generate_client_key_and_crt $CA 'client' 'Apache Ignite Client Test'
-generate_client_key_and_crt $CA 'server' 'Apache Ignite Server Test'
+generate_client_key_and_crt $CA $CLIENT 'Apache Ignite Client Test'
+generate_client_key_and_crt $CA $CLIENT_WITH_PASS 'Apache Ignite Client Test' 1
+generate_client_key_and_crt $CA $SERVER 'Apache Ignite Server Test'
 
 # We won't sign up any other certs so we do not need CA key or srl
 rm -f "$CA.key" "$CA.srl"
@@ -110,10 +117,11 @@ rm -f $CA_UNKNOWN*
 
 # Re-naming everything as needed
 cat $CLIENT.key $CLIENT.crt > "$CLIENT"_full.pem
+cat $CLIENT_WITH_PASS.key $CLIENT_WITH_PASS.crt > "$CLIENT_WITH_PASS"_full.pem
 cat $CLIENT_UNKNOWN.key $CLIENT_UNKNOWN.crt > $CLIENT_UNKNOWN.pem
 mv $CA.jks trust.jks
 mv $CA.crt ca.pem
 
-rm -f $CLIENT.crt $CLIENT.key $CLIENT_UNKNOWN.key $CLIENT_UNKNOWN.crt $SERVER_KEY $SERVER_CRT
+rm -f $CLIENT.crt $CLIENT.key $CLIENT_WITH_PASS.key $CLIENT_WITH_PASS.crt $CLIENT_UNKNOWN.key $CLIENT_UNKNOWN.crt $SERVER_KEY $SERVER_CRT
 
 
diff --git a/modules/platforms/python/pyignite/connection/__init__.py b/modules/platforms/python/pyignite/connection/__init__.py
index 32decdf..1f6f0c0 100644
--- a/modules/platforms/python/pyignite/connection/__init__.py
+++ b/modules/platforms/python/pyignite/connection/__init__.py
@@ -77,6 +77,7 @@ class Connection:
             'ssl_ciphers',
             'ssl_cert_reqs',
             'ssl_keyfile',
+            'ssl_keyfile_password',
             'ssl_certfile',
             'ssl_ca_certfile',
             'username',
@@ -118,6 +119,9 @@ class Connection:
 
         :param ssl_keyfile: (optional) a path to SSL key file to identify
          local (client) party,
+        :param ssl_keyfile_password: (optional) password for SSL key file,
+         can be provided when key file is encrypted to prevent OpenSSL
+         password prompt,
         :param ssl_certfile: (optional) a path to ssl certificate file
          to identify local (client) party,
         :param ssl_ca_certfile: (optional) a path to a trusted certificate
diff --git a/modules/platforms/python/pyignite/connection/ssl.py b/modules/platforms/python/pyignite/connection/ssl.py
index 548ca7f..044b103 100644
--- a/modules/platforms/python/pyignite/connection/ssl.py
+++ b/modules/platforms/python/pyignite/connection/ssl.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 
 import ssl
+from ssl import SSLContext
 
 from pyignite.constants import *
 
@@ -21,19 +22,28 @@ from pyignite.constants import *
 def wrap(client, _socket):
     """ Wrap socket in SSL wrapper. """
     if client.init_kwargs.get('use_ssl', None):
-        _socket = ssl.wrap_socket(
-            _socket,
-            ssl_version=client.init_kwargs.get(
-                'ssl_version', SSL_DEFAULT_VERSION
-            ),
-            ciphers=client.init_kwargs.get(
-                'ssl_ciphers', SSL_DEFAULT_CIPHERS
-            ),
-            cert_reqs=client.init_kwargs.get(
-                'ssl_cert_reqs', ssl.CERT_NONE
-            ),
-            keyfile=client.init_kwargs.get('ssl_keyfile', None),
-            certfile=client.init_kwargs.get('ssl_certfile', None),
-            ca_certs=client.init_kwargs.get('ssl_ca_certfile', None),
-        )
+        keyfile = client.init_kwargs.get('ssl_keyfile', None)
+        certfile = client.init_kwargs.get('ssl_certfile', None)
+
+        if keyfile and not certfile:
+            raise ValueError("certfile must be specified")
+
+        password = client.init_kwargs.get('ssl_keyfile_password', None)
+        ssl_version = client.init_kwargs.get('ssl_version', SSL_DEFAULT_VERSION)
+        ciphers = client.init_kwargs.get('ssl_ciphers', SSL_DEFAULT_CIPHERS)
+        cert_reqs = client.init_kwargs.get('ssl_cert_reqs', ssl.CERT_NONE)
+        ca_certs = client.init_kwargs.get('ssl_ca_certfile', None)
+
+        context = SSLContext(ssl_version)
+        context.verify_mode = cert_reqs
+        
+        if ca_certs:
+            context.load_verify_locations(ca_certs)
+        if certfile:
+            context.load_cert_chain(certfile, keyfile, password)
+        if ciphers:
+            context.set_ciphers(ciphers)
+
+        _socket = context.wrap_socket(sock=_socket)
+
     return _socket
diff --git a/modules/platforms/python/tests/config/ssl.xml b/modules/platforms/python/tests/config/ssl.xml
new file mode 100644
index 0000000..d9d406f
--- /dev/null
+++ b/modules/platforms/python/tests/config/ssl.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+    <!--
+        Initialize property configurer so we can reference environment variables.
+    -->
+    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_FALLBACK"/>
+        <property name="searchSystemEnvironment" value="true"/>
+    </bean>
+  
+    <bean id="test.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <property name="localHost" value="127.0.0.1"/>
+        <property name="connectorConfiguration"><null/></property>
+
+        <property name="clientConnectorConfiguration">
+            <bean class="org.apache.ignite.configuration.ClientConnectorConfiguration">
+                <property name="host" value="127.0.0.1"/>
+                <property name="portRange" value="10"/>
+                <property name="sslEnabled" value="true"/>
+                <property name="useIgniteSslContextFactory" value="false"/>
+                <property name="sslClientAuth" value="true"/>
+
+                <!-- Provide Ssl context. -->
+                <property name="sslContextFactory">
+                    <bean class="org.apache.ignite.ssl.SslContextFactory">
+                        <property name="keyStoreFilePath" value="${PYTHON_TEST_CONFIG_PATH}/ssl/server.jks"/>
+                        <property name="keyStorePassword" value="123456"/>
+                        <property name="trustStoreFilePath" value="${PYTHON_TEST_CONFIG_PATH}/ssl/trust.jks"/>
+                        <property name="trustStorePassword" value="123456"/>
+                    </bean>
+                </property>
+            </bean>
+        </property>
+    </bean>
+</beans>
\ No newline at end of file
diff --git a/modules/platforms/python/tests/config/ssl/README.txt b/modules/platforms/python/tests/config/ssl/README.txt
new file mode 100644
index 0000000..eca07ea
--- /dev/null
+++ b/modules/platforms/python/tests/config/ssl/README.txt
@@ -0,0 +1,3 @@
+These files generated using script
+`$IGNITE_SRC/modules/platforms/cpp/thin-client-test/config/ssl/generate_certificates.sh`
+To update them just run script and move files to this folder.
\ No newline at end of file
diff --git a/modules/platforms/python/tests/config/ssl/client_full.pem b/modules/platforms/python/tests/config/ssl/client_full.pem
new file mode 100644
index 0000000..8260928
--- /dev/null
+++ b/modules/platforms/python/tests/config/ssl/client_full.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCnW8A/wVcIQL7O
+T197f6YSl572HyXZbhAMXU9CIT5Er1TDUETPHE2cslvkXSvpMkaI61ftPelEfoir
+IVyuoJb4c6rnPLtnt+LfUmN8MS8C+vsZPw6gaZW6JIKGMLsUo/nmz986C9AfuSco
+auVFQC+48pHjzXUQ+sGvnAQjSaz/U5+0pKMJBMxxmcwLSn6vopz7859X08odWdV2
+5sq6irJW+w/93vuYdBXqlFthjMSVzOBhFTeTYw6db+CmNofG+EMjqP9lB5rPGLHb
+qbOJx3jv8dvTxECtoc2myAmQrUB9+xXX6/90j2HRuNu2BauPsmpfq7lNvjV/Bea/
+hnhFl+anAgMBAAECggEBAIsACYzqZ/7Sx6dTBVrtimGmzMBe3nDYmTurxEiIk884
+UI5n/L6II24iNXBWckIdH7hYv46r/TKGZby82N2xQ7LXXvrv1jcu45/YLgjYUNOI
+4UT2uo9BIrqX2FDb6IYcK1MpE56CcTnn7j4DiqkZxok17zXlT3XqzzOrwUQNzUHC
+Oo3vPRzZBYqyLknyIqNP5fZoJbVgH469ka6s6oOyOzW5fTvPdlK/lWqAdqf7GJEV
+1xwVsDOy1NvrxXwqz3knq3yykkErYFXi7Wf4AcCMH0n42kWQwWh4w3Ug+TtcRe4c
+Y7qcQFa3GVeVDIB4komCtezOhHGG4upRuwK4fko1iwECgYEA2OCIHqjvWEmOsB3G
+2c7ci78NNjOVn12NhiX671wALnJ+IqVlHUg1TUV8lu7oK8rHLDhiQPiM9aTc1012
++3pwSn9l2z5UtEt4KxeRc14lCOMST+mZe/SDf7TLQsj26oOWJksT9UfxT2AtzcvF
+Xy51uG+0Ve32s1OZiGp04lORPtMCgYEAxYxtbxkYJsg2yXjf/d97hr+eMGoyoWxv
+TIytIWyNh8SinQdyjyPlMrMjDKXhPuMvWocAkDiLtd9wHSzgTV8VkdRuajDxptjL
+Z0Kjt9pMp1SMTNzfCMflDviWq46SXEAQkm7lAag3zqZNB34rI5WpW8dPf/gIIJCc
+zegqadYXHF0CgYAOi0g1niim6A/smaKbOrcpm/9b0ivHizORenyQjr/oXX89/Y+B
+XjVM4EsRqCXjwe6HdaSJLOHvG0ZAHg7LoJNlO5PuFwkBKkp9wU/cx8R+CxRQTZ8g
+Y+5pows6iFWetoJcQQ6ulUuGgjGwKmkrD+ePHdafKJ0xu3qBXnpGL0p/RwKBgQCm
+xDZ57EhMLQa7LBSDf88K4OZM3snhJeYLTFK3fak47RGN2ISoO9g35av3+GzfJvCJ
+zp/2IBYpMfe2WXT9PAC8fAW+FZVakXecs0/8XAgL1j8ef/K0ufMvoUGokBIUWGzl
+AULIFFcQV6l9YtBOGQDAntAJKrzJqOsGlDCB6h7WbQKBgQCnF1SuakiToiv7TQHk
+KQT6kUGqBO7hSfGG3jx2alATXww46iCj2Op8dcIYcM1vPCSFlMgI4zlgX01tap2/
++LDtehygTY11jm6q8adoplqGN8LlotXeBTwgN2COdNbhh6Nj+9M+yCl749nnBfd7
+17EiuQzTB8B4oK9dfvDK07hq3w==
+-----END PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIEBTCCAu0CCQDvTawLdBCCFDANBgkqhkiG9w0BAQsFADCBvzELMAkGA1UEBhMC
+VVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCVdha2VmaWVsZDEa
+MBgGA1UEAwwRaWduaXRlLmFwYWNoZS5vcmcxJzAlBgNVBAoMHlRoZSBBcGFjaGUg
+U29mdHdhcmUgRm91bmRhdGlvbjEZMBcGA1UECwwQQXBhY2hlIElnbml0ZSBDQTEk
+MCIGCSqGSIb3DQEJARYVZGV2QGlnbml0ZS5hcGFjaGUub3JnMB4XDTIwMDgzMTA5
+MjgyNVoXDTMwMDgyOTA5MjgyNVowgcgxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1N
+YXNzYWNodXNldHRzMRIwEAYDVQQHDAlXYWtlZmllbGQxGjAYBgNVBAMMEWlnbml0
+ZS5hcGFjaGUub3JnMScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5k
+YXRpb24xIjAgBgNVBAsMGUFwYWNoZSBJZ25pdGUgQ2xpZW50IFRlc3QxJDAiBgkq
+hkiG9w0BCQEWFWRldkBpZ25pdGUuYXBhY2hlLm9yZzCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAKdbwD/BVwhAvs5PX3t/phKXnvYfJdluEAxdT0IhPkSv
+VMNQRM8cTZyyW+RdK+kyRojrV+096UR+iKshXK6glvhzquc8u2e34t9SY3wxLwL6
++xk/DqBplbokgoYwuxSj+ebP3zoL0B+5Jyhq5UVAL7jykePNdRD6wa+cBCNJrP9T
+n7SkowkEzHGZzAtKfq+inPvzn1fTyh1Z1XbmyrqKslb7D/3e+5h0FeqUW2GMxJXM
+4GEVN5NjDp1v4KY2h8b4QyOo/2UHms8Ysdups4nHeO/x29PEQK2hzabICZCtQH37
+Fdfr/3SPYdG427YFq4+yal+ruU2+NX8F5r+GeEWX5qcCAwEAATANBgkqhkiG9w0B
+AQsFAAOCAQEAiE2xX2uNRmsPMfVA//nbc6Djj+a/FEqJ2OvqVTaJPw5M2Jw8F+XG
+sd09qXXCKpBtihBrbnoHQIQNUTOAkuxrCkRCubQ0w7PQTomOX/cXQdMPdgWa27Oi
+Li7Pq2FwAEwhnSfOPwrj+2XU1bzwwIMdT85XD9KQFirIzGaAnGMN08pNxRROlOyV
+bOqIptP9DGuM51lKNd+rNoBY1C29pnYoitFjarRkNfOwJqBabPacDvjZLuo/CP8Z
+KmhjH3W1AtcRNGNrlaqsaS02Ny6SgvXWKNKtp5xRpwmOZ6YT8Q2pHXPfE8mjCvl0
+Cu6HiNMP8LUdxriKDtdHZbhBCAfnjzBzUw==
+-----END CERTIFICATE-----
diff --git a/modules/platforms/python/tests/config/ssl/client_with_pass_full.pem b/modules/platforms/python/tests/config/ssl/client_with_pass_full.pem
new file mode 100644
index 0000000..a53bc51
--- /dev/null
+++ b/modules/platforms/python/tests/config/ssl/client_with_pass_full.pem
@@ -0,0 +1,54 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,42A0C0A0F7D8E31ABF5BE4EC262E2881
+
+j6XDTAvm5OI12CmE/UlK9NTTWbvwuoKcuqaYlPxPtPdO9tZ7RxdPLX0aasi4ALPm
+WF1oe1SmPAneXQrHejxb/mw1rliqwVwEblSdXUEtq4ZFSGwy+YmYXP62XNKwColM
+BppNX87MxS5hu6wsV2cuML7e/Y5wUro04Tk2kXoraVXyxLChKffY68rzih1pv5d1
+cA4lFqvMNBbIOGIUIRX60eZSlZ6XS5oZY9pc7O+KOUH7e8Pa3dFEbdXgbSX+dGLt
+DhV7bb1sciuJDBC7F9HjZem5YkKt44AkwfL3v/m7kGTaESNN2/NYemNGsth+HmF6
+nWB5ver1dQ3iGG1gLLmLbDyXcmOHSxWIcagqN0/bX08gBdBIWiTTHx7k3ke8z5QO
+8T+Yx6O6O0ccLWYZUnA3Dw4vNEV8Xn1V2+e0Z0uhTt0kf2bu4xCwkmrlREjcqtMD
+8OAzzhiyQjJGmbQQpTrVKdIT5e3Ux+PKzaUo5U1ZP8s7b76VxjsmljXrFV9I4qLC
+/NP22GH71F+p68qaawldw/ljtx9KuVYGD3cbvN5bF3VDUSf4HoI56U/WrfM1/P+/
+27yLYGEb8g4kzIp0GjC50CkFZRTAG/C5kh5mo+L8A5kQ77z8Utn75FnnUDuL22Pa
+qnJE7IWFWITA0f3KE62oiIxx//+rxy4KneYKv9HLRjqd7p0Yzv9XhyBlXtFRX9g0
+ji8M0lvJGwDxarH6BTFozLYfjFo92FG5la0GJS/uPOXaly2DFElg71pA24xGlgr0
+u6Cprge5T95VVFKOEJ6z5M0tTtfKPXnD+vb9FfIotKWr03+palUANGuXAIf3C++a
+NfUm6R7dZ3nUGk4+L+U+NsyIGEMYnBLD5jgSVGg8q3MiUb6Zwy3lV0maoNV3pizt
+QrWWlSuo6fUAkFEADyEhy305FhjWBTsJ5ZP+D75Joh5tR7gzDhl0Xg4nyTQ+QUM+
+6E/yBsEIjunITQeDOf7Il8Jg/07T0StH9RllWnz7/UTAD4SYrrPs5Fvn1heIP/aO
+s/ER7Ip2YVhr0U4aCFzzuxSuWRRJCEE7Rb0AYT7pU4/iTu2tQYQV/VAMaK+PM0O6
+j5YwnV7fVZBjs3BgZodu+qm/8bK7fSjG8qQQ50jEcQZmkqEuBbJRIi4RNvBpm1Eo
+q79CuxhAPBM69jmJao5cxKOj3zRzI3ZamT6cMcssz/HkgEKO4H9rr2ZKB4xCeR7n
+QUo9bQbnq5W4xbei23Zk5/Tg8g0lUdfhiNTa+0mQap7Vnl7SQaaH4MfKEpdzm7eW
+73eIvl4HVOtp76SIV82wMMW+IVzcikpFwQpP8EEq+XGZFk/zY1tptsRy2USadM4Y
+Hjpyx4ZOYFg0HKI0vc2TuMo2AvmgyL1/zBB4DC44OUEW8TuUoX20rYhtq3alqlpl
+ieHAyqIDeZV+//FSMSDiHR4TAWQu4LnH/3G0MIZYnp9jyqjc7fF+uXfdSiCqGFn3
+DP9nU/PyL0fYFXnNlL8Lazyhi7ETvn694ni/HdElXnqugAIBdaRcwjqfaZ0XA0ho
+QGOSiPEYkJL19x93C96EXmBxW+Y72uxlEeEYuFafSegIypOkf4swgzlfdsaVq2uo
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE-----
+MIIEBTCCAu0CCQDvTawLdBCCFTANBgkqhkiG9w0BAQsFADCBvzELMAkGA1UEBhMC
+VVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCVdha2VmaWVsZDEa
+MBgGA1UEAwwRaWduaXRlLmFwYWNoZS5vcmcxJzAlBgNVBAoMHlRoZSBBcGFjaGUg
+U29mdHdhcmUgRm91bmRhdGlvbjEZMBcGA1UECwwQQXBhY2hlIElnbml0ZSBDQTEk
+MCIGCSqGSIb3DQEJARYVZGV2QGlnbml0ZS5hcGFjaGUub3JnMB4XDTIwMDgzMTA5
+MjgyNVoXDTMwMDgyOTA5MjgyNVowgcgxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1N
+YXNzYWNodXNldHRzMRIwEAYDVQQHDAlXYWtlZmllbGQxGjAYBgNVBAMMEWlnbml0
+ZS5hcGFjaGUub3JnMScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5k
+YXRpb24xIjAgBgNVBAsMGUFwYWNoZSBJZ25pdGUgQ2xpZW50IFRlc3QxJDAiBgkq
+hkiG9w0BCQEWFWRldkBpZ25pdGUuYXBhY2hlLm9yZzCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAPXi2AbcfKK/BdGWIZZvXyICOfLXXXNezAo1fiVs5LfG
+C5v0lBSmxeu1NYRF05Wf4/mEmVZnhzoVxViQWlUbL6M6A/VrrZPOF421tloiz/1J
+hBfVI91JBji2cP78HvdPAGIHg5zLlgGUxaKxgvRfm3v43hc3YvzXo8Adg6QBMNdQ
+m3co5L887lhixCHZh/FcncbaXSwRSZJtS9B1DiCUVIlfcAIkn80xL2bJ5giS5vwH
+pKZagoykaVbwrd3ObHGQtCZ/TtLM5gseDfppEWRtZv5wmJEejcHot5nSfUIrDuuY
+7MO6flSy6yshSXbk2eAQ8YCLywwSm87uA3PrOeX77PsCAwEAATANBgkqhkiG9w0B
+AQsFAAOCAQEAI+2iiMcS1ks7YZZb9H/Oa1Il4wOOC+OEkFsVBLBKtUiEYkBJHykg
+BPguDjd/wXfCRb8FgG28JUfhzcvEIZB18tb1updKvEsLZUfPGXI89vUTshi51hy7
+VoOAJMyzJRWDP37MAtnTAu0uS205Q+8VE/adDrdjDQKBGF98OkXQVsxyfckzY2Za
+mmCmOWdJWTZH/5eh+2ogvsGDy9VXYyQlhNNl5oLVldPL4AjanKfIwaYIwYZXyKV9
+2+2lkkM7ikY6WxCHct41IuyBx5Nty2zu5tdLoQd1lII4u1c0t5AfrJYyWjeNMMnF
++e9wWnM1ivfHESAHFzhdzSbXuEFHlq3F1w==
+-----END CERTIFICATE-----
diff --git a/modules/platforms/python/tests/config/ssl/server.jks b/modules/platforms/python/tests/config/ssl/server.jks
new file mode 100644
index 0000000..e6a9c1a
Binary files /dev/null and b/modules/platforms/python/tests/config/ssl/server.jks differ
diff --git a/modules/platforms/python/tests/config/ssl/trust.jks b/modules/platforms/python/tests/config/ssl/trust.jks
new file mode 100644
index 0000000..0bc7210
Binary files /dev/null and b/modules/platforms/python/tests/config/ssl/trust.jks differ
diff --git a/modules/platforms/python/tests/conftest.py b/modules/platforms/python/tests/conftest.py
index be6d029..f7e2e1f 100644
--- a/modules/platforms/python/tests/conftest.py
+++ b/modules/platforms/python/tests/conftest.py
@@ -66,7 +66,7 @@ class SSLVersionParser(argparse.Action):
 
 @pytest.fixture(scope='module')
 def client(
-    ignite_host, ignite_port, timeout, use_ssl, ssl_keyfile, ssl_certfile,
+    ignite_host, ignite_port, timeout, use_ssl, ssl_keyfile, ssl_keyfile_password, ssl_certfile,
     ssl_ca_certfile, ssl_cert_reqs, ssl_ciphers, ssl_version,
     username, password,
 ):
@@ -74,6 +74,7 @@ def client(
         timeout=timeout,
         use_ssl=use_ssl,
         ssl_keyfile=ssl_keyfile,
+        ssl_keyfile_password=ssl_keyfile_password,
         ssl_certfile=ssl_certfile,
         ssl_ca_certfile=ssl_ca_certfile,
         ssl_cert_reqs=ssl_cert_reqs,
@@ -136,6 +137,13 @@ def pytest_addoption(parser):
         help='a path to SSL key file to identify local party'
     )
     parser.addoption(
+        '--ssl-keyfile-password',
+        action='store',
+        default=None,
+        type=str,
+        help='password for SSL key file'
+    )
+    parser.addoption(
         '--ssl-certfile',
         action='store',
         default=None,
@@ -199,6 +207,7 @@ def pytest_generate_tests(metafunc):
         'timeout': None,
         'use_ssl': False,
         'ssl_keyfile': None,
+        'ssl_keyfile_password': None,
         'ssl_certfile': None,
         'ssl_ca_certfile': None,
         'ssl_cert_reqs': ssl.CERT_NONE,
diff --git a/modules/platforms/python/tests/test_handshake.py b/modules/platforms/python/tests/test_handshake.py
index 54315f0..d655d94 100644
--- a/modules/platforms/python/tests/test_handshake.py
+++ b/modules/platforms/python/tests/test_handshake.py
@@ -21,13 +21,14 @@ from pyignite.connection.handshake import HandshakeRequest, read_response
 
 def test_handshake(
     monkeypatch,
-    ignite_host, ignite_port, use_ssl, ssl_keyfile, ssl_certfile,
+    ignite_host, ignite_port, use_ssl, ssl_keyfile, ssl_keyfile_password, ssl_certfile,
     ssl_ca_certfile, ssl_cert_reqs, ssl_ciphers, ssl_version,
     username, password,
 ):
     client = Client(
         use_ssl=use_ssl,
         ssl_keyfile=ssl_keyfile,
+        ssl_keyfile_password=ssl_keyfile_password,
         ssl_certfile=ssl_certfile,
         ssl_ca_certfile=ssl_ca_certfile,
         ssl_cert_reqs=ssl_cert_reqs,