Merge pull request #40 from Snapchat/tls_cert_rotation
Added support for TLS certificate rotation.
This commit is contained in:
commit
2677899cd4
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@ -31,3 +31,6 @@ jobs:
|
|||||||
- name: module tests
|
- name: module tests
|
||||||
run: |
|
run: |
|
||||||
./runtest-moduleapi
|
./runtest-moduleapi
|
||||||
|
- name: rotation test
|
||||||
|
run: |
|
||||||
|
./runtest-rotation
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -48,7 +48,7 @@ src/nodes.conf
|
|||||||
deps/lua/src/lua
|
deps/lua/src/lua
|
||||||
deps/lua/src/luac
|
deps/lua/src/luac
|
||||||
deps/lua/src/liblua.a
|
deps/lua/src/liblua.a
|
||||||
tests/tls/*
|
tests/tls*/*
|
||||||
.make-*
|
.make-*
|
||||||
.prerequisites
|
.prerequisites
|
||||||
*.dSYM
|
*.dSYM
|
||||||
|
@ -122,13 +122,6 @@ installed):
|
|||||||
% ./runtest --tls
|
% ./runtest --tls
|
||||||
|
|
||||||
|
|
||||||
If TLS is built, running the tests with TLS enabled (you will need `tcl-tls`
|
|
||||||
installed):
|
|
||||||
|
|
||||||
% ./utils/gen-test-certs.sh
|
|
||||||
% ./runtest --tls
|
|
||||||
|
|
||||||
|
|
||||||
Fixing build problems with dependencies or cached build options
|
Fixing build problems with dependencies or cached build options
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
@ -257,6 +257,11 @@ tcp-keepalive 300
|
|||||||
#
|
#
|
||||||
# tls-session-cache-timeout 60
|
# tls-session-cache-timeout 60
|
||||||
|
|
||||||
|
# Allow the server to monitor the filesystem and rotate out TLS certificates if
|
||||||
|
# they change on disk, defaults to no.
|
||||||
|
#
|
||||||
|
# tls-rotation no
|
||||||
|
|
||||||
################################# GENERAL #####################################
|
################################# GENERAL #####################################
|
||||||
|
|
||||||
# By default KeyDB does not run as a daemon. Use 'yes' if you need it.
|
# By default KeyDB does not run as a daemon. Use 'yes' if you need it.
|
||||||
|
31
runtest-rotation
Executable file
31
runtest-rotation
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
TCL_VERSIONS="8.5 8.6"
|
||||||
|
TCLSH=""
|
||||||
|
|
||||||
|
export ASAN_OPTIONS=allocator_may_return_null=1 $ASAN_OPTIONS
|
||||||
|
|
||||||
|
for VERSION in $TCL_VERSIONS; do
|
||||||
|
TCL=`which tclsh$VERSION 2>/dev/null` && TCLSH=$TCL
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z $TCLSH ]
|
||||||
|
then
|
||||||
|
echo "You need tcl 8.5 or newer in order to run the KeyDB test"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -r tests/tls ] || [ ! -r tests/tls_1 ] || [ ! -r tests/tls_2 ];
|
||||||
|
then
|
||||||
|
echo "Generating neccessary certificates for TLS rotation testing."
|
||||||
|
rm -rf tests/tls tests/tls_1 tests/tls_2
|
||||||
|
|
||||||
|
utils/gen-test-certs.sh
|
||||||
|
mv tests/tls tests/tls_1
|
||||||
|
utils/gen-test-certs.sh
|
||||||
|
mv tests/tls tests/tls_2
|
||||||
|
utils/gen-test-certs.sh
|
||||||
|
fi
|
||||||
|
$TCLSH tests/test_helper.tcl \
|
||||||
|
--single unit/tls-rotation \
|
||||||
|
--tls \
|
||||||
|
--config server-threads 3 \
|
||||||
|
"${@}"
|
@ -2863,6 +2863,7 @@ standardConfig configs[] = {
|
|||||||
createEnumConfig("tls-auth-clients", NULL, MODIFIABLE_CONFIG, tls_auth_clients_enum, g_pserver->tls_auth_clients, TLS_CLIENT_AUTH_YES, NULL, NULL),
|
createEnumConfig("tls-auth-clients", NULL, MODIFIABLE_CONFIG, tls_auth_clients_enum, g_pserver->tls_auth_clients, TLS_CLIENT_AUTH_YES, NULL, NULL),
|
||||||
createBoolConfig("tls-prefer-server-ciphers", NULL, MODIFIABLE_CONFIG, g_pserver->tls_ctx_config.prefer_server_ciphers, 0, NULL, updateTlsCfgBool),
|
createBoolConfig("tls-prefer-server-ciphers", NULL, MODIFIABLE_CONFIG, g_pserver->tls_ctx_config.prefer_server_ciphers, 0, NULL, updateTlsCfgBool),
|
||||||
createBoolConfig("tls-session-caching", NULL, MODIFIABLE_CONFIG, g_pserver->tls_ctx_config.session_caching, 1, NULL, updateTlsCfgBool),
|
createBoolConfig("tls-session-caching", NULL, MODIFIABLE_CONFIG, g_pserver->tls_ctx_config.session_caching, 1, NULL, updateTlsCfgBool),
|
||||||
|
createBoolConfig("tls-rotation", NULL, MODIFIABLE_CONFIG, g_pserver->tls_rotation, 0, NULL, updateTlsCfgBool),
|
||||||
createStringConfig("tls-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->tls_ctx_config.cert_file, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->tls_ctx_config.cert_file, NULL, NULL, updateTlsCfg),
|
||||||
createStringConfig("tls-key-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->tls_ctx_config.key_file, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-key-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->tls_ctx_config.key_file, NULL, NULL, updateTlsCfg),
|
||||||
createStringConfig("tls-key-file-pass", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->tls_ctx_config.key_file_pass, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-key-file-pass", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, g_pserver->tls_ctx_config.key_file_pass, NULL, NULL, updateTlsCfg),
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "hiredis.h"
|
#include "hiredis.h"
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
#include "openssl/ssl.h"
|
#include <openssl/ssl.h>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "hiredis_ssl.h"
|
#include "hiredis_ssl.h"
|
||||||
}
|
}
|
||||||
|
@ -2578,6 +2578,13 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
|||||||
fastlock_auto_adjust_waits();
|
fastlock_auto_adjust_waits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reload the TLS cert if neccessary. This effectively rotates the
|
||||||
|
* cert if a change has been made on disk, but the KeyDB server hasn't
|
||||||
|
* been notified. */
|
||||||
|
run_with_period(1000){
|
||||||
|
tlsReload();
|
||||||
|
}
|
||||||
|
|
||||||
/* Resize tracking keys table if needed. This is also done at every
|
/* Resize tracking keys table if needed. This is also done at every
|
||||||
* command execution, but we want to be sure that if the last command
|
* command execution, but we want to be sure that if the last command
|
||||||
* executed changes the value via CONFIG SET, the server will perform
|
* executed changes the value via CONFIG SET, the server will perform
|
||||||
|
@ -1915,6 +1915,12 @@ typedef struct redisTLSContextConfig {
|
|||||||
int session_caching;
|
int session_caching;
|
||||||
int session_cache_size;
|
int session_cache_size;
|
||||||
int session_cache_timeout;
|
int session_cache_timeout;
|
||||||
|
time_t cert_file_last_modified;
|
||||||
|
time_t key_file_last_modified;
|
||||||
|
time_t client_cert_file_last_modified;
|
||||||
|
time_t client_key_file_last_modified;
|
||||||
|
time_t ca_cert_file_last_modified;
|
||||||
|
time_t ca_cert_dir_last_modified;
|
||||||
} redisTLSContextConfig;
|
} redisTLSContextConfig;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------
|
/*-----------------------------------------------------------------------------
|
||||||
@ -2606,6 +2612,7 @@ struct redisServer {
|
|||||||
int tls_cluster;
|
int tls_cluster;
|
||||||
int tls_replication;
|
int tls_replication;
|
||||||
int tls_auth_clients;
|
int tls_auth_clients;
|
||||||
|
int tls_rotation;
|
||||||
redisTLSContextConfig tls_ctx_config;
|
redisTLSContextConfig tls_ctx_config;
|
||||||
|
|
||||||
/* cpu affinity */
|
/* cpu affinity */
|
||||||
@ -3881,7 +3888,7 @@ void tlsInit(void);
|
|||||||
void tlsInitThread();
|
void tlsInitThread();
|
||||||
void tlsCleanup(void);
|
void tlsCleanup(void);
|
||||||
int tlsConfigure(redisTLSContextConfig *ctx_config);
|
int tlsConfigure(redisTLSContextConfig *ctx_config);
|
||||||
|
void tlsReload(void);
|
||||||
|
|
||||||
|
|
||||||
class ShutdownException
|
class ShutdownException
|
||||||
|
51
src/tls.cpp
51
src/tls.cpp
@ -35,13 +35,14 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
|
|
||||||
#include <openssl/conf.h>
|
#include <openssl/conf.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#define REDIS_TLS_PROTO_TLSv1 (1<<0)
|
#define REDIS_TLS_PROTO_TLSv1 (1<<0)
|
||||||
#define REDIS_TLS_PROTO_TLSv1_1 (1<<1)
|
#define REDIS_TLS_PROTO_TLSv1_1 (1<<1)
|
||||||
#define REDIS_TLS_PROTO_TLSv1_2 (1<<2)
|
#define REDIS_TLS_PROTO_TLSv1_2 (1<<2)
|
||||||
@ -206,6 +207,18 @@ static int tlsPasswordCallback(char *buf, int size, int rwflag, void *u) {
|
|||||||
return (int) pass_len;
|
return (int) pass_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given a path to a file, return the last time it was accessed (in seconds) */
|
||||||
|
time_t getLastModifiedTime(const char* path){
|
||||||
|
struct stat path_stat;
|
||||||
|
stat(path, &path_stat);
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
return path_stat.st_mtimespec.tv_sec;
|
||||||
|
#else
|
||||||
|
return path_stat.st_mtime;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a *base* SSL_CTX using the SSL configuration provided. The base context
|
/* Create a *base* SSL_CTX using the SSL configuration provided. The base context
|
||||||
* includes everything that's common for both client-side and server-side connections.
|
* includes everything that's common for both client-side and server-side connections.
|
||||||
*/
|
*/
|
||||||
@ -310,6 +323,14 @@ int tlsConfigure(redisTLSContextConfig *ctx_config) {
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the last modified times for the TLS elements */
|
||||||
|
ctx_config->key_file_last_modified = getLastModifiedTime(ctx_config->key_file);
|
||||||
|
ctx_config->cert_file_last_modified = getLastModifiedTime(ctx_config->cert_file);
|
||||||
|
ctx_config->client_cert_file_last_modified = getLastModifiedTime(ctx_config->client_cert_file);
|
||||||
|
ctx_config->client_key_file_last_modified = getLastModifiedTime(ctx_config->client_key_file);
|
||||||
|
ctx_config->ca_cert_dir_last_modified = getLastModifiedTime(ctx_config->ca_cert_dir);
|
||||||
|
ctx_config->ca_cert_file_last_modified = getLastModifiedTime(ctx_config->ca_cert_file);
|
||||||
|
|
||||||
protocols = parseProtocolsConfig(ctx_config->protocols);
|
protocols = parseProtocolsConfig(ctx_config->protocols);
|
||||||
if (protocols == -1) goto error;
|
if (protocols == -1) goto error;
|
||||||
|
|
||||||
@ -385,6 +406,31 @@ error:
|
|||||||
return C_ERR;
|
return C_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reload TLS certificate from disk, effectively rotating it */
|
||||||
|
void tlsReload(void){
|
||||||
|
/* We will only bother checking keys and certs if TLS is enabled, otherwise we would be calling 'stat' for no reason */
|
||||||
|
if (g_pserver->tls_rotation && (g_pserver->tls_port || g_pserver->tls_replication || g_pserver->tls_cluster)){
|
||||||
|
|
||||||
|
bool cert_file_modified = getLastModifiedTime(g_pserver->tls_ctx_config.cert_file) != g_pserver->tls_ctx_config.cert_file_last_modified;
|
||||||
|
bool key_file_modified = getLastModifiedTime(g_pserver->tls_ctx_config.key_file) != g_pserver->tls_ctx_config.key_file_last_modified;
|
||||||
|
|
||||||
|
bool client_cert_file_modified = g_pserver->tls_ctx_config.client_cert_file != NULL && getLastModifiedTime(g_pserver->tls_ctx_config.client_cert_file) != g_pserver->tls_ctx_config.client_cert_file_last_modified;
|
||||||
|
bool client_key_file_modified = g_pserver->tls_ctx_config.client_key_file != NULL && getLastModifiedTime(g_pserver->tls_ctx_config.client_key_file) != g_pserver->tls_ctx_config.client_key_file_last_modified;
|
||||||
|
|
||||||
|
bool ca_cert_file_modified = g_pserver->tls_ctx_config.ca_cert_file != NULL && getLastModifiedTime(g_pserver->tls_ctx_config.ca_cert_file) != g_pserver->tls_ctx_config.ca_cert_file_last_modified;
|
||||||
|
bool ca_cert_dir_modified = g_pserver->tls_ctx_config.ca_cert_dir != NULL && getLastModifiedTime(g_pserver->tls_ctx_config.ca_cert_dir) != g_pserver->tls_ctx_config.ca_cert_dir_last_modified;
|
||||||
|
|
||||||
|
if (cert_file_modified || key_file_modified || ca_cert_file_modified || ca_cert_dir_modified || client_cert_file_modified || client_key_file_modified){
|
||||||
|
serverLog(LL_NOTICE, "TLS certificates changed on disk, attempting to rotate.");
|
||||||
|
if (tlsConfigure(&g_pserver->tls_ctx_config) == C_ERR) {
|
||||||
|
serverLog(LL_NOTICE, "Error trying to rotate TLS certificates, TLS credentials remain unchanged.");
|
||||||
|
} else {
|
||||||
|
serverLog(LL_NOTICE, "TLS certificates rotated successfully.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TLS_DEBUGGING
|
#ifdef TLS_DEBUGGING
|
||||||
#define TLSCONN_DEBUG(fmt, ...) \
|
#define TLSCONN_DEBUG(fmt, ...) \
|
||||||
serverLog(LL_DEBUG, "TLSCONN: " fmt, __VA_ARGS__)
|
serverLog(LL_DEBUG, "TLSCONN: " fmt, __VA_ARGS__)
|
||||||
@ -1093,6 +1139,9 @@ int tlsConfigure(redisTLSContextConfig *ctx_config) {
|
|||||||
return C_OK;
|
return C_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tlsReload(void){
|
||||||
|
}
|
||||||
|
|
||||||
connection *connCreateTLS(void) {
|
connection *connCreateTLS(void) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -242,6 +242,26 @@ proc redis_client {args} {
|
|||||||
return $client
|
return $client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proc redis_client_tls {args} {
|
||||||
|
set level 0
|
||||||
|
if {[llength $args] > 0 && [string is integer [lindex $args 0]]} {
|
||||||
|
set level [lindex $args 0]
|
||||||
|
set args [lrange $args 1 end]
|
||||||
|
}
|
||||||
|
|
||||||
|
set tlsoptions ""
|
||||||
|
if {[llength $args] > 0 && ![string is integer [lindex $args 0]]} {
|
||||||
|
set tlsoptions [lrange $args 0 end]
|
||||||
|
}
|
||||||
|
|
||||||
|
# create client that takes in custom tls options
|
||||||
|
set client [redis [srv $level "host"] [srv $level "port"] 0 $::tls $tlsoptions]
|
||||||
|
|
||||||
|
# # select the right db and read the response (OK)
|
||||||
|
$client select 9
|
||||||
|
return $client
|
||||||
|
}
|
||||||
|
|
||||||
# Provide easy access to INFO properties. Same semantic as "proc r".
|
# Provide easy access to INFO properties. Same semantic as "proc r".
|
||||||
proc s {args} {
|
proc s {args} {
|
||||||
set level 0
|
set level 0
|
||||||
@ -273,6 +293,7 @@ proc cleanup {} {
|
|||||||
flush stdout
|
flush stdout
|
||||||
catch {exec rm -rf {*}[glob tests/tmp/redis.conf.*]}
|
catch {exec rm -rf {*}[glob tests/tmp/redis.conf.*]}
|
||||||
catch {exec rm -rf {*}[glob tests/tmp/server.*]}
|
catch {exec rm -rf {*}[glob tests/tmp/server.*]}
|
||||||
|
catch {exec rm -rf {*}[glob tests/tmp/tlscerts.*]}
|
||||||
if {!$::quiet} {puts "OK"}
|
if {!$::quiet} {puts "OK"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
109
tests/unit/tls-rotation.tcl
Normal file
109
tests/unit/tls-rotation.tcl
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
start_server {tags {"tls-rotation"} overrides {tls-rotation yes}} {
|
||||||
|
if {$::tls} {
|
||||||
|
package require tls
|
||||||
|
|
||||||
|
test {TLS: Create temporary location for certificate rotation} {
|
||||||
|
set rootdir [tmpdir tlscerts]
|
||||||
|
|
||||||
|
file copy "tests/tls" $rootdir
|
||||||
|
file copy "tests/tls_1" $rootdir
|
||||||
|
file copy "tests/tls_2" $rootdir
|
||||||
|
|
||||||
|
set serverdir [format "%s/$rootdir/tls" [pwd]]
|
||||||
|
set clientdir1 [format "%s/$rootdir/tls_1" [pwd]]
|
||||||
|
set clientdir2 [format "%s/$rootdir/tls_2" [pwd]]
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Update server config to point to temporary location } {
|
||||||
|
r config set tls-key-file "$serverdir/server.key"
|
||||||
|
r config set tls-cert-file "$serverdir/server.crt"
|
||||||
|
r config set tls-ca-cert-file "$serverdir/ca.crt"
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Connect client to server} {
|
||||||
|
set r2 [redis_client_tls -keyfile "$serverdir/client.key" -certfile "$serverdir/client.crt" -require 1 -cafile "$serverdir/ca.crt"]
|
||||||
|
$r2 set x 50
|
||||||
|
assert_equal {50} [$r2 get x]
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Rotate all TLS certificates} {
|
||||||
|
file delete -force -- $serverdir
|
||||||
|
file copy $clientdir1 $serverdir
|
||||||
|
after 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Already connected clients do not lose connection post certificate rotation} {
|
||||||
|
$r2 incrby x 50
|
||||||
|
assert_equal {100} [$r2 get x]
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Clients with outdated credentials cannot connect} {
|
||||||
|
catch {set r2 [redis_client_tls -keyfile "$clientdir2/client.key" -certfile "$clientdir2/client.crt" -require 1 -cafile "$clientdir2/ca.crt"]} e
|
||||||
|
assert_no_match {*::redis::redisHandle*} $e
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Clients with correct certifcates can cannect to server post rotation} {
|
||||||
|
set r2 [redis_client_tls -keyfile "$clientdir1/client.key" -certfile "$clientdir1/client.crt" -require 1 -cafile "$clientdir1/ca.crt"]
|
||||||
|
$r2 incrby x 50
|
||||||
|
assert_equal {150} [$r2 get x]
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Rotate only server key causing key/cert mismatch} {
|
||||||
|
file copy -force -- "$clientdir2/server.key" $serverdir
|
||||||
|
after 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Already connected clients do not lose connection despite mismatch} {
|
||||||
|
$r2 incrby x 50
|
||||||
|
assert_equal {200} [$r2 get x]
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Clients with old credentials can still connect} {
|
||||||
|
set r2 [redis_client_tls -keyfile "$clientdir1/client.key" -certfile "$clientdir1/client.crt" -require 1 -cafile "$clientdir1/ca.crt"]
|
||||||
|
$r2 incrby x 50
|
||||||
|
assert_equal {250} [$r2 get x]
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Rotate corresponding cert fixing key/cert mismatch} {
|
||||||
|
file copy -force -- "$clientdir2/server.crt" $serverdir
|
||||||
|
after 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Check that old client is still connected post rotation} {
|
||||||
|
$r2 incrby x 50
|
||||||
|
assert_equal {300} [$r2 get x]
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Clients with outdated credentials cannot connect} {
|
||||||
|
catch {set r2 [redis_client_tls -keyfile "$clientdir1/client.key" -certfile "$clientdir1/client.crt" -require 1 -cafile "$clientdir1/ca.crt"]} e
|
||||||
|
assert_no_match {*::redis::redisHandle*} $e
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Clients with correct certifcates can cannect to server post rotation} {
|
||||||
|
set r2 [redis_client_tls -keyfile "$clientdir1/client.key" -certfile "$clientdir1/client.crt" -require 1 -cafile "$clientdir2/ca.crt"]
|
||||||
|
$r2 incrby x 50
|
||||||
|
assert_equal {350} [$r2 get x]
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Rotate only CA cert} {
|
||||||
|
file copy -force -- "$clientdir2/ca.crt" $serverdir
|
||||||
|
after 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Check that old client is still connected} {
|
||||||
|
$r2 incrby x 50
|
||||||
|
assert_equal {400} [$r2 get x]
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Check that client with old credentials won't connect} {
|
||||||
|
catch {set r2 [redis_client_tls -keyfile "$clientdir1/client.key" -certfile "$clientdir1/client.crt" -require 1 -cafile "$clientdir2/ca.crt"]} e
|
||||||
|
assert_no_match {*::redis::redisHandle*} $e
|
||||||
|
}
|
||||||
|
|
||||||
|
test {TLS: Check that client with updated credentials will connect} {
|
||||||
|
catch {set r2 [redis_client_tls -keyfile "$clientdir2/client.key" -certfile "$clientdir2/client.crt" -require 1 -cafile "$clientdir2/ca.crt"]} e
|
||||||
|
$r2 incrby x 50
|
||||||
|
assert_equal {450} [$r2 get x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
start_server {tags {"tls"}} {
|
start_server {tags {"tls"} overrides {tls-rotation yes}} {
|
||||||
if {$::tls} {
|
if {$::tls} {
|
||||||
package require tls
|
package require tls
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user