Skip to content

Commit 49ab61c

Browse files
committed
allow defining additional commands as safe for read-only mode, defaulting to "info" and "select"
Signed-off-by: Stefan Seide <[email protected]>
1 parent bb5020e commit 49ab61c

File tree

7 files changed

+52
-5
lines changed

7 files changed

+52
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* add option to overwrite global folding character per connection
1515
* add Sentinel TLS connections and improved configuration and env var handling for TLS secured connections, #514
1616
* add Redis Cluster support, #160 #216 #527
17+
* allow defining additional commands as safe for read-only mode, defaulting to "info" and "select", #542
1718
* update base image to [email protected] using NodeJS 18.x now, #511
1819
* update helm chart autoscaling apis for newer K8s versions, #520
1920
* update helm chart to allow setting ingressClassName for newer K8s versions, #494

config/default.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919
"rootPattern": "*",
2020
"connectionName": "redis-commander",
2121
"defaultLabel": "local",
22-
"defaultSentinelGroup": "mymaster"
22+
"defaultSentinelGroup": "mymaster",
23+
"extraAllowedReadOnlyCommands": [
24+
"select",
25+
"info"
26+
]
2327
},
2428
"server": {
2529
"address": "0.0.0.0",

docs/configuration.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,39 @@ while the second connection to 10.9.8.7 uses '/' here:
9191
| redis.connectionName | string | 'redis-commander' | | REDIS_CONNECTION_NAME | connection name to set at redis client for easier identification of clients at redis server (command "client list") |
9292
| redis.defaultLabel | string | 'local' | | REDIS_LABEL | default label to display for a connection if no label is specified (e.g. for connection from env vars or command line) |
9393
| redis.defaultSentinelGroup | string | 'mymaster' | | | default redis database group if using sentinels to connect and no special database group via connection param 'sentinelName' is given. |
94+
| redis.extraAllowedReadOnlyCommands | list | ['select', 'info'] | | | list of additional redis commands allowed if set to read-only. See remark below |
95+
96+
#### Read-Only Mode
97+
98+
Setting the parameter `redis.readOnly` to `true` only commands not changing data are allowed. As Default the list with all read-only commands
99+
is directly queried from the server (calling "COMMANDS") and parsing the output for the "readonly" flag.
100+
101+
Some commands are not marked as read-only by there server - adding these commands to the list at `redis.extraAllowedReadOnlyCommands`
102+
allows them too being in readOnly mode. This list is not used if all commands are allowed (readOnly=false).
103+
104+
Attention: if this list shall be changed (ore set to emtpy) within a local config file (like `local.json`) the new
105+
value _overwrites_ the default list defined in the `default.json` file. The values are not appended and the full list of allowed
106+
commands must be configured in the local file.
107+
108+
Example (shortened) output from "COMMANDS" command showing `dbsize` flagged as readonly while `select` is not
109+
```
110+
61) 1) "select"
111+
2) (integer) 2
112+
3) 1) loading
113+
2) fast
114+
4) (integer) 0
115+
5) (integer) 0
116+
6) (integer) 0
117+
...
118+
86) 1) "dbsize"
119+
2) (integer) 1
120+
3) 1) readonly
121+
2) fast
122+
4) (integer) 0
123+
5) (integer) 0
124+
6) (integer) 0
125+
...
126+
```
94127

95128
### 4. Express HTTP Server parameter
96129

lib/connections.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,11 @@ class ConnectionWrapper {
306306
if (p[0].status === 'fulfilled' && Array.isArray(p[0].value)) {
307307
// console.debug('Got list of ' + p[0].value.length + ' commands from server ' + redisConnection.options.host + ':' +
308308
// redisConnection.options.port);
309+
const extraROCmds = require('config').get('redis.extraAllowedReadOnlyCommands');
309310
redisConnection.options.commandList = {
310311
all: p[0].value.map((item) => (item[0].toLowerCase())),
311-
ro: p[0].value.filter((item) => (item[2].indexOf('readonly') >= 0)).map((item) => (item[0].toLowerCase()))
312+
ro: p[0].value.filter((item) => (item[2].indexOf('readonly') >= 0 || extraROCmds.indexOf(item[0]) >= 0))
313+
.map((item) => (item[0].toLowerCase()))
312314
};
313315
}
314316
else {

lib/util.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,13 @@ function validateConfig() {
662662
else c.util.setPath(c, ['sso', 'jwtAlgorithms'], "");
663663
}
664664

665+
// check if extra readonly commands is a list, warn and set to empty list if not (be safe here)
666+
if (! Array.isArray(c.get('redis.extraAllowedReadOnlyCommands'))) {
667+
console.warn('Attention - config redis.extraAllowedReadOnlyCommands is not a list - ignoring value');
668+
c.util.setPath(c, ['redis', 'extraAllowedReadOnlyCommands'], []);
669+
}
670+
671+
// evaluate errors - exit if there are some critical ones...
665672
if (errCount > 0) {
666673
throw new Error(`Configuration invalid - ${errCount} errors found.`);
667674
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"Stefan Seide <[email protected]"
99
],
1010
"name": "redis-commander",
11-
"version": "0.9.0-rc3",
11+
"version": "0.9.0-rc4",
1212
"description": "Redis web-based management tool written in node.js",
1313
"license": "MIT",
1414
"repository": {

0 commit comments

Comments
 (0)