Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c5994f2

Browse files
yatsukhnenkoPavel Yatsukhnenko
authored andcommitted
RedisCluster auth
1 parent e145f85 commit c5994f2

9 files changed

Lines changed: 90 additions & 25 deletions

File tree

cluster.markdown

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ $obj_cluster = new RedisCluster(NULL, Array("host:7000", "host:7001"), 1.5, 1.5)
1919
// persistent connections to each node.
2020
$obj_cluster = new RedisCluster(NULL, Array("host:7000", "host:7001"), 1.5, 1.5, true);
2121

22+
// Connect with cluster using password.
23+
$obj_cluster = new RedisCluster(NULL, Array("host:7000", "host:7001"), 1.5, 1.5, true, "password");
24+
2225
</pre>
2326

2427
#### Loading a cluster configuration by name
@@ -29,6 +32,7 @@ In order to load a named array, one must first define the seed nodes in redis.in
2932
redis.clusters.seeds = "mycluster[]=localhost:7000&test[]=localhost:7001"
3033
redis.clusters.timeout = "mycluster=5"
3134
redis.clusters.read_timeout = "mycluster=10"
35+
redis.clusters.auth = "mycluster=password"
3236
</pre>
3337

3438
Then, this cluster can be loaded by doing the following
@@ -161,7 +165,7 @@ To do this, you must configure your `session.save_handler` and `session.save_pat
161165

162166
~~~
163167
session.save_handler = rediscluster
164-
session.save_path = "seed[]=host1:port1&seed[]=host2:port2&seed[]=hostN:portN&timeout=2&read_timeout=2&failover=error&persistent=1"
168+
session.save_path = "seed[]=host1:port1&seed[]=host2:port2&seed[]=hostN:portN&timeout=2&read_timeout=2&failover=error&persistent=1&auth=password"
165169
~~~
166170

167171
### session.session_handler
@@ -175,5 +179,6 @@ The save path for cluster based session storage takes the form of a PHP GET requ
175179
* _persistent_: Tells phpredis whether persistent connections should be used.
176180
* _distribute_: phpredis will randomly distribute session reads between masters and any attached slaves (load balancing).
177181
* _failover (string)_: How phpredis should distribute session reads between master and slave nodes.
182+
* _auth (string, empty by default)_: The password used to authenticate with the server prior to sending commands.
178183
* * _none_ : phpredis will only communicate with master nodes
179184
* * _error_: phpredis will communicate with master nodes unless one failes, in which case an attempt will be made to read session information from a slave.

cluster_library.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,17 @@ cluster_read_sock_resp(RedisSock *redis_sock, REDIS_REPLY_TYPE type,
259259
return r;
260260
}
261261

262+
/* Helper to open connection and send AUTH if necessary */
263+
static zend_always_inline int
264+
cluster_sock_open(RedisSock *redis_sock TSRMLS_DC)
265+
{
266+
zend_bool need_auth = (redis_sock->auth && redis_sock->status != REDIS_SOCK_STATUS_CONNECTED);
267+
if (!redis_sock_server_open(redis_sock TSRMLS_CC) && (!need_auth || !redis_sock_auth(redis_sock TSRMLS_CC))) {
268+
return SUCCESS;
269+
}
270+
return FAILURE;
271+
}
272+
262273
/*
263274
* Helpers to send various 'control type commands to a specific node, e.g.
264275
* MULTI, ASKING, READONLY, READWRITE, etc
@@ -654,6 +665,10 @@ cluster_node_create(redisCluster *c, char *host, size_t host_len,
654665
node->sock = redis_sock_create(host, host_len, port, c->timeout,
655666
c->read_timeout, c->persistent, NULL, 0);
656667

668+
if (c->auth) {
669+
node->sock->auth = zend_string_copy(c->auth);
670+
}
671+
657672
return node;
658673
}
659674

@@ -824,6 +839,7 @@ PHP_REDIS_API redisCluster *cluster_create(double timeout, double read_timeout,
824839
c->read_timeout = read_timeout;
825840
c->failover = failover;
826841
c->persistent = persistent;
842+
c->auth = NULL;
827843
c->err = NULL;
828844

829845
/* Set up our waitms based on timeout */
@@ -858,6 +874,9 @@ cluster_free(redisCluster *c, int free_ctx TSRMLS_DC)
858874
efree(c->seeds);
859875
efree(c->nodes);
860876

877+
/* Free auth info we've got */
878+
if (c->auth) zend_string_release(c->auth);
879+
861880
/* Free any error we've got */
862881
if (c->err) zend_string_release(c->err);
863882

@@ -925,6 +944,11 @@ cluster_init_seeds(redisCluster *cluster, HashTable *ht_seeds) {
925944
(unsigned short)atoi(psep+1), cluster->timeout,
926945
cluster->read_timeout, cluster->persistent, NULL, 0);
927946

947+
// Set auth information if specified
948+
if (cluster->auth) {
949+
redis_sock->auth = zend_string_copy(cluster->auth);
950+
}
951+
928952
// Index this seed by host/port
929953
key_len = snprintf(key, sizeof(key), "%s:%u", ZSTR_VAL(redis_sock->host),
930954
redis_sock->port);
@@ -948,7 +972,7 @@ PHP_REDIS_API int cluster_map_keyspace(redisCluster *c TSRMLS_DC) {
948972
// Iterate over seeds until we can get slots
949973
ZEND_HASH_FOREACH_PTR(c->seeds, seed) {
950974
// Attempt to connect to this seed node
951-
if (seed == NULL || redis_sock_connect(seed TSRMLS_CC) != 0) {
975+
if (seed == NULL || cluster_sock_open(seed TSRMLS_CC) != 0) {
952976
continue;
953977
}
954978

@@ -1119,11 +1143,6 @@ static int cluster_dist_write(redisCluster *c, const char *cmd, size_t sz,
11191143
redis_sock = cluster_slot_sock(c, c->cmd_slot, nodes[i]);
11201144
if (!redis_sock) continue;
11211145

1122-
/* Connect to this node if we haven't already */
1123-
if(redis_sock_server_open(redis_sock TSRMLS_CC)) {
1124-
continue;
1125-
}
1126-
11271146
/* If we're not on the master, attempt to send the READONLY command to
11281147
* this slave, and skip it if that fails */
11291148
if (nodes[i] == 0 || redis_sock->readonly ||

cluster_library.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262

6363
/* Protected sending of data down the wire to a RedisSock->stream */
6464
#define CLUSTER_SEND_PAYLOAD(sock, buf, len) \
65-
(sock && !redis_sock_server_open(sock TSRMLS_CC) && sock->stream && !redis_check_eof(sock, 1 TSRMLS_CC) && \
65+
(sock && !cluster_sock_open(sock TSRMLS_CC) && sock->stream && !redis_check_eof(sock, 1 TSRMLS_CC) && \
6666
php_stream_write(sock->stream, buf, len)==len)
6767

6868
/* Macro to read our reply type character */
@@ -170,6 +170,8 @@ typedef struct redisCluster {
170170
zend_object std;
171171
#endif
172172

173+
zend_string *auth;
174+
173175
/* Timeout and read timeout (for normal operations) */
174176
double timeout;
175177
double read_timeout;

common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ zend_string_realloc(zend_string *s, size_t len, int persistent)
6868
return zstr;
6969
}
7070

71+
#define zend_string_copy(s) zend_string_init(ZSTR_VAL(s), ZSTR_LEN(s), 0)
72+
7173
#define zend_string_equal_val(s1, s2) !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1))
7274
#define zend_string_equal_content(s1, s2) (ZSTR_LEN(s1) == ZSTR_LEN(s2) && zend_string_equal_val(s1, s2))
7375
#define zend_string_equals(s1, s2) (s1 == s2 || zend_string_equal_content(s1, s2))

library.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ static int reselect_db(RedisSock *redis_sock TSRMLS_DC) {
9090
}
9191

9292
/* Helper to resend AUTH <password> in the case of a reconnect */
93-
static int resend_auth(RedisSock *redis_sock TSRMLS_DC) {
93+
PHP_REDIS_API int
94+
redis_sock_auth(RedisSock *redis_sock TSRMLS_DC)
95+
{
9496
char *cmd, *response;
9597
int cmd_len, response_len;
9698

@@ -205,7 +207,7 @@ redis_check_eof(RedisSock *redis_sock, int no_throw TSRMLS_DC)
205207
errno = 0;
206208
if (php_stream_eof(redis_sock->stream) == 0) {
207209
/* If we're using a password, attempt a reauthorization */
208-
if (redis_sock->auth && resend_auth(redis_sock TSRMLS_CC) != 0) {
210+
if (redis_sock->auth && redis_sock_auth(redis_sock TSRMLS_CC) != 0) {
209211
errmsg = "AUTH failed while reconnecting";
210212
break;
211213
}

library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ PHP_REDIS_API void redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *
4545
PHP_REDIS_API RedisSock* redis_sock_create(char *host, int host_len, unsigned short port, double timeout, double read_timeout, int persistent, char *persistent_id, long retry_interval);
4646
PHP_REDIS_API int redis_sock_connect(RedisSock *redis_sock TSRMLS_DC);
4747
PHP_REDIS_API int redis_sock_server_open(RedisSock *redis_sock TSRMLS_DC);
48+
PHP_REDIS_API int redis_sock_auth(RedisSock *redis_sock TSRMLS_DC);
4849
PHP_REDIS_API int redis_sock_disconnect(RedisSock *redis_sock, int force TSRMLS_DC);
4950
PHP_REDIS_API zval *redis_sock_read_multibulk_reply_zval(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab);
5051
PHP_REDIS_API int redis_sock_read_single_line(RedisSock *redis_sock, char *buffer,

redis.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ PHP_INI_BEGIN()
6969
PHP_INI_ENTRY("redis.arrays.retryinterval", "0", PHP_INI_ALL, NULL)
7070

7171
/* redis cluster */
72+
PHP_INI_ENTRY("redis.clusters.auth", "", PHP_INI_ALL, NULL)
7273
PHP_INI_ENTRY("redis.clusters.persistent", "0", PHP_INI_ALL, NULL)
7374
PHP_INI_ENTRY("redis.clusters.read_timeout", "0", PHP_INI_ALL, NULL)
7475
PHP_INI_ENTRY("redis.clusters.seeds", "", PHP_INI_ALL, NULL)

redis_cluster.c

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ctor, 0, 0, 1)
4646
ZEND_ARG_INFO(0, timeout)
4747
ZEND_ARG_INFO(0, read_timeout)
4848
ZEND_ARG_INFO(0, persistent)
49+
ZEND_ARG_INFO(0, auth)
4950
ZEND_END_ARG_INFO()
5051

5152
ZEND_BEGIN_ARG_INFO_EX(arginfo_del, 0, 0, 1)
@@ -397,8 +398,10 @@ free_cluster_context(zend_object *object)
397398
#endif
398399

399400
/* Attempt to connect to a Redis cluster provided seeds and timeout options */
400-
void redis_cluster_init(redisCluster *c, HashTable *ht_seeds, double timeout,
401-
double read_timeout, int persistent TSRMLS_DC)
401+
static void
402+
redis_cluster_init(redisCluster *c, HashTable *ht_seeds,
403+
double timeout, double read_timeout, int persistent,
404+
char *auth, strlen_t auth_len TSRMLS_DC)
402405
{
403406
// Validate timeout
404407
if (timeout < 0L || timeout > INT_MAX) {
@@ -417,6 +420,11 @@ void redis_cluster_init(redisCluster *c, HashTable *ht_seeds, double timeout,
417420
zend_throw_exception(redis_cluster_exception_ce,
418421
"Must pass seeds", 0 TSRMLS_CC);
419422
}
423+
424+
if (auth && auth_len > 0) {
425+
c->auth = zend_string_init(auth, auth_len, 0);
426+
}
427+
420428
/* Set our timeout and read_timeout which we'll pass through to the
421429
* socket type operations */
422430
c->timeout = timeout;
@@ -438,8 +446,9 @@ void redis_cluster_init(redisCluster *c, HashTable *ht_seeds, double timeout,
438446

439447
/* Attempt to load a named cluster configured in php.ini */
440448
void redis_cluster_load(redisCluster *c, char *name, int name_len TSRMLS_DC) {
441-
zval z_seeds, z_timeout, z_read_timeout, z_persistent, *z_value;
442-
char *iptr;
449+
zval z_seeds, z_timeout, z_read_timeout, z_persistent, z_auth, *z_value;
450+
char *iptr, *auth = NULL;
451+
strlen_t auth_len = 0;
443452
double timeout = 0, read_timeout = 0;
444453
int persistent = 0;
445454
HashTable *ht_seeds = NULL;
@@ -500,14 +509,27 @@ void redis_cluster_load(redisCluster *c, char *name, int name_len TSRMLS_DC) {
500509
}
501510
}
502511

512+
/* Cluster auth */
513+
array_init(&z_auth);
514+
if ((iptr = INI_STR("redis.clusters.auth")) != NULL) {
515+
sapi_module.treat_data(PARSE_STRING, estrdup(iptr), &z_auth TSRMLS_CC);
516+
}
517+
if ((z_value = zend_hash_str_find(Z_ARRVAL(z_auth), name, name_len)) != NULL &&
518+
Z_TYPE_P(z_value) == IS_STRING && Z_STRLEN_P(z_value) > 0
519+
) {
520+
auth = Z_STRVAL_P(z_value);
521+
auth_len = Z_STRLEN_P(z_value);
522+
}
523+
503524
/* Attempt to create/connect to the cluster */
504-
redis_cluster_init(c, ht_seeds, timeout, read_timeout, persistent TSRMLS_CC);
525+
redis_cluster_init(c, ht_seeds, timeout, read_timeout, persistent, auth, auth_len TSRMLS_CC);
505526

506527
/* Clean up our arrays */
507528
zval_dtor(&z_seeds);
508529
zval_dtor(&z_timeout);
509530
zval_dtor(&z_read_timeout);
510531
zval_dtor(&z_persistent);
532+
zval_dtor(&z_auth);
511533
}
512534

513535
/*
@@ -517,17 +539,17 @@ void redis_cluster_load(redisCluster *c, char *name, int name_len TSRMLS_DC) {
517539
/* Create a RedisCluster Object */
518540
PHP_METHOD(RedisCluster, __construct) {
519541
zval *object, *z_seeds = NULL;
520-
char *name;
521-
strlen_t name_len;
542+
char *name, *auth = NULL;
543+
strlen_t name_len, auth_len = 0;
522544
double timeout = 0.0, read_timeout = 0.0;
523545
zend_bool persistent = 0;
524546
redisCluster *context = GET_CONTEXT();
525547

526548
// Parse arguments
527549
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
528-
"Os!|addb", &object, redis_cluster_ce, &name,
529-
&name_len, &z_seeds, &timeout,
530-
&read_timeout, &persistent) == FAILURE)
550+
"Os!|addbs", &object, redis_cluster_ce, &name,
551+
&name_len, &z_seeds, &timeout, &read_timeout,
552+
&persistent, &auth, &auth_len) == FAILURE)
531553
{
532554
RETURN_FALSE;
533555
}
@@ -543,7 +565,7 @@ PHP_METHOD(RedisCluster, __construct) {
543565
* to a named cluster, stored in php.ini, otherwise we'll need manual seeds */
544566
if (ZEND_NUM_ARGS() > 1) {
545567
redis_cluster_init(context, Z_ARRVAL_P(z_seeds), timeout, read_timeout,
546-
persistent TSRMLS_CC);
568+
persistent, auth, auth_len TSRMLS_CC);
547569
} else {
548570
redis_cluster_load(context, name, name_len TSRMLS_CC);
549571
}

redis_session.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -992,9 +992,9 @@ PS_OPEN_FUNC(rediscluster) {
992992
zval z_conf, *z_val;
993993
HashTable *ht_conf, *ht_seeds;
994994
double timeout = 0, read_timeout = 0;
995-
int persistent = 0;
996-
int retval, prefix_len, failover = REDIS_FAILOVER_NONE;
997-
char *prefix;
995+
int retval, persistent = 0, failover = REDIS_FAILOVER_NONE;
996+
strlen_t prefix_len, auth_len = 0;
997+
char *prefix, *auth = NULL;
998998

999999
/* Parse configuration for session handler */
10001000
array_init(&z_conf);
@@ -1041,7 +1041,7 @@ PS_OPEN_FUNC(rediscluster) {
10411041

10421042
/* Look for a specific failover setting */
10431043
if ((z_val = zend_hash_str_find(ht_conf, "failover", sizeof("failover") - 1)) != NULL &&
1044-
Z_TYPE_P(z_val) == IS_STRING
1044+
Z_TYPE_P(z_val) == IS_STRING && Z_STRLEN_P(z_val) > 0
10451045
) {
10461046
if (!strcasecmp(Z_STRVAL_P(z_val), "error")) {
10471047
failover = REDIS_FAILOVER_ERROR;
@@ -1050,7 +1050,18 @@ PS_OPEN_FUNC(rediscluster) {
10501050
}
10511051
}
10521052

1053+
/* Look for a specific auth setting */
1054+
if ((z_val = zend_hash_str_find(ht_conf, "auth", sizeof("auth") - 1)) != NULL &&
1055+
Z_TYPE_P(z_val) == IS_STRING && Z_STRLEN_P(z_val) > 0
1056+
) {
1057+
auth = Z_STRVAL_P(z_val);
1058+
auth_len = Z_STRLEN_P(z_val);
1059+
}
1060+
10531061
c = cluster_create(timeout, read_timeout, failover, persistent);
1062+
if (auth && auth_len > 0) {
1063+
c->auth = zend_string_init(auth, auth_len, 0);
1064+
}
10541065
if (!cluster_init_seeds(c, ht_seeds) && !cluster_map_keyspace(c TSRMLS_CC)) {
10551066
/* Set up our prefix */
10561067
c->flags->prefix = zend_string_init(prefix, prefix_len, 0);

0 commit comments

Comments
 (0)