diff --git a/README.md b/README.md
index 32e6fa48..818643d5 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,16 @@ class { 'redis':
}
```
+With ACL authentication
+
+```puppet
+class { 'redis':
+ bind => '10.0.1.1',
+ masterauth => 'secret',
+ masteruser => 'username',
+}
+```
+
### Slave node
```puppet
diff --git a/REFERENCE.md b/REFERENCE.md
index c2b5a708..416fefb1 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -122,6 +122,7 @@ The following parameters are available in the `redis` class:
* [`manage_package`](#-redis--manage_package)
* [`managed_by_cluster_manager`](#-redis--managed_by_cluster_manager)
* [`masterauth`](#-redis--masterauth)
+* [`masteruser`](#-redis--masteruser)
* [`maxclients`](#-redis--maxclients)
* [`maxmemory`](#-redis--maxmemory)
* [`maxmemory_policy`](#-redis--maxmemory_policy)
@@ -532,7 +533,15 @@ Default value: `false`
Data type: `Optional[Variant[String[1], Sensitive[String[1]], Deferred]]`
-If the master is password protected (using the "requirepass" configuration
+If the master is password protected (using the "requirepass" configuration)
+
+Default value: `undef`
+
+##### `masteruser`
+
+Data type: `Optional[Variant[String[1], Sensitive[String[1]], Deferred]]`
+
+If the master is password protected and a user is defined (using the "user" configuration)
Default value: `undef`
@@ -1953,6 +1962,7 @@ The following parameters are available in the `redis::instance` defined type:
* [`managed_by_cluster_manager`](#-redis--instance--managed_by_cluster_manager)
* [`manage_service_file`](#-redis--instance--manage_service_file)
* [`masterauth`](#-redis--instance--masterauth)
+* [`masteruser`](#-redis--instance--masteruser)
* [`maxclients`](#-redis--instance--maxclients)
* [`maxmemory`](#-redis--instance--maxmemory)
* [`maxmemory_policy`](#-redis--instance--maxmemory_policy)
@@ -2305,7 +2315,15 @@ Default value: `true`
Data type: `Optional[Variant[String[1], Sensitive[String[1]], Deferred]]`
-If the master is password protected (using the "requirepass" configuration
+If the master is password protected (using the "requirepass" configuration)
+
+Default value: `$redis::masterauth`
+
+##### `masteruser`
+
+Data type: `Optional[Variant[String[1], Sensitive[String[1]], Deferred]]`
+
+If the master is password protected and a user is defined (using the "user" configuration)
Default value: `$redis::masterauth`
diff --git a/manifests/init.pp b/manifests/init.pp
index e48ed67c..f19f8d79 100644
--- a/manifests/init.pp
+++ b/manifests/init.pp
@@ -95,7 +95,9 @@
# @param managed_by_cluster_manager
# Choose if redis will be managed by a cluster manager such as pacemaker or rgmanager
# @param masterauth
-# If the master is password protected (using the "requirepass" configuration
+# If the master is password protected (using the "requirepass" configuration)
+# @param masteruser
+# If the master is password protected and a user is defined (using the "user" configuration)
# @param maxclients
# Set the max number of connected clients at the same time.
# @param maxmemory
@@ -392,6 +394,7 @@
Boolean $manage_package = true,
Boolean $manage_repo = false,
Optional[Variant[String[1], Sensitive[String[1]], Deferred]] $masterauth = undef,
+ Optional[Variant[String[1], Sensitive[String[1]], Deferred]] $masteruser = undef,
Integer[1] $maxclients = 10000,
$maxmemory = undef,
Optional[Redis::MemoryPolicy] $maxmemory_policy = undef,
diff --git a/manifests/instance.pp b/manifests/instance.pp
index 3b18cfca..b8256b87 100644
--- a/manifests/instance.pp
+++ b/manifests/instance.pp
@@ -74,7 +74,9 @@
# @param manage_service_file
# Determine if the systemd service file should be managed
# @param masterauth
-# If the master is password protected (using the "requirepass" configuration
+# If the master is password protected (using the "requirepass" configuration)
+# @param masteruser
+# If the master is password protected and a user is defined (using the "user" configuration)
# @param maxclients
# Set the max number of connected clients at the same time.
# @param maxmemory
@@ -325,6 +327,7 @@
Stdlib::Filemode $log_dir_mode = $redis::log_dir_mode,
Redis::LogLevel $log_level = $redis::log_level,
Optional[Variant[String[1], Sensitive[String[1]], Deferred]] $masterauth = $redis::masterauth,
+ Optional[Variant[String[1], Sensitive[String[1]], Deferred]] $masteruser = $redis::masterauth,
Integer[1] $maxclients = $redis::maxclients,
Optional[Variant[Integer, String]] $maxmemory = $redis::maxmemory,
Optional[Redis::MemoryPolicy] $maxmemory_policy = $redis::maxmemory_policy,
@@ -526,6 +529,7 @@
slaveof => $slaveof,
replicaof => $replicaof,
masterauth => $masterauth,
+ masteruser => $masteruser,
slave_serve_stale_data => $slave_serve_stale_data,
slave_read_only => $slave_read_only,
repl_announce_ip => $repl_announce_ip,
diff --git a/manifests/sentinel.pp b/manifests/sentinel.pp
index 2813802b..ea956e3b 100644
--- a/manifests/sentinel.pp
+++ b/manifests/sentinel.pp
@@ -3,6 +3,9 @@
# @param auth_pass
# The password to use to authenticate with the master and slaves.
#
+# @param auth_user
+# The username to use to authenticate with the master and slaves.
+#
# @param config_file
# The location and name of the sentinel config file.
#
@@ -147,6 +150,7 @@
#
class redis::sentinel (
Optional[Variant[String[1], Sensitive[String[1]]]] $auth_pass = undef,
+ Optional[Variant[String[1], Sensitive[String[1]]]] $auth_user = undef,
Stdlib::Absolutepath $config_file = $redis::params::sentinel_config_file,
Stdlib::Absolutepath $config_file_orig = $redis::params::sentinel_config_file_orig,
Stdlib::Filemode $config_file_mode = '0644',
@@ -193,6 +197,11 @@
} else {
$auth_pass
}
+ $auth_user_unsensitive = if $auth_user =~ Sensitive {
+ $auth_user.unwrap
+ } else {
+ $auth_user
+ }
contain 'redis'
diff --git a/spec/classes/redis_sentinel_spec.rb b/spec/classes/redis_sentinel_spec.rb
index 945d8561..9b450024 100644
--- a/spec/classes/redis_sentinel_spec.rb
+++ b/spec/classes/redis_sentinel_spec.rb
@@ -110,6 +110,7 @@ class { 'redis':
{
sentinel_tls_port: 26_380,
auth_pass: 'password',
+ auth_user: 'username',
sentinel_bind: '192.0.2.10',
protected_mode: false,
master_name: 'cow',
@@ -151,6 +152,7 @@ class { 'redis':
sentinel parallel-syncs cow 1
sentinel failover-timeout cow 28000
sentinel auth-pass cow password
+ sentinel auth-user cow username
sentinel notification-script cow /path/to/bar.sh
sentinel client-reconfig-script cow /path/to/foo.sh
@@ -177,6 +179,7 @@ class { 'redis':
let(:params) do
{
auth_pass: 'password',
+ auth_user: 'username',
sentinel_bind: ['192.0.2.10', '192.168.1.1'],
master_name: 'cow',
down_after: 6000,
@@ -203,6 +206,7 @@ class { 'redis':
sentinel parallel-syncs cow 1
sentinel failover-timeout cow 28000
sentinel auth-pass cow password
+ sentinel auth-user cow username
sentinel notification-script cow /path/to/bar.sh
sentinel client-reconfig-script cow /path/to/foo.sh
diff --git a/spec/classes/redis_spec.rb b/spec/classes/redis_spec.rb
index b0cae74a..674a2cdb 100644
--- a/spec/classes/redis_spec.rb
+++ b/spec/classes/redis_spec.rb
@@ -523,6 +523,27 @@ class { 'redis':
}
end
+ describe 'with parameter masteruser ACL' do
+ let(:params) do
+ {
+ masterauth: '_PASSWORD_VALUE_',
+ masteruser: '_USERNAME_VALUE_'
+ }
+ end
+
+ it {
+ is_expected.to contain_file(config_file_orig).with(
+ 'content' => %r{masterauth.*_PASSWORD_VALUE_}
+ )
+ }
+
+ it {
+ is_expected.to contain_file(config_file_orig).with(
+ 'content' => %r{masteruser.*_USERNAME_VALUE_}
+ )
+ }
+ end
+
describe 'with parameter maxclients' do
let(:params) do
{
diff --git a/templates/redis-sentinel.conf.erb b/templates/redis-sentinel.conf.erb
index 283743c1..ed6c9a20 100644
--- a/templates/redis-sentinel.conf.erb
+++ b/templates/redis-sentinel.conf.erb
@@ -27,6 +27,9 @@ sentinel failover-timeout <%= @master_name %> <%= @failover_timeout %>
<% if @auth_pass_unsensitive -%>
sentinel auth-pass <%= @master_name %> <%= @auth_pass_unsensitive %>
<% end -%>
+<% if @auth_user_unsensitive -%>
+sentinel auth-user <%= @master_name %> <%= @auth_user_unsensitive %>
+<% end -%>
<% if @notification_script -%>
sentinel notification-script <%= @master_name %> <%= @notification_script %>
<% end -%>
diff --git a/templates/redis.conf.epp b/templates/redis.conf.epp
index a14f7060..578ca914 100644
--- a/templates/redis.conf.epp
+++ b/templates/redis.conf.epp
@@ -23,6 +23,7 @@
Optional[String[1]] $slaveof,
Optional[String[1]] $replicaof,
Optional[Variant[String[1], Sensitive[String[1]]]] $masterauth,
+ Optional[Variant[String[1], Sensitive[String[1]]]] $masteruser,
Boolean $slave_serve_stale_data,
Boolean $slave_read_only,
Optional[Stdlib::Host] $repl_announce_ip,
@@ -411,6 +412,18 @@ dir <%= $workdir %>
# masterauth
<% if $masterauth { -%>masterauth <%= $masterauth %><% } -%>
+# However this is not enough if you are using Redis ACLs (for Redis version
+# 6 or greater), and the default user is not capable of running the PSYNC
+# command and/or other commands needed for replication. In this case it's
+# better to configure a special user to use with replication, and specify the
+# username configuration as such:
+#
+# masteruser
+<% if $masteruser { -%>masteruser <%= $masteruser %><% } -%>
+
+# When masteruser is specified, the replica will authenticate against its
+# master using the new AUTH form: AUTH .
+
# When a slave loses the connection with the master, or when the replication
# is still in progress, the slave can act in two different ways:
#