From 0a9f13983fea04096cfd9b0e2c48690e6df46838 Mon Sep 17 00:00:00 2001 From: Murilo Pereira Date: Tue, 17 Apr 2018 20:15:19 +0200 Subject: [PATCH 1/5] Plumb cipher configuration through. --- frameworks/kafka/src/main/dist/server.properties.mustache | 4 ++++ frameworks/kafka/universe/config.json | 5 +++++ frameworks/kafka/universe/marathon.json.mustache | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/frameworks/kafka/src/main/dist/server.properties.mustache b/frameworks/kafka/src/main/dist/server.properties.mustache index b2293fd2413..291fe77c067 100644 --- a/frameworks/kafka/src/main/dist/server.properties.mustache +++ b/frameworks/kafka/src/main/dist/server.properties.mustache @@ -53,6 +53,10 @@ ssl.truststore.password=notsecure ssl.enabled.protocols=TLSv1.2 +{{#SECURITY_TRANSPORT_ENCRYPTION_CIPHERS}} +ssl.cipher.suites={{SECURITY_TRANSPORT_ENCRYPTION_CIPHERS}} +{{/SECURITY_TRANSPORT_ENCRYPTION_CIPHERS}} + # If Kerberos is NOT enabled, then SSL authentication can be turned on. {{^SECURITY_KERBEROS_ENABLED}} {{#SECURITY_SSL_AUTHENTICATION_ENABLED}} diff --git a/frameworks/kafka/universe/config.json b/frameworks/kafka/universe/config.json index dd97c53c522..5fd3161e156 100644 --- a/frameworks/kafka/universe/config.json +++ b/frameworks/kafka/universe/config.json @@ -193,6 +193,11 @@ "description": "Allow plaintext alongside encrypted traffic", "type": "boolean", "default": false + }, + "ciphers": { + "description": "Comma-separated list of cipher suites. Note that Kafka requires cipher suite names to be prefixed with \"TLS_\".", + "type": "string", + "default": "TLS_AES128-GCM-SHA256,TLS_AES128-SHA256,TLS_AES256-GCM-SHA384,TLS_AES256-SHA256,TLS_DHE-RSA-AES128-GCM-SHA256,TLS_DHE-RSA-AES128-SHA256,TLS_DHE-RSA-AES256-GCM-SHA384,TLS_DHE-RSA-AES256-SHA256,TLS_ECDHE-RSA-AES128-GCM-SHA256,TLS_ECDHE-RSA-AES128-SHA256,TLS_ECDHE-RSA-AES256-GCM-SHA384,TLS_ECDHE-RSA-AES256-SHA384" } } }, diff --git a/frameworks/kafka/universe/marathon.json.mustache b/frameworks/kafka/universe/marathon.json.mustache index 4fa0e799b6a..52385c30bab 100644 --- a/frameworks/kafka/universe/marathon.json.mustache +++ b/frameworks/kafka/universe/marathon.json.mustache @@ -92,6 +92,10 @@ "TASKCFG_ALL_SECURITY_TRANSPORT_ENCRYPTION_ALLOW_PLAINTEXT": "{{service.security.transport_encryption.allow_plaintext}}", {{/service.security.transport_encryption.allow_plaintext}} + {{#service.security.transport_encryption.ciphers}} + "TASKCFG_ALL_SECURITY_TRANSPORT_ENCRYPTION_CIPHERS": "{{service.security.transport_encryption.ciphers}}", + {{/service.security.transport_encryption.ciphers}} + {{#service.security.ssl_authentication.enabled}} "TASKCFG_ALL_SECURITY_SSL_AUTHENTICATION_ENABLED": "{{service.security.ssl_authentication.enabled}}", {{/service.security.ssl_authentication.enabled}} From a35994c3c300683714e17c9ee039ae96582a5f51 Mon Sep 17 00:00:00 2001 From: Murilo Pereira Date: Tue, 17 Apr 2018 20:32:28 +0200 Subject: [PATCH 2/5] Add tests. --- frameworks/kafka/tests/test_tls.py | 41 ++++++++++++++++++++++++++++++ testing/sdk_security.py | 31 ++++++++++++++++++++++ testing/sdk_utils.py | 6 +++++ 3 files changed, 78 insertions(+) diff --git a/frameworks/kafka/tests/test_tls.py b/frameworks/kafka/tests/test_tls.py index d6f44f3c45c..ff19de80f36 100644 --- a/frameworks/kafka/tests/test_tls.py +++ b/frameworks/kafka/tests/test_tls.py @@ -4,6 +4,7 @@ import sdk_install import sdk_networks import sdk_plan +import sdk_security import sdk_utils from security import transport_encryption @@ -96,3 +97,43 @@ def test_producer_over_tls(kafka_service_tls): json=True) assert len(write_info) == 1 assert write_info['message'].startswith('Output: {} records sent'.format(num_messages)) + + +@pytest.mark.tls +@pytest.mark.smoke +@pytest.mark.sanity +@sdk_utils.dcos_ee_only +@pytest.mark.dcos_min_version('1.10') +def test_tls_ciphers(kafka_service_tls): + task_name = 'kafka-0-broker' + endpoint = sdk_cmd.svc_cli( + config.PACKAGE_NAME, + config.SERVICE_NAME, + 'endpoints {}'.format(BROKER_TLS_ENDPOINT), + json=True)['dns'][0] + ciphers_config_path = ['service', 'security', 'transport_encryption', 'ciphers'] + expected_ciphers = set(sdk_utils.get_in(ciphers_config_path, sdk_cmd.svc_cli( + config.PACKAGE_NAME, + config.SERVICE_NAME, + 'describe', + json=True), '').rstrip().split(':')) + possible_ciphers = sdk_security.openssl_ciphers() + enabled_ciphers = set() + + assert expected_ciphers # Non-empty set. + assert possible_ciphers # Non-empty set. + + sdk_cmd.service_task_exec(config.SERVICE_NAME, task_name, 'openssl version') # Output OpenSSL version. + print("\nExpected ciphers:") + print("\n".join(sdk_utils.sort(list(expected_ciphers)))) + print("\n{} ciphers will be checked:".format(len(possible_ciphers))) + print("\n".join(sdk_utils.sort(list(possible_ciphers)))) + + for cipher in possible_ciphers: + if sdk_security.is_cipher_enabled(config.SERVICE_NAME, task_name, cipher, endpoint): + enabled_ciphers.add(cipher) + + print('{} ciphers enabled out of {}:'.format(len(enabled_ciphers), len(possible_ciphers))) + print("\n".join(sdk_utils.sort(list(enabled_ciphers)))) + + assert expected_ciphers == enabled_ciphers diff --git a/testing/sdk_security.py b/testing/sdk_security.py index 48feafde991..5d3799407a6 100644 --- a/testing/sdk_security.py +++ b/testing/sdk_security.py @@ -6,6 +6,7 @@ ''' import logging import os +from subprocess import check_output from typing import List import retrying @@ -272,3 +273,33 @@ def configure_security(configure_universe): finally: if is_strict: cleanup_security(framework_name) + + +def openssl_ciphers(): + return set( + check_output(['openssl', 'ciphers', + 'ALL:eNULL']).decode('utf-8').rstrip().split(':')) + + +def is_cipher_enabled(service_name: str, + task_name: str, + cipher: str, + endpoint: str, + openssl_timeout: str = '1') -> bool: + @retrying.retry(stop_max_attempt_number=3, + wait_fixed=2000, + retry_on_result=lambda result: 'Failed to enter mount namespace' in result) + def run_openssl_command() -> str: + command = ' '.join([ + 'timeout', openssl_timeout, + 'openssl', 's_client', '-cipher', cipher, + '-connect', endpoint#, + #'-CAfile', 'broker.truststore' + ]) + + _, output = sdk_cmd.service_task_exec(service_name, task_name, command, True) + return output + + output = run_openssl_command() + + return "Cipher is {}".format(cipher) in output diff --git a/testing/sdk_utils.py b/testing/sdk_utils.py index 3208922954e..403b4a4ec01 100644 --- a/testing/sdk_utils.py +++ b/testing/sdk_utils.py @@ -159,3 +159,9 @@ def get_in(keys, coll, default=None): return functools.reduce(operator.getitem, keys, coll) except (KeyError, IndexError, TypeError): return default + + +def sort(coll): + """ Sorts a collection and returns it. """ + coll.sort() + return coll From 39aeb4a2c66591cb42f071bf2d7a46ad82fa1dd1 Mon Sep 17 00:00:00 2001 From: Murilo Pereira Date: Wed, 18 Apr 2018 15:31:23 +0200 Subject: [PATCH 3/5] Handle RFC cipher suite names. --- frameworks/kafka/tests/test_tls.py | 13 +++++++------ frameworks/kafka/universe/config.json | 4 ++-- testing/sdk_security.py | 4 +--- testing/sdk_utils.py | 5 +++++ 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/frameworks/kafka/tests/test_tls.py b/frameworks/kafka/tests/test_tls.py index ff19de80f36..5750cd9b1f8 100644 --- a/frameworks/kafka/tests/test_tls.py +++ b/frameworks/kafka/tests/test_tls.py @@ -7,7 +7,7 @@ import sdk_security import sdk_utils -from security import transport_encryption +from security import transport_encryption, cipher_suites from tests import config @@ -117,11 +117,11 @@ def test_tls_ciphers(kafka_service_tls): config.SERVICE_NAME, 'describe', json=True), '').rstrip().split(':')) - possible_ciphers = sdk_security.openssl_ciphers() + possible_ciphers = set(map(cipher_suites.rfc_name, sdk_security.openssl_ciphers())) enabled_ciphers = set() - assert expected_ciphers # Non-empty set. - assert possible_ciphers # Non-empty set. + assert expected_ciphers, 'Expected ciphers should be non-empty' + assert possible_ciphers, 'Possible ciphers should be non-empty' sdk_cmd.service_task_exec(config.SERVICE_NAME, task_name, 'openssl version') # Output OpenSSL version. print("\nExpected ciphers:") @@ -130,10 +130,11 @@ def test_tls_ciphers(kafka_service_tls): print("\n".join(sdk_utils.sort(list(possible_ciphers)))) for cipher in possible_ciphers: - if sdk_security.is_cipher_enabled(config.SERVICE_NAME, task_name, cipher, endpoint): + openssl_cipher = cipher_suites.openssl_name(cipher) + if sdk_security.is_cipher_enabled(config.SERVICE_NAME, task_name, openssl_cipher, endpoint): enabled_ciphers.add(cipher) print('{} ciphers enabled out of {}:'.format(len(enabled_ciphers), len(possible_ciphers))) print("\n".join(sdk_utils.sort(list(enabled_ciphers)))) - assert expected_ciphers == enabled_ciphers + assert expected_ciphers == enabled_ciphers, "Enabled ciphers should match expected ciphers" diff --git a/frameworks/kafka/universe/config.json b/frameworks/kafka/universe/config.json index 5fd3161e156..9f2f713511a 100644 --- a/frameworks/kafka/universe/config.json +++ b/frameworks/kafka/universe/config.json @@ -195,9 +195,9 @@ "default": false }, "ciphers": { - "description": "Comma-separated list of cipher suites. Note that Kafka requires cipher suite names to be prefixed with \"TLS_\".", + "description": "Comma-separated list of JSSE Cipher Suite Names", "type": "string", - "default": "TLS_AES128-GCM-SHA256,TLS_AES128-SHA256,TLS_AES256-GCM-SHA384,TLS_AES256-SHA256,TLS_DHE-RSA-AES128-GCM-SHA256,TLS_DHE-RSA-AES128-SHA256,TLS_DHE-RSA-AES256-GCM-SHA384,TLS_DHE-RSA-AES256-SHA256,TLS_ECDHE-RSA-AES128-GCM-SHA256,TLS_ECDHE-RSA-AES128-SHA256,TLS_ECDHE-RSA-AES256-GCM-SHA384,TLS_ECDHE-RSA-AES256-SHA384" + "default": "TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" } } }, diff --git a/testing/sdk_security.py b/testing/sdk_security.py index 5d3799407a6..002a92b44ef 100644 --- a/testing/sdk_security.py +++ b/testing/sdk_security.py @@ -292,9 +292,7 @@ def is_cipher_enabled(service_name: str, def run_openssl_command() -> str: command = ' '.join([ 'timeout', openssl_timeout, - 'openssl', 's_client', '-cipher', cipher, - '-connect', endpoint#, - #'-CAfile', 'broker.truststore' + 'openssl', 's_client', '-cipher', cipher, '-connect', endpoint ]) _, output = sdk_cmd.service_task_exec(service_name, task_name, command, True) diff --git a/testing/sdk_utils.py b/testing/sdk_utils.py index 403b4a4ec01..1eb872424ad 100644 --- a/testing/sdk_utils.py +++ b/testing/sdk_utils.py @@ -165,3 +165,8 @@ def sort(coll): """ Sorts a collection and returns it. """ coll.sort() return coll + + +def invert_dict(d: dict) -> dict: + """ Returns a dictionary with its values being its keys and vice-versa. """ + return dict((v, k) for k, v in d.items()) From 6df37767f38cb3bf6d36429a012bd41387f0eacb Mon Sep 17 00:00:00 2001 From: Murilo Pereira Date: Wed, 18 Apr 2018 16:26:36 +0200 Subject: [PATCH 4/5] Ciphers are separated by commas in the service configuration. --- frameworks/kafka/tests/test_tls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/kafka/tests/test_tls.py b/frameworks/kafka/tests/test_tls.py index 5750cd9b1f8..a4464edcb97 100644 --- a/frameworks/kafka/tests/test_tls.py +++ b/frameworks/kafka/tests/test_tls.py @@ -116,7 +116,7 @@ def test_tls_ciphers(kafka_service_tls): config.PACKAGE_NAME, config.SERVICE_NAME, 'describe', - json=True), '').rstrip().split(':')) + json=True), '').rstrip().split(',')) possible_ciphers = set(map(cipher_suites.rfc_name, sdk_security.openssl_ciphers())) enabled_ciphers = set() From 3f8aa7fad391f839d19705bf0dce114c7e820dd6 Mon Sep 17 00:00:00 2001 From: Murilo Pereira Date: Wed, 18 Apr 2018 17:08:39 +0200 Subject: [PATCH 5/5] Of course I forgot to include this file. --- testing/security/cipher_suites.py | 184 ++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 testing/security/cipher_suites.py diff --git a/testing/security/cipher_suites.py b/testing/security/cipher_suites.py new file mode 100644 index 00000000000..f6f8fc389b8 --- /dev/null +++ b/testing/security/cipher_suites.py @@ -0,0 +1,184 @@ +import sdk_utils + +OPENSSL_TO_RFC_NAMES = { + 'ADH-AES128-GCM-SHA256': 'TLS_DH_anon_WITH_AES_128_GCM_SHA256', + 'ADH-AES128-SHA': 'TLS_DH_anon_WITH_AES_128_CBC_SHA', + 'ADH-AES128-SHA256': 'TLS_DH_anon_WITH_AES_128_CBC_SHA256', + 'ADH-AES256-GCM-SHA384': 'TLS_DH_anon_WITH_AES_256_GCM_SHA384', + 'ADH-AES256-SHA': 'TLS_DH_anon_WITH_AES_256_CBC_SHA', + 'ADH-AES256-SHA256': 'TLS_DH_anon_WITH_AES_256_CBC_SHA256', + 'ADH-CAMELLIA128-SHA': 'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA', + 'ADH-CAMELLIA256-SHA': 'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA', + 'ADH-DES-CBC-SHA': 'TLS_DH_anon_WITH_DES_CBC_SHA', + 'ADH-DES-CBC3-SHA': 'TLS_DH_anon_WITH_3DES_EDE_CBC_SHA', + 'ADH-RC4-MD5': 'TLS_DH_anon_WITH_RC4_128_MD5', + 'ADH-SEED-SHA': 'TLS_DH_anon_WITH_SEED_CBC_SHA', + 'AECDH-AES128-SHA': 'TLS_ECDH_anon_WITH_AES_128_CBC_SHA', + 'AECDH-AES256-SHA': 'TLS_ECDH_anon_WITH_AES_256_CBC_SHA', + 'AECDH-DES-CBC3-SHA': 'TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA', + 'AECDH-NULL-SHA': 'TLS_ECDH_anon_WITH_NULL_SHA', + 'AECDH-RC4-SHA': 'TLS_ECDH_anon_WITH_RC4_128_SHA', + 'AES128-GCM-SHA256': 'TLS_RSA_WITH_AES_128_GCM_SHA256', + 'AES128-SHA': 'TLS_RSA_WITH_AES_128_CBC_SHA', + 'AES128-SHA256': 'TLS_RSA_WITH_AES_128_CBC_SHA256', + 'AES256-GCM-SHA384': 'TLS_RSA_WITH_AES_256_GCM_SHA384', + 'AES256-SHA': 'TLS_RSA_WITH_AES_256_CBC_SHA', + 'AES256-SHA256': 'TLS_RSA_WITH_AES_256_CBC_SHA256', + 'CAMELLIA128-SHA': 'TLS_RSA_WITH_CAMELLIA_128_CBC_SHA', + 'CAMELLIA256-SHA': 'TLS_RSA_WITH_CAMELLIA_256_CBC_SHA', + 'DES-CBC-MD5': 'SSL_CK_DES_64_CBC_WITH_MD5', + 'DES-CBC-SHA': 'TLS_RSA_WITH_DES_CBC_SHA', + 'DES-CBC3-MD5': 'SSL_CK_DES_192_EDE3_CBC_WITH_MD5', + 'DES-CBC3-SHA': 'TLS_RSA_WITH_3DES_EDE_CBC_SHA', + 'DH-DSS-AES128-GCM-SHA256': 'TLS_DH_DSS_WITH_AES_128_GCM_SHA256', + 'DH-DSS-AES128-SHA': 'TLS_DH_DSS_WITH_AES_128_CBC_SHA', + 'DH-DSS-AES128-SHA256': 'TLS_DH_DSS_WITH_AES_128_CBC_SHA256', + 'DH-DSS-AES256-GCM-SHA384': 'TLS_DH_DSS_WITH_AES_256_GCM_SHA384', + 'DH-DSS-AES256-SHA': 'TLS_DH_DSS_WITH_AES_256_CBC_SHA', + 'DH-DSS-AES256-SHA256': 'TLS_DH_DSS_WITH_AES_256_CBC_SHA256', + 'DH-DSS-CAMELLIA128-SHA': 'TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA', + 'DH-DSS-CAMELLIA256-SHA': 'TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA', + 'DH-DSS-DES-CBC-SHA': 'TLS_DH_DSS_WITH_DES_CBC_SHA', + 'DH-DSS-DES-CBC3-SHA': 'TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA', + 'DH-DSS-SEED-SHA': 'TLS_DH_DSS_WITH_SEED_CBC_SHA', + 'DH-RSA-AES128-GCM-SHA256': 'TLS_DH_RSA_WITH_AES_128_GCM_SHA256', + 'DH-RSA-AES128-SHA': 'TLS_DH_RSA_WITH_AES_128_CBC_SHA', + 'DH-RSA-AES128-SHA256': 'TLS_DH_RSA_WITH_AES_128_CBC_SHA256', + 'DH-RSA-AES256-GCM-SHA384': 'TLS_DH_RSA_WITH_AES_256_GCM_SHA384', + 'DH-RSA-AES256-SHA': 'TLS_DH_RSA_WITH_AES_256_CBC_SHA', + 'DH-RSA-AES256-SHA256': 'TLS_DH_RSA_WITH_AES_256_CBC_SHA256', + 'DH-RSA-CAMELLIA128-SHA': 'TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA', + 'DH-RSA-CAMELLIA256-SHA': 'TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA', + 'DH-RSA-DES-CBC-SHA': 'TLS_DH_RSA_WITH_DES_CBC_SHA', + 'DH-RSA-DES-CBC3-SHA': 'TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA', + 'DH-RSA-SEED-SHA': 'TLS_DH_RSA_WITH_SEED_CBC_SHA', + 'DHE-DSS-AES128-GCM-SHA256': 'TLS_DHE_DSS_WITH_AES_128_GCM_SHA256', + 'DHE-DSS-AES128-SHA': 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA', + 'DHE-DSS-AES128-SHA256': 'TLS_DHE_DSS_WITH_AES_128_CBC_SHA256', + 'DHE-DSS-AES256-GCM-SHA384': 'TLS_DHE_DSS_WITH_AES_256_GCM_SHA384', + 'DHE-DSS-AES256-SHA': 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA', + 'DHE-DSS-AES256-SHA256': 'TLS_DHE_DSS_WITH_AES_256_CBC_SHA256', + 'DHE-DSS-CAMELLIA128-SHA': 'TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA', + 'DHE-DSS-CAMELLIA256-SHA': 'TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA', + 'DHE-DSS-RC4-SHA': 'TLS_DHE_DSS_WITH_RC4_128_SHA', + 'DHE-DSS-SEED-SHA': 'TLS_DHE_DSS_WITH_SEED_CBC_SHA', + 'DHE-RSA-AES128-GCM-SHA256': 'TLS_DHE_RSA_WITH_AES_128_GCM_SHA256', + 'DHE-RSA-AES128-SHA': 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA', + 'DHE-RSA-AES128-SHA256': 'TLS_DHE_RSA_WITH_AES_128_CBC_SHA256', + 'DHE-RSA-AES256-GCM-SHA384': 'TLS_DHE_RSA_WITH_AES_256_GCM_SHA384', + 'DHE-RSA-AES256-SHA': 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA', + 'DHE-RSA-AES256-SHA256': 'TLS_DHE_RSA_WITH_AES_256_CBC_SHA256', + 'DHE-RSA-CAMELLIA128-SHA': 'TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA', + 'DHE-RSA-CAMELLIA256-SHA': 'TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA', + 'DHE-RSA-CHACHA20-POLY1305': 'TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256', + 'DHE-RSA-SEED-SHA': 'TLS_DHE_RSA_WITH_SEED_CBC_SHA', + 'ECDH-ECDSA-AES128-GCM-SHA256': 'TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256', + 'ECDH-ECDSA-AES128-SHA': 'TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA', + 'ECDH-ECDSA-AES128-SHA256': 'TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256', + 'ECDH-ECDSA-AES256-GCM-SHA384': 'TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384', + 'ECDH-ECDSA-AES256-SHA': 'TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA', + 'ECDH-ECDSA-AES256-SHA384': 'TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384', + 'ECDH-ECDSA-DES-CBC3-SHA': 'TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA', + 'ECDH-ECDSA-NULL-SHA': 'TLS_ECDH_ECDSA_WITH_NULL_SHA', + 'ECDH-ECDSA-RC4-SHA': 'TLS_ECDH_ECDSA_WITH_RC4_128_SHA', + 'ECDH-RSA-AES128-GCM-SHA256': 'TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256', + 'ECDH-RSA-AES128-SHA': 'TLS_ECDH_RSA_WITH_AES_128_CBC_SHA', + 'ECDH-RSA-AES128-SHA256': 'TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256', + 'ECDH-RSA-AES256-GCM-SHA384': 'TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384', + 'ECDH-RSA-AES256-SHA': 'TLS_ECDH_RSA_WITH_AES_256_CBC_SHA', + 'ECDH-RSA-AES256-SHA384': 'TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384', + 'ECDH-RSA-DES-CBC3-SHA': 'TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA', + 'ECDH-RSA-NULL-SHA': 'TLS_ECDH_RSA_WITH_NULL_SHA', + 'ECDH-RSA-RC4-SHA': 'TLS_ECDH_RSA_WITH_RC4_128_SHA', + 'ECDHE-ECDSA-AES128-GCM-SHA256': 'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', + 'ECDHE-ECDSA-AES128-SHA': 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA', + 'ECDHE-ECDSA-AES128-SHA256': 'TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256', + 'ECDHE-ECDSA-AES256-GCM-SHA384': 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', + 'ECDHE-ECDSA-AES256-SHA': 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA', + 'ECDHE-ECDSA-AES256-SHA384': 'TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384', + 'ECDHE-ECDSA-CHACHA20-POLY1305': 'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256', + 'ECDHE-ECDSA-DES-CBC3-SHA': 'TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA', + 'ECDHE-ECDSA-NULL-SHA': 'TLS_ECDHE_ECDSA_WITH_NULL_SHA', + 'ECDHE-ECDSA-RC4-SHA': 'TLS_ECDHE_ECDSA_WITH_RC4_128_SHA', + 'ECDHE-RSA-AES128-GCM-SHA256': 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', + 'ECDHE-RSA-AES128-SHA': 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA', + 'ECDHE-RSA-AES128-SHA256': 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256', + 'ECDHE-RSA-AES256-GCM-SHA384': 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', + 'ECDHE-RSA-AES256-SHA': 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA', + 'ECDHE-RSA-AES256-SHA384': 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384', + 'ECDHE-RSA-CHACHA20-POLY1305': 'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256', + 'ECDHE-RSA-DES-CBC3-SHA': 'TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA', + 'ECDHE-RSA-NULL-SHA': 'TLS_ECDHE_RSA_WITH_NULL_SHA', + 'ECDHE-RSA-RC4-SHA': 'TLS_ECDHE_RSA_WITH_RC4_128_SHA', + 'EDH-DSS-DES-CBC-SHA': 'TLS_DHE_DSS_WITH_DES_CBC_SHA', + 'EDH-DSS-DES-CBC3-SHA': 'TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA', + 'EDH-RSA-DES-CBC-SHA': 'TLS_DHE_RSA_WITH_DES_CBC_SHA', + 'EDH-RSA-DES-CBC3-SHA': 'TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA', + 'EXP-ADH-DES-CBC-SHA': 'TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA', + 'EXP-ADH-RC4-MD5': 'TLS_DH_anon_EXPORT_WITH_RC4_40_MD5', + 'EXP-DES-CBC-SHA': 'TLS_RSA_EXPORT_WITH_DES40_CBC_SHA', + 'EXP-DH-DSS-DES-CBC-SHA': 'TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA', + 'EXP-DH-RSA-DES-CBC-SHA': 'TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA', + 'EXP-EDH-DSS-DES-CBC-SHA': 'TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA', + 'EXP-EDH-RSA-DES-CBC-SHA': 'TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA', + 'EXP-KRB5-DES-CBC-MD5': 'TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5', + 'EXP-KRB5-DES-CBC-SHA': 'TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA', + 'EXP-KRB5-RC2-CBC-MD5': 'TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5', + 'EXP-KRB5-RC2-CBC-SHA': 'TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA', + 'EXP-KRB5-RC4-MD5': 'TLS_KRB5_EXPORT_WITH_RC4_40_MD5', + 'EXP-KRB5-RC4-SHA': 'TLS_KRB5_EXPORT_WITH_RC4_40_SHA', + 'EXP-RC2-CBC-MD5': 'SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5', + 'EXP-RC2-CBC-MD5': 'TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5', + 'EXP-RC4-MD5': 'SSL_CK_RC4_128_EXPORT40_WITH_MD5', + 'EXP-RC4-MD5': 'TLS_RSA_EXPORT_WITH_RC4_40_MD5', + 'EXP1024-DES-CBC-SHA': 'TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA', + 'EXP1024-DHE-DSS-DES-CBC-SHA': 'TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA', + 'EXP1024-DHE-DSS-RC4-SHA': 'TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA', + 'EXP1024-RC4-SHA': 'TLS_RSA_EXPORT1024_WITH_RC4_56_SHA', + 'GOST2001-GOST89-GOST89': 'TLS_GOSTR341001_WITH_28147_CNT_IMIT', + 'GOST94-GOST89-GOST89': 'TLS_GOSTR341094_WITH_28147_CNT_IMIT', + 'IDEA-CBC-MD5': 'SSL_CK_IDEA_128_CBC_WITH_MD5', + 'IDEA-CBC-SHA': 'TLS_RSA_WITH_IDEA_CBC_SHA', + 'KRB5-DES-CBC-MD5': 'TLS_KRB5_WITH_DES_CBC_MD5', + 'KRB5-DES-CBC-SHA': 'TLS_KRB5_WITH_DES_CBC_SHA', + 'KRB5-DES-CBC3-MD5': 'TLS_KRB5_WITH_3DES_EDE_CBC_MD5', + 'KRB5-DES-CBC3-SHA': 'TLS_KRB5_WITH_3DES_EDE_CBC_SHA', + 'KRB5-IDEA-CBC-MD5': 'TLS_KRB5_WITH_IDEA_CBC_MD5', + 'KRB5-IDEA-CBC-SHA': 'TLS_KRB5_WITH_IDEA_CBC_SHA', + 'KRB5-RC4-MD5': 'TLS_KRB5_WITH_RC4_128_MD5', + 'KRB5-RC4-SHA': 'TLS_KRB5_WITH_RC4_128_SHA', + 'NULL-MD5': 'TLS_NULL_WITH_NULL_NULL', + 'NULL-MD5': 'TLS_RSA_WITH_NULL_MD5', + 'NULL-SHA': 'TLS_RSA_WITH_NULL_SHA', + 'NULL-SHA256': 'TLS_RSA_WITH_NULL_SHA256', + 'PSK-3DES-EDE-CBC-SHA': 'TLS_PSK_WITH_3DES_EDE_CBC_SHA', + 'PSK-AES128-CBC-SHA': 'TLS_PSK_WITH_AES_128_CBC_SHA', + 'PSK-AES256-CBC-SHA': 'TLS_PSK_WITH_AES_256_CBC_SHA', + 'PSK-RC4-SHA': 'TLS_PSK_WITH_RC4_128_SHA', + 'RC2-CBC-MD5': 'SSL_CK_RC2_128_CBC_WITH_MD5', + 'RC4-64-MD5': 'SSL_CK_RC4_64_WITH_MD5', + 'RC4-MD5': 'SSL_CK_RC4_128_WITH_MD5', + 'RC4-MD5': 'TLS_RSA_WITH_RC4_128_MD5', + 'RC4-SHA': 'TLS_RSA_WITH_RC4_128_SHA', + 'SEED-SHA': 'TLS_RSA_WITH_SEED_CBC_SHA', + 'SRP-3DES-EDE-CBC-SHA': 'TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA', + 'SRP-AES-128-CBC-SHA': 'TLS_SRP_SHA_WITH_AES_128_CBC_SHA', + 'SRP-AES-256-CBC-SHA': 'TLS_SRP_SHA_WITH_AES_256_CBC_SHA', + 'SRP-DSS-3DES-EDE-CBC-SHA': 'TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA', + 'SRP-DSS-AES-128-CBC-SHA': 'TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA', + 'SRP-DSS-AES-256-CBC-SHA': 'TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA', + 'SRP-RSA-3DES-EDE-CBC-SHA': 'TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA', + 'SRP-RSA-AES-128-CBC-SHA': 'TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA', + 'SRP-RSA-AES-256-CBC-SHA': 'TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA', + 'TLS_FALLBACK_SCSV': 'TLS_FALLBACK_SCSV' +} + +RFC_TO_OPENSSL_NAMES = sdk_utils.invert_dict(OPENSSL_TO_RFC_NAMES) + + +def rfc_name(openssl_name: str) -> str: + return OPENSSL_TO_RFC_NAMES[openssl_name] + + +def openssl_name(rfc_name: str) -> str: + return RFC_TO_OPENSSL_NAMES[rfc_name]