Skip to content

Commit c98c290

Browse files
committed
feat(redis): Fix channel config in users.acl
Signed-off-by: Oliver Gondža <ogondza@gmail.com>
1 parent e6b65ae commit c98c290

7 files changed

Lines changed: 100 additions & 56 deletions

File tree

controllers/argocd/deployment_test.go

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2374,16 +2374,6 @@ func repoServerDefaultVolumes() []corev1.Volume {
23742374
VolumeSource: corev1.VolumeSource{
23752375
Secret: &corev1.SecretVolumeSource{
23762376
SecretName: "argocd-redis-initial-password",
2377-
Items: []corev1.KeyToPath{
2378-
{
2379-
Key: "admin.password",
2380-
Path: "auth",
2381-
},
2382-
{
2383-
Key: "users.acl",
2384-
Path: "users.acl",
2385-
},
2386-
},
23872377
},
23882378
},
23892379
},
@@ -2487,16 +2477,6 @@ func serverDefaultVolumes() []corev1.Volume {
24872477
VolumeSource: corev1.VolumeSource{
24882478
Secret: &corev1.SecretVolumeSource{
24892479
SecretName: "argocd-redis-initial-password",
2490-
Items: []corev1.KeyToPath{
2491-
{
2492-
Key: "admin.password",
2493-
Path: "auth",
2494-
},
2495-
{
2496-
Key: "users.acl",
2497-
Path: "users.acl",
2498-
},
2499-
},
25002480
},
25012481
},
25022482
},

controllers/argocd/secret.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -746,13 +746,24 @@ func (r *ReconcileArgoCD) getClusterSecrets(cr *argoproj.ArgoCD) (*corev1.Secret
746746
// reconcileRedisInitialPasswordSecret will ensure that the redis Secret is present for the cluster.
747747
func (r *ReconcileArgoCD) reconcileRedisInitialPasswordSecret(cr *argoproj.ArgoCD) error {
748748
secret := argoutil.NewSecretWithSuffix(cr, "redis-initial-password")
749+
existed := false
749750

750-
secretExists, err := argoutil.IsObjectFound(r.Client, cr.Namespace, secret.Name, secret)
751-
if err != nil {
751+
// Recreate if the secret or some of its keys are missing
752+
err := argoutil.FetchObject(r.Client, cr.Namespace, secret.Name, secret)
753+
if err != nil && !apierrors.IsNotFound(err) {
752754
return err
753755
}
754-
if secretExists {
755-
return nil // Secret found, do nothing
756+
if secret.Data != nil {
757+
_, hasPwd := secret.Data[common.ArgoCDKeyAdminPassword]
758+
_, hasAuth := secret.Data["auth"]
759+
_, hasUsername := secret.Data["auth_username"]
760+
_, hasAcl := secret.Data["users.acl"]
761+
if hasPwd && hasAuth && hasUsername && hasAcl {
762+
return nil // Healthy - keep it
763+
}
764+
// Drop unsettable fields from FetchObject
765+
secret = argoutil.NewSecretWithSuffix(cr, "redis-initial-password")
766+
existed = true
756767
}
757768

758769
redisInitialPassword, err := generateRedisAdminPassword()
@@ -761,18 +772,26 @@ func (r *ReconcileArgoCD) reconcileRedisInitialPasswordSecret(cr *argoproj.ArgoC
761772
}
762773

763774
pw := strings.TrimRight(string(redisInitialPassword), "\n")
764-
usersACL := fmt.Sprintf(`user default on >%s ~* +@all`, pw)
775+
usersACL := fmt.Sprintf("user default on >%s allchannels allkeys allcommands\n", pw)
765776

766777
secret.Data = map[string][]byte{
767-
"immutable": []byte("true"),
778+
"immutable": []byte("true"),
779+
// Mapping the legacy key-name, the operator customers can depend on.
768780
common.ArgoCDKeyAdminPassword: redisInitialPassword,
769781
// Provide ACL file content so redis-server can use file-based ACLs
770-
"users.acl": []byte(usersACL),
782+
"auth": redisInitialPassword,
783+
"auth_username": []byte("default"),
784+
"users.acl": []byte(usersACL),
771785
}
772786

773787
if err := controllerutil.SetControllerReference(cr, secret, r.Scheme); err != nil {
774788
return err
775789
}
790+
791+
if existed {
792+
argoutil.LogResourceUpdate(log, secret)
793+
return r.Update(context.TODO(), secret)
794+
}
776795
argoutil.LogResourceCreation(log, secret)
777796
return r.Create(context.TODO(), secret)
778797
}

controllers/argocd/secret_test.go

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import (
1010
"testing"
1111

1212
argopass "github.com/argoproj/argo-cd/v3/util/password"
13-
1413
configv1 "github.com/openshift/api/config/v1"
1514
routev1 "github.com/openshift/api/route/v1"
1615
"github.com/stretchr/testify/assert"
16+
"github.com/stretchr/testify/require"
1717

1818
corev1 "k8s.io/api/core/v1"
1919
testclient "k8s.io/client-go/kubernetes/fake"
@@ -362,6 +362,77 @@ func Test_ReconcileArgoCD_ReconcileShouldNotChangeWhenUpdatedAdminPass(t *testin
362362
assert.True(t, argoutil.IsTrackedByOperator(testSecret.Labels))
363363
}
364364

365+
func Test_ReconcileArgoCD_ReconcileRedisInitialPasswordSecret(t *testing.T) {
366+
const suffix = "redis-initial-password"
367+
argocd := &argoproj.ArgoCD{
368+
ObjectMeta: metav1.ObjectMeta{
369+
Name: "argocd",
370+
Namespace: "argocd-operator",
371+
},
372+
}
373+
secretName := argoutil.NewSecretWithSuffix(argocd, suffix).Name
374+
secretNN := types.NamespacedName{Name: secretName, Namespace: "argocd-operator"}
375+
376+
resObjs := []client.Object{argocd}
377+
subresObjs := []client.Object{argocd}
378+
runtimeObjs := []runtime.Object{}
379+
sch := makeTestReconcilerScheme(argoproj.AddToScheme)
380+
cl := makeTestReconcilerClient(sch, resObjs, subresObjs, runtimeObjs)
381+
r := makeTestReconciler(cl, sch, testclient.NewSimpleClientset())
382+
383+
var actual corev1.Secret
384+
fetchSecret := func() error {
385+
return r.Get(t.Context(), secretNN, &actual)
386+
}
387+
assertSecretValid := func() string {
388+
assert.Equal(t, "true", string(actual.Data["immutable"]))
389+
assert.Equal(t, "default", string(actual.Data["auth_username"]))
390+
assert.Contains(t, string(actual.Data["users.acl"]), "user default on >")
391+
assert.Contains(t, string(actual.Data["users.acl"]), " allchannels allkeys allcommands")
392+
actualPwd := string(actual.Data["auth"])
393+
assert.NotEqual(t, "", actualPwd)
394+
assert.Contains(t, string(actual.Data["users.acl"]), actualPwd, "Password is mentioned in the ACL file")
395+
return actualPwd
396+
}
397+
398+
t.Run("Create when does not exist", func(t *testing.T) {
399+
require.ErrorContains(t, fetchSecret(), fmt.Sprintf(`secrets "%s" not found`, secretName))
400+
401+
require.NoError(t, r.reconcileRedisInitialPasswordSecret(argocd))
402+
403+
require.NoError(t, fetchSecret())
404+
assertSecretValid()
405+
})
406+
407+
t.Run("Update keys and regenerate on operator upgrade", func(t *testing.T) {
408+
const oldPwd = "asdfghjkl"
409+
secret := argoutil.NewSecretWithSuffix(argocd, suffix)
410+
secret.Data = map[string][]byte{
411+
"immutable": []byte("true"),
412+
common.ArgoCDKeyAdminPassword: []byte(oldPwd),
413+
}
414+
require.NoError(t, r.Update(t.Context(), secret))
415+
416+
require.NoError(t, r.reconcileRedisInitialPasswordSecret(argocd))
417+
418+
require.NoError(t, fetchSecret())
419+
actualPwd := assertSecretValid()
420+
assert.NotEqual(t, oldPwd, actualPwd)
421+
})
422+
423+
t.Run("Keep untouched if healthy", func(t *testing.T) {
424+
require.NoError(t, fetchSecret())
425+
assertSecretValid()
426+
oldVersion := actual.ResourceVersion
427+
428+
require.NoError(t, r.reconcileRedisInitialPasswordSecret(argocd))
429+
430+
require.NoError(t, fetchSecret())
431+
assertSecretValid()
432+
assert.Equal(t, oldVersion, actual.ResourceVersion, "Resource version should not change")
433+
})
434+
}
435+
365436
func Test_ReconcileArgoCD_ReconcileRedisTLSSecret(t *testing.T) {
366437
argocd := &argoproj.ArgoCD{
367438
ObjectMeta: metav1.ObjectMeta{

controllers/argocd/statefulset_test.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,6 @@ func controllerDefaultVolumes() []corev1.Volume {
9292
VolumeSource: corev1.VolumeSource{
9393
Secret: &corev1.SecretVolumeSource{
9494
SecretName: "argocd-redis-initial-password",
95-
Items: []corev1.KeyToPath{
96-
{
97-
Key: "admin.password",
98-
Path: "auth",
99-
},
100-
{
101-
Key: "users.acl",
102-
Path: "users.acl",
103-
},
104-
},
10595
},
10696
},
10797
},

controllers/argocdagent/deployment_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -434,11 +434,7 @@ func TestReconcilePrincipalDeployment_VerifyDeploymentSpec(t *testing.T) {
434434
assert.NotNil(t, redisAuthVolume.Secret)
435435
assert.Equal(t, "argocd-redis-initial-password", redisAuthVolume.Secret.SecretName)
436436
assert.NotEqual(t, ptr.To(true), redisAuthVolume.Secret.Optional)
437-
assert.Len(t, redisAuthVolume.Secret.Items, 2)
438-
assert.Equal(t, "admin.password", redisAuthVolume.VolumeSource.Secret.Items[0].Key)
439-
assert.Equal(t, "auth", redisAuthVolume.VolumeSource.Secret.Items[0].Path)
440-
assert.Equal(t, "users.acl", redisAuthVolume.VolumeSource.Secret.Items[1].Key)
441-
assert.Equal(t, "users.acl", redisAuthVolume.VolumeSource.Secret.Items[1].Path)
437+
assert.Len(t, redisAuthVolume.Secret.Items, 0)
442438
}
443439

444440
func TestReconcilePrincipalDeployment_CustomImage(t *testing.T) {

controllers/argoutil/redis.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,6 @@ func MountRedisAuthToArgo(cr *argoproj.ArgoCD) (volume corev1.Volume, mount core
2424
VolumeSource: corev1.VolumeSource{
2525
Secret: &corev1.SecretVolumeSource{
2626
SecretName: GetSecretNameWithSuffix(cr, "redis-initial-password"),
27-
Items: []corev1.KeyToPath{
28-
{
29-
// Mapping the legacy key-name, the operator customers can depend on, to the expected file name for argo-cd
30-
// Ref.: https://argo-cd.readthedocs.io/en/latest/faq/#using-file-based-redis-credentials-via-redis_creds_dir_path
31-
Key: "admin.password",
32-
Path: "auth",
33-
},
34-
{
35-
// ACL file used by redis-server
36-
Key: "users.acl",
37-
Path: "users.acl",
38-
},
39-
},
4027
},
4128
},
4229
}

tests/ginkgo/sequential/1-053_validate_argocd_agent_principal_connected_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ var _ = Describe("GitOps Operator Sequential E2E Tests", func() {
370370
Eventually(func() bool {
371371
for {
372372
// drain channel looking for name of new pod
373+
GinkgoWriter.Println("Awaiting message")
373374
select {
374375
case msg := <-msgChan:
375376
GinkgoWriter.Println("Processing message:", msg)

0 commit comments

Comments
 (0)