Skip to content

Commit

Permalink
Enable specifying the tls protocol version to use via --tls-protocols…
Browse files Browse the repository at this point in the history
… argument (#234)

* Enable specifying the tls protocol version to use via --tls-protocols argument

* Added tls-protocols tlsv1.2 and tlsv1.3 tests to CI

* Removed spurious comment on tls protocol parsing

* Updated comment on TLS_PROTOCOLS env variable usage on tests
  • Loading branch information
filipecosta90 committed Sep 14, 2023
1 parent 4203084 commit bec3471
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ jobs:
run: |
TLS=1 ./tests/run_tests.sh
- name: Test OSS TCP TLS v1.2
if: matrix.platform == 'ubuntu-latest'
timeout-minutes: 10
run: |
TLS_PROTOCOLS="tlsv1.2" TLS=1 ./tests/run_tests.sh
- name: Test OSS TCP TLS v1.3
if: matrix.platform == 'ubuntu-latest'
timeout-minutes: 10
run: |
TLS_PROTOCOLS="tlsv1.3" TLS=1 ./tests/run_tests.sh
- name: Test OSS-CLUSTER TCP
timeout-minutes: 10
run: |
Expand Down
55 changes: 55 additions & 0 deletions memtier_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>

#define REDIS_TLS_PROTO_TLSv1 (1<<0)
#define REDIS_TLS_PROTO_TLSv1_1 (1<<1)
#define REDIS_TLS_PROTO_TLSv1_2 (1<<2)
#define REDIS_TLS_PROTO_TLSv1_3 (1<<3)

/* Use safe defaults */
#ifdef TLS1_3_VERSION
#define REDIS_TLS_PROTO_DEFAULT (REDIS_TLS_PROTO_TLSv1_2|REDIS_TLS_PROTO_TLSv1_3)
#else
#define REDIS_TLS_PROTO_DEFAULT (REDIS_TLS_PROTO_TLSv1_2)
#endif

#endif

#include <stdexcept>
Expand Down Expand Up @@ -296,6 +309,8 @@ static void config_init_defaults(struct benchmark_config *cfg)
cfg->hdr_prefix = "";
if (!cfg->print_percentiles.is_defined())
cfg->print_percentiles = config_quantiles("50,99,99.9");
if (!cfg->tls_protocols)
cfg->tls_protocols = REDIS_TLS_PROTO_DEFAULT;
}

static int generate_random_seed()
Expand Down Expand Up @@ -404,6 +419,7 @@ static int config_parse_args(int argc, char *argv[], struct benchmark_config *cf
o_tls_cacert,
o_tls_skip_verify,
o_tls_sni,
o_tls_protocols,
o_hdr_file_prefix,
o_help
};
Expand All @@ -423,6 +439,7 @@ static int config_parse_args(int argc, char *argv[], struct benchmark_config *cf
{ "cacert", 1, 0, o_tls_cacert },
{ "tls-skip-verify", 0, 0, o_tls_skip_verify },
{ "sni", 1, 0, o_tls_sni },
{ "tls-protocols", 1, 0, o_tls_protocols },
#endif
{ "out-file", 1, 0, 'o' },
{ "hdr-file-prefix", 1, 0, o_hdr_file_prefix },
Expand Down Expand Up @@ -863,6 +880,34 @@ static int config_parse_args(int argc, char *argv[], struct benchmark_config *cf
case o_tls_sni:
cfg->tls_sni = optarg;
break;
case o_tls_protocols:
{
const char tls_delimiter = ',';
char* tls_token = strtok(optarg, &tls_delimiter);
while (tls_token != nullptr) {
if (!strcasecmp(tls_token, "tlsv1"))
cfg->tls_protocols |= REDIS_TLS_PROTO_TLSv1;
else if (!strcasecmp(tls_token, "tlsv1.1"))
cfg->tls_protocols |= REDIS_TLS_PROTO_TLSv1_1;
else if (!strcasecmp(tls_token, "tlsv1.2"))
cfg->tls_protocols |= REDIS_TLS_PROTO_TLSv1_2;
else if (!strcasecmp(tls_token, "tlsv1.3")) {
#ifdef TLS1_3_VERSION
cfg->tls_protocols |= REDIS_TLS_PROTO_TLSv1_3;
#else
fprintf(stderr, "TLSv1.3 is specified in tls-protocols but not supported by OpenSSL.");
return -1;
#endif
} else {
fprintf(stderr, "Invalid tls-protocols specified. "
"Use a combination of 'TLSv1', 'TLSv1.1', 'TLSv1.2' and 'TLSv1.3'.");
return -1;
break;
}
tls_token = strtok(nullptr, &tls_delimiter);
}
break;
}
#endif
default:
return -1;
Expand Down Expand Up @@ -903,6 +948,7 @@ void usage() {
" --key=FILE Use specified private key for TLS\n"
" --cacert=FILE Use specified CA certs bundle for TLS\n"
" --tls-skip-verify Skip verification of server certificate\n"
" --tls-protocols Specify the tls protocol version to use, comma delemited. Use a combination of 'TLSv1', 'TLSv1.1', 'TLSv1.2' and 'TLSv1.3'"
" --sni=STRING Add an SNI header\n"
#endif
" -x, --run-count=NUMBER Number of full-test iterations to perform\n"
Expand Down Expand Up @@ -1311,6 +1357,15 @@ int main(int argc, char *argv[])
cfg.openssl_ctx = SSL_CTX_new(SSLv23_client_method());
SSL_CTX_set_options(cfg.openssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

if (!(cfg.tls_protocols & REDIS_TLS_PROTO_TLSv1))
SSL_CTX_set_options(cfg.openssl_ctx, SSL_OP_NO_TLSv1);
if (!(cfg.tls_protocols & REDIS_TLS_PROTO_TLSv1_1))
SSL_CTX_set_options(cfg.openssl_ctx, SSL_OP_NO_TLSv1_1);
if (!(cfg.tls_protocols & REDIS_TLS_PROTO_TLSv1_2))
SSL_CTX_set_options(cfg.openssl_ctx, SSL_OP_NO_TLSv1_2);
if (!(cfg.tls_protocols & REDIS_TLS_PROTO_TLSv1_3))
SSL_CTX_set_options(cfg.openssl_ctx, SSL_OP_NO_TLSv1_3);

if (cfg.tls_cert) {
if (!SSL_CTX_use_certificate_chain_file(cfg.openssl_ctx, cfg.tls_cert)) {
ERR_print_errors_fp(stderr);
Expand Down
1 change: 1 addition & 0 deletions memtier_benchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ struct benchmark_config {
const char *tls_cacert;
bool tls_skip_verify;
const char *tls_sni;
int tls_protocols;
SSL_CTX *openssl_ctx;
#endif
};
Expand Down
14 changes: 14 additions & 0 deletions tests/include.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
TLS_CERT = os.environ.get("TLS_CERT", "")
TLS_KEY = os.environ.get("TLS_KEY", "")
TLS_CACERT = os.environ.get("TLS_CACERT", "")
TLS_PROTOCOLS = os.environ.get("TLS_PROTOCOLS", "")


def ensure_tls_protocols(master_nodes_connections):
if TLS_PROTOCOLS != "":
# if we've specified the TLS_PROTOCOLS env variable ensure the server enforces thos protocol versions
for master_connection in master_nodes_connections:
master_connection.execute_command("CONFIG", "SET", "tls-protocols", TLS_PROTOCOLS)


def assert_minimum_memtier_outcomes(config, env, memtier_ok, overall_expected_request_count,
Expand All @@ -24,6 +32,10 @@ def assert_minimum_memtier_outcomes(config, env, memtier_ok, overall_expected_re
debugPrintMemtierOnError(config, env)

def add_required_env_arguments(benchmark_specs, config, env, master_nodes_list):
# if we've specified TLS_PROTOCOLS ensure we configure it on redis
master_nodes_connections = env.getOSSMasterNodesConnectionList()
ensure_tls_protocols(master_nodes_connections)

# check if environment is cluster
if env.isCluster():
benchmark_specs["args"].append("--cluster-mode")
Expand Down Expand Up @@ -91,6 +103,8 @@ def addTLSArgs(benchmark_specs, env):
benchmark_specs['args'].append('--key={}'.format(TLS_KEY))
else:
benchmark_specs['args'].append('--tls-skip-verify')
if TLS_PROTOCOLS != "":
benchmark_specs['args'].append('--tls-protocols={}'.format(TLS_PROTOCOLS))



Expand Down

0 comments on commit bec3471

Please sign in to comment.