|
| 1 | +Authentication |
| 2 | +=== |
| 3 | + |
| 4 | +There are multiple ways of connecting to a Redis server, depending on the authentication model. The simplest |
| 5 | +(but least secure) approach is to use the `default` user, with no authentication, and no transport security. |
| 6 | +This is as simple as: |
| 7 | + |
| 8 | +``` csharp |
| 9 | +var muxer = await ConnectionMultiplexer.ConnectAsync("myserver"); // or myserver:1241 to use a custom port |
| 10 | +``` |
| 11 | + |
| 12 | +This approach is often used for local transient servers - it is simple, but insecure. But from there, |
| 13 | +we can get more complex! |
| 14 | + |
| 15 | +TLS |
| 16 | +=== |
| 17 | + |
| 18 | +If your server has TLS enabled, SE.Redis can be instructed to use it. In some cases (AMR, etc), the |
| 19 | +library will recognize the endpoint address, meaning: *you do not need to do anything*. To |
| 20 | +*manually* enable TLS, the `ssl` token can be used: |
| 21 | + |
| 22 | +``` csharp |
| 23 | +var muxer = await ConnectionMultiplexer.ConnectAsync("myserver,ssl=true"); |
| 24 | +``` |
| 25 | + |
| 26 | +This will work fine if the server is using a server-certificate that is already trusted by the local |
| 27 | +machine. If this is *not* the case, we need to tell the library about the server. This requires |
| 28 | +the `ConfigurationOptions` type: |
| 29 | + |
| 30 | +``` csharp |
| 31 | +var options = ConfigurationOptions.Parse("myserver,ssl=true"); |
| 32 | +// or: var options = new ConfigurationOptions { Endpoints = { "myserver" }, Ssl = true }; |
| 33 | +// TODO configure |
| 34 | +var muxer = await ConnectionMultiplexer.ConnectAsync(options); |
| 35 | +``` |
| 36 | + |
| 37 | +If we have a local *issuer* public certificate (commonly `ca.crt`), we can use: |
| 38 | + |
| 39 | +``` csharp |
| 40 | +options.TrustIssuer(caPath); |
| 41 | +``` |
| 42 | + |
| 43 | +Alternatively, in advanced scenarios: to provide your own custom server validation, the `options.CertificateValidation` callback |
| 44 | +can be used; this uses the normal [`RemoteCertificateValidationCallback`](https://learn.microsoft.com/dotnet/api/system.net.security.remotecertificatevalidationcallback) |
| 45 | +API. |
| 46 | + |
| 47 | +Usernames and Passwords |
| 48 | +=== |
| 49 | + |
| 50 | +Usernames and passwords can be specified with the `user` and `password` tokens, respectively: |
| 51 | + |
| 52 | +``` csharp |
| 53 | +var muxer = await ConnectionMultiplexer.ConnectAsync("myserver,ssl=true,user=myuser,password=mypassword"); |
| 54 | +``` |
| 55 | + |
| 56 | +If no `user` is provided, the `default` user is assumed. In some cases, an authentication-token can be |
| 57 | +used in place of a classic password. |
| 58 | + |
| 59 | +Client certificates |
| 60 | +=== |
| 61 | + |
| 62 | +If the server is configured to require a client certificate, this can be supplied in multiple ways. |
| 63 | +If you have a local public / private key pair (such as `MyUser2.crt` and `MyUser2.key`), the |
| 64 | +`options.SetUserPemCertificate(...)` method can be used: |
| 65 | + |
| 66 | +``` csharp |
| 67 | +config.SetUserPemCertificate( |
| 68 | + userCertificatePath: userCrtPath, |
| 69 | + userKeyPath: userKeyPath |
| 70 | +); |
| 71 | +``` |
| 72 | + |
| 73 | +If you have a single `pfx` file that contains the public / private pair, the `options.SetUserPfxCertificate(...)` |
| 74 | +method can be used: |
| 75 | + |
| 76 | +``` csharp |
| 77 | +config.SetUserPfxCertificate( |
| 78 | + userCertificatePath: userCrtPath, |
| 79 | + password: filePassword // optional |
| 80 | +); |
| 81 | +``` |
| 82 | + |
| 83 | +Alternatively, in advanced scenarios: to provide your own custom client-certificate lookup, the `options.CertificateSelection` callback |
| 84 | +can be used; this uses the normal |
| 85 | +[`LocalCertificateSelectionCallback`](https://learn.microsoft.com/dotnet/api/system.net.security.remotecertificatevalidationcallback) |
| 86 | +API. |
| 87 | + |
| 88 | +User certificates with implicit user authentication |
| 89 | +=== |
| 90 | + |
| 91 | +Historically, the client certificate only provided access to the server, but as the `default` user. From 8.6, |
| 92 | +the server can be configured to use client certificates to provide user identity. This replaces the |
| 93 | +usage of passwords, and requires: |
| 94 | + |
| 95 | +- An 8.6+ server, configured to use TLS with client certificates mapped - typically using the `CN` of the certificate as the user. |
| 96 | +- A matching `ACL` user account configured on the server, that is enabled (`on`) - i.e. the `ACL LIST` command should |
| 97 | + display something like `user MyUser2 on sanitize-payload ~* &* +@all` (the details will vary depending on the user permissions). |
| 98 | +- At the client: access to the client certificate pair. |
| 99 | + |
| 100 | +For example: |
| 101 | + |
| 102 | +``` csharp |
| 103 | +string certRoot = // some path to a folder with ca.crt, MyUser2.crt and MyUser2.key |
| 104 | +
|
| 105 | +var options = ConfigurationOptions.Parse("myserver:6380"); |
| 106 | +options.SetUserPemCertificate(// automatically enables TLS |
| 107 | + userCertificatePath: Path.Combine(certRoot, "MyUser2.crt"), |
| 108 | + userKeyPath: Path.Combine(certRoot, "MyUser2.key")); |
| 109 | +options.TrustIssuer(Path.Combine(certRoot, "ca.crt")); |
| 110 | +await using var conn = await ConnectionMultiplexer.ConnectAsync(options); |
| 111 | + |
| 112 | +// prove we are connected as MyUser2 |
| 113 | +var user = (string?)await conn.GetDatabase().ExecuteAsync("acl", "whoami"); |
| 114 | +Console.WriteLine(user); // writes "MyUser2" |
| 115 | +``` |
| 116 | + |
| 117 | +More info |
| 118 | +=== |
| 119 | + |
| 120 | +For more information: |
| 121 | + |
| 122 | +- [Redis Security](https://redis.io/docs/latest/operate/oss_and_stack/management/security/) |
| 123 | + - [ACL](https://redis.io/docs/latest/operate/oss_and_stack/management/security/acl/) |
| 124 | + - [TLS](https://redis.io/docs/latest/operate/oss_and_stack/management/security/encryption/) |
0 commit comments