Using the Redis NoSql database with .NET Part 16: security
May 8, 2017 Leave a comment
Introduction
In the previous post we looked at how to log slow queries in Redis. We can declare the limit using the slowlog-log-slower-than flag that accepts an integer. If a query whose execution time exceeds this limit expressed in microseconds is logged to the slow log. The slow log is persisted only in memory and we can set an upper limit to the number of commands stored there. If this limit is reached then the oldest stored command is removed.
In this post we’ll see what Redis has to offer by way of security.
Security in Redis
Redis offers two types of security: passwords and obfuscation of commands. Both can be configured in the config file. If you open the Redis config file then you can search for the section called SECURITY. As usual the documentation is really good there. The “requirepass” flag accepts a password as a string. By default there’s no password authentication at all. If a password is set then the client will have to authenticate before running any command.
Obfuscation is basically renaming a command to something else. The config file shows an example:
rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
We can even disable a command by setting its name to an empty string:
rename-command CONFIG “”
That’s it really, Redis doesn’t come with the extensive security features of full blown relational databases like Oracle.
Let’s see how password based security works. Open a command prompts and run the Redis cli in it. We set a password without modifying the config file as follows:
CONFIG SET requirepass passw0rd
Next try to execute a single command:
GET “customer:1:name”
You’ll get an error:
NOAUTH Authentication required.
So let’s authenticate:
AUTH passw0rd
That’s it, we’re in.
In the Redis .NET client
Now all our previous Redis client tests will fail since we don’t provide any authentication. The following exception will be thrown:
“NOAUTH Authentication required.”
…of type ServiceStack.Redis.RedisResponseException.
When constructing a RedisClient object directly like for example here…
using (IRedisNativeClient nativeClient = new RedisClient())
…we can provide the password through the RedisEndpoint object as follows:
RedisEndpoint conf = new RedisEndpoint(); conf.Password = "passw0rd"; using (IRedisNativeClient nativeClient = new RedisClient(conf)) { nativeClient.Set(customerOneNameKey, Encoding.UTF8.GetBytes("Great Customer")); }
In the case of BasicRedisClientManager we can attach the password to the connection string as follows:
string connectionString = "passw0rd@127.0.0.1:6379"; IRedisClientsManager clientManager = new BasicRedisClientManager(connectionString);
An alternative is to declare the Redis endpoints one by one. This makes more sense in a cluster scenario with one main Redis instance called a master and several other instances connected to the master. These latter instances are called slaves. Usually the master can we written to and read from whereas the slaves are read-only. The master is set up to replicate all its data to the slaves. BasicRedisClientManager has an overload where we can declare the list of read-write endpoints and a list of read-only endpoints. Here we only have one endpoint, i.e. the localhost which is read-write. The second parameter in the following example is the list of read-only nodes but we don’t have any so it’s empty:
RedisEndpoint readWrite = new RedisEndpoint("127.0.0.1", 6379, "passw0rd"); IRedisClientsManager clientManager = new BasicRedisClientManager(new List<RedisEndpoint>() { readWrite }, new List<RedisEndpoint>());
The PooledRedisClientManager object can be set up in the same way as BasicRedisClientManager.
In the next post we’ll look at persistence in Redis.
You can view all posts related to data storage on this blog here.