Skip to content

Commit 58f831d

Browse files
committed
feature: create secret for agent password
1 parent f806910 commit 58f831d

23 files changed

+551
-40
lines changed

.evergreen-tasks.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,11 @@ tasks:
585585
commands:
586586
- func: "e2e_test"
587587

588+
- name: e2e_sharded_cluster_scram_sha_256_switch_project
589+
tags: [ "patch-run" ]
590+
commands:
591+
- func: "e2e_test"
592+
588593
- name: e2e_sharded_cluster_scram_sha_1_user_connectivity
589594
tags: [ "patch-run" ]
590595
commands:

.evergreen.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,7 @@ task_groups:
710710
- e2e_replica_set_scram_x509_ic_manual_certs
711711
- e2e_sharded_cluster_scram_sha_1_upgrade
712712
- e2e_sharded_cluster_scram_sha_256_user_connectivity
713+
- e2e_sharded_cluster_scram_sha_256_switch_project
713714
- e2e_sharded_cluster_scram_sha_1_user_connectivity
714715
- e2e_sharded_cluster_scram_x509_ic_manual_certs
715716
- e2e_sharded_cluster_external_access

controllers/om/automation_config.go

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
package om
22

33
import (
4+
"context"
45
"encoding/json"
6+
"fmt"
57

68
"github.com/google/go-cmp/cmp"
79
"github.com/spf13/cast"
810
"k8s.io/apimachinery/pkg/api/equality"
11+
"k8s.io/apimachinery/pkg/types"
12+
"sigs.k8s.io/controller-runtime/pkg/client"
913

1014
"github.com/mongodb/mongodb-kubernetes/controllers/operator/ldap"
1115
"github.com/mongodb/mongodb-kubernetes/controllers/operator/oidc"
16+
"github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/pkg/kube/secret"
1217
"github.com/mongodb/mongodb-kubernetes/pkg/util"
1318
"github.com/mongodb/mongodb-kubernetes/pkg/util/generate"
1419
"github.com/mongodb/mongodb-kubernetes/pkg/util/maputil"
1520
)
1621

22+
// The constants for the authentication secret
23+
const agentAuthenticationSecretSuffix = "-agent-auth-secret"
24+
const autoPwdSecretKey = "automation-agent-password"
25+
1726
// AutomationConfig maintains the raw map in the Deployment field
1827
// and constructs structs to make use of go's type safety
1928
// Dev notes: actually, this object is just a wrapper for the `Deployment` object which is received from Ops Manager,
@@ -429,16 +438,63 @@ func (ac *AutomationConfig) EnsureKeyFileContents() error {
429438
// EnsurePassword makes sure that there is an Automation Agent password
430439
// that the agents will use to communicate with the deployments. The password
431440
// is returned, so it can be provided to the other agents
432-
func (ac *AutomationConfig) EnsurePassword() (string, error) {
433-
if ac.Auth.AutoPwd == "" || ac.Auth.AutoPwd == util.InvalidAutomationAgentPassword {
434-
automationAgentBackupPassword, err := generate.KeyFileContents()
441+
// EnsurePassword makes sure that there is an Automation Agent password
442+
// that the agents will use to communicate with the deployments. The password
443+
// is returned, so it can be provided to the other agents.
444+
func (ac *AutomationConfig) EnsurePassword(k8sClient secret.GetUpdateCreator, ctx context.Context, mdbNamespacedName *types.NamespacedName) (string, error) {
445+
secretNamespacedName := client.ObjectKey{Name: mdbNamespacedName.Name + agentAuthenticationSecretSuffix, Namespace: mdbNamespacedName.Namespace}
446+
447+
var password string
448+
449+
data, err := secret.ReadStringData(ctx, k8sClient, secretNamespacedName)
450+
if err == nil {
451+
if val, ok := data[autoPwdSecretKey]; ok && len(val) > 0 {
452+
password = val
453+
}
454+
} else if secret.SecretNotExist(err) {
455+
if ac.Auth.AutoPwd != "" && ac.Auth.AutoPwd != util.InvalidAutomationAgentPassword {
456+
password = ac.Auth.AutoPwd
457+
}
458+
459+
err := EnsureEmptySecret(ctx, k8sClient, secretNamespacedName)
435460
if err != nil {
436461
return "", err
437462
}
438-
ac.Auth.AutoPwd = automationAgentBackupPassword
439-
return automationAgentBackupPassword, nil
440463
}
441-
return ac.Auth.AutoPwd, nil
464+
465+
if password == "" {
466+
generatedPassword, genErr := generate.KeyFileContents()
467+
if genErr != nil {
468+
return "", genErr
469+
}
470+
password = generatedPassword
471+
}
472+
473+
ac.Auth.AutoPwd = password
474+
err = secret.UpdateField(ctx, k8sClient, secretNamespacedName, autoPwdSecretKey, password)
475+
if err != nil {
476+
return "", fmt.Errorf("failed to update password field in shared secret %s/%s: %w", secretNamespacedName.Namespace, secretNamespacedName.Name, err)
477+
}
478+
479+
return password, nil
480+
}
481+
482+
func EnsureEmptySecret(ctx context.Context, k8sClient secret.GetUpdateCreator, secretNamespacedName types.NamespacedName) error {
483+
dataFields := map[string]string{
484+
autoPwdSecretKey: "",
485+
}
486+
487+
emptySecret := secret.Builder().
488+
SetName(secretNamespacedName.Name).
489+
SetNamespace(secretNamespacedName.Namespace).
490+
SetStringMapToData(dataFields).
491+
Build()
492+
493+
if err := secret.CreateOrUpdateIfNeeded(ctx, k8sClient, emptySecret); err != nil {
494+
return fmt.Errorf("failed to create or update empty secret %s/%s: %w", secretNamespacedName.Namespace, secretNamespacedName.Name, err)
495+
}
496+
497+
return nil
442498
}
443499

444500
func (ac *AutomationConfig) CanEnableX509ProjectAuthentication() (bool, string) {

controllers/operator/appdbreplicaset_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1667,7 +1667,7 @@ func (r *ReconcileAppDbReplicaSet) tryConfigureMonitoringInOpsManager(ctx contex
16671667
AutoPEMKeyFilePath: agentCertPath,
16681668
CAFilePath: util.CAFilePathInContainer,
16691669
}
1670-
err = authentication.Configure(conn, opts, false, log)
1670+
err = authentication.Configure(r.client, ctx, &types.NamespacedName{Namespace: opsManager.Namespace, Name: opsManager.Name}, conn, opts, false, log)
16711671
if err != nil {
16721672
log.Errorf("Could not set Automation Authentication options in Ops/Cloud Manager for the Application Database. "+
16731673
"Application Database is always configured with authentication enabled, but this will not be "+

controllers/operator/authentication/authentication.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
package authentication
22

33
import (
4+
"context"
5+
46
"go.uber.org/zap"
57
"golang.org/x/xerrors"
8+
"k8s.io/apimachinery/pkg/types"
69

710
mdbv1 "github.com/mongodb/mongodb-kubernetes/api/v1/mdb"
811
"github.com/mongodb/mongodb-kubernetes/controllers/om"
912
"github.com/mongodb/mongodb-kubernetes/controllers/operator/ldap"
1013
"github.com/mongodb/mongodb-kubernetes/controllers/operator/oidc"
14+
kubernetesClient "github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/pkg/kube/client"
1115
"github.com/mongodb/mongodb-kubernetes/pkg/util"
1216
)
1317

@@ -82,7 +86,7 @@ type UserOptions struct {
8286

8387
// Configure will configure all the specified authentication Mechanisms. We need to ensure we wait for
8488
// the agents to reach ready state after each operation as prematurely updating the automation config can cause the agents to get stuck.
85-
func Configure(conn om.Connection, opts Options, isRecovering bool, log *zap.SugaredLogger) error {
89+
func Configure(client kubernetesClient.Client, ctx context.Context, mdbNamespacedName *types.NamespacedName, conn om.Connection, opts Options, isRecovering bool, log *zap.SugaredLogger) error {
8690
log.Infow("ensuring correct deployment mechanisms", "ProcessNames", opts.ProcessNames, "Mechanisms", opts.Mechanisms)
8791

8892
// In case we're recovering, we can push all changes at once, because the mechanism is triggered after 20min by default.
@@ -113,7 +117,7 @@ func Configure(conn om.Connection, opts Options, isRecovering bool, log *zap.Sug
113117

114118
// once we have made sure that the deployment authentication mechanism array contains the desired auth mechanism
115119
// we can then configure the agent authentication.
116-
if err := enableAgentAuthentication(conn, opts, log); err != nil {
120+
if err := enableAgentAuthentication(client, ctx, mdbNamespacedName, conn, opts, log); err != nil {
117121
return xerrors.Errorf("error enabling agent authentication: %w", err)
118122
}
119123
if err := waitForReadyStateIfNeeded(); err != nil {
@@ -151,7 +155,7 @@ func Configure(conn om.Connection, opts Options, isRecovering bool, log *zap.Sug
151155

152156
// Disable disables all authentication mechanisms, and waits for the agents to reach goal state. It is still required to provide
153157
// automation agent username, password and keyfile contents to ensure a valid Automation Config.
154-
func Disable(conn om.Connection, opts Options, deleteUsers bool, log *zap.SugaredLogger) error {
158+
func Disable(client kubernetesClient.Client, ctx context.Context, mdbNamespacedName *types.NamespacedName, conn om.Connection, opts Options, deleteUsers bool, log *zap.SugaredLogger) error {
155159
ac, err := conn.ReadAutomationConfig()
156160
if err != nil {
157161
return xerrors.Errorf("error reading automation config: %w", err)
@@ -181,7 +185,7 @@ func Disable(conn om.Connection, opts Options, deleteUsers bool, log *zap.Sugare
181185
if err := ac.EnsureKeyFileContents(); err != nil {
182186
return xerrors.Errorf("error ensuring keyfile contents: %w", err)
183187
}
184-
if _, err := ac.EnsurePassword(); err != nil {
188+
if _, err := ac.EnsurePassword(client, ctx, mdbNamespacedName); err != nil {
185189
return xerrors.Errorf("error ensuring agent password: %w", err)
186190
}
187191

@@ -258,7 +262,7 @@ func removeUnsupportedAgentMechanisms(conn om.Connection, opts Options, log *zap
258262

259263
// enableAgentAuthentication determines which agent authentication mechanism should be configured
260264
// and enables it in Ops Manager
261-
func enableAgentAuthentication(conn om.Connection, opts Options, log *zap.SugaredLogger) error {
265+
func enableAgentAuthentication(client kubernetesClient.Client, ctx context.Context, mdbNamespacedName *types.NamespacedName, conn om.Connection, opts Options, log *zap.SugaredLogger) error {
262266
ac, err := conn.ReadAutomationConfig()
263267
if err != nil {
264268
return xerrors.Errorf("error reading automation config: %w", err)
@@ -267,7 +271,7 @@ func enableAgentAuthentication(conn om.Connection, opts Options, log *zap.Sugare
267271
// we then configure the agent authentication for that type
268272
mechanism := convertToMechanismOrPanic(opts.AgentMechanism, ac)
269273

270-
if err := ensureAgentAuthenticationIsConfigured(conn, opts, ac, mechanism, log); err != nil {
274+
if err := ensureAgentAuthenticationIsConfigured(client, ctx, mdbNamespacedName, conn, opts, ac, mechanism, log); err != nil {
271275
return xerrors.Errorf("error ensuring agent authentication is configured: %w", err)
272276
}
273277

@@ -365,14 +369,14 @@ func addOrRemoveAgentClientCertificate(conn om.Connection, opts Options, log *za
365369
}
366370

367371
// ensureAgentAuthenticationIsConfigured will configure the agent authentication settings based on the desiredAgentAuthMechanism
368-
func ensureAgentAuthenticationIsConfigured(conn om.Connection, opts Options, ac *om.AutomationConfig, mechanism Mechanism, log *zap.SugaredLogger) error {
372+
func ensureAgentAuthenticationIsConfigured(client kubernetesClient.Client, ctx context.Context, mdbNamespacedName *types.NamespacedName, conn om.Connection, opts Options, ac *om.AutomationConfig, mechanism Mechanism, log *zap.SugaredLogger) error {
369373
if mechanism.IsAgentAuthenticationConfigured(ac, opts) {
370374
log.Infof("Agent authentication mechanism %s is already configured", mechanism.GetName())
371375
return nil
372376
}
373377

374378
log.Infof("Enabling %s agent authentication", mechanism.GetName())
375-
return mechanism.EnableAgentAuthentication(conn, opts, log)
379+
return mechanism.EnableAgentAuthentication(client, ctx, mdbNamespacedName, conn, opts, log)
376380
}
377381

378382
// ensureDeploymentMechanisms configures the given AutomationConfig to allow deployments to

controllers/operator/authentication/authentication_mechanism.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
package authentication
22

33
import (
4+
"context"
45
"slices"
56
"strings"
67

78
"go.uber.org/zap"
89
"golang.org/x/xerrors"
10+
"k8s.io/apimachinery/pkg/types"
911

1012
"github.com/mongodb/mongodb-kubernetes/controllers/om"
13+
kubernetesClient "github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/pkg/kube/client"
1114
"github.com/mongodb/mongodb-kubernetes/pkg/util"
1215
)
1316

1417
// Mechanism is an interface that needs to be implemented for any Ops Manager authentication mechanism
1518
type Mechanism interface {
16-
EnableAgentAuthentication(conn om.Connection, opts Options, log *zap.SugaredLogger) error
19+
EnableAgentAuthentication(client kubernetesClient.Client, ctx context.Context, mdbNamespacedName *types.NamespacedName, conn om.Connection, opts Options, log *zap.SugaredLogger) error
1720
DisableAgentAuthentication(conn om.Connection, log *zap.SugaredLogger) error
1821
EnableDeploymentAuthentication(conn om.Connection, opts Options, log *zap.SugaredLogger) error
1922
DisableDeploymentAuthentication(conn om.Connection, log *zap.SugaredLogger) error

controllers/operator/authentication/configure_authentication_test.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package authentication
22

33
import (
4+
"context"
45
"testing"
56

67
"github.com/stretchr/testify/assert"
78
"github.com/stretchr/testify/require"
89
"go.uber.org/zap"
10+
"k8s.io/apimachinery/pkg/types"
911

1012
"github.com/mongodb/mongodb-kubernetes/controllers/om"
13+
"github.com/mongodb/mongodb-kubernetes/controllers/operator/mock"
1114
"github.com/mongodb/mongodb-kubernetes/pkg/util"
1215
)
1316

@@ -17,6 +20,10 @@ func init() {
1720
}
1821

1922
func TestConfigureScramSha256(t *testing.T) {
23+
ctx := context.Background()
24+
kubeClient, _ := mock.NewDefaultFakeClient()
25+
mdbNamespacedName := &types.NamespacedName{Namespace: "test", Name: "test"}
26+
2027
dep := om.NewDeployment()
2128
conn := om.NewMockedOmConnection(dep)
2229

@@ -27,7 +34,7 @@ func TestConfigureScramSha256(t *testing.T) {
2734
AgentMechanism: "SCRAM",
2835
}
2936

30-
if err := Configure(conn, opts, false, zap.S()); err != nil {
37+
if err := Configure(kubeClient, ctx, mdbNamespacedName, conn, opts, false, zap.S()); err != nil {
3138
t.Fatal(err)
3239
}
3340

@@ -41,6 +48,10 @@ func TestConfigureScramSha256(t *testing.T) {
4148
}
4249

4350
func TestConfigureX509(t *testing.T) {
51+
ctx := context.Background()
52+
kubeClient, _ := mock.NewDefaultFakeClient()
53+
mdbNamespacedName := &types.NamespacedName{Namespace: "test", Name: "test"}
54+
4455
dep := om.NewDeployment()
4556
conn := om.NewMockedOmConnection(dep)
4657

@@ -55,7 +66,7 @@ func TestConfigureX509(t *testing.T) {
5566
},
5667
}
5768

58-
if err := Configure(conn, opts, false, zap.S()); err != nil {
69+
if err := Configure(kubeClient, ctx, mdbNamespacedName, conn, opts, false, zap.S()); err != nil {
5970
t.Fatal(err)
6071
}
6172

@@ -69,6 +80,10 @@ func TestConfigureX509(t *testing.T) {
6980
}
7081

7182
func TestConfigureScramSha1(t *testing.T) {
83+
ctx := context.Background()
84+
kubeClient, _ := mock.NewDefaultFakeClient()
85+
mdbNamespacedName := &types.NamespacedName{Namespace: "test", Name: "test"}
86+
7287
dep := om.NewDeployment()
7388
conn := om.NewMockedOmConnection(dep)
7489

@@ -79,7 +94,7 @@ func TestConfigureScramSha1(t *testing.T) {
7994
AgentMechanism: "SCRAM-SHA-1",
8095
}
8196

82-
if err := Configure(conn, opts, false, zap.S()); err != nil {
97+
if err := Configure(kubeClient, ctx, mdbNamespacedName, conn, opts, false, zap.S()); err != nil {
8398
t.Fatal(err)
8499
}
85100

@@ -91,6 +106,10 @@ func TestConfigureScramSha1(t *testing.T) {
91106
}
92107

93108
func TestConfigureMultipleAuthenticationMechanisms(t *testing.T) {
109+
ctx := context.Background()
110+
kubeClient, _ := mock.NewDefaultFakeClient()
111+
mdbNamespacedName := &types.NamespacedName{Namespace: "test", Name: "test"}
112+
94113
dep := om.NewDeployment()
95114
conn := om.NewMockedOmConnection(dep)
96115

@@ -104,7 +123,7 @@ func TestConfigureMultipleAuthenticationMechanisms(t *testing.T) {
104123
},
105124
}
106125

107-
if err := Configure(conn, opts, false, zap.S()); err != nil {
126+
if err := Configure(kubeClient, ctx, mdbNamespacedName, conn, opts, false, zap.S()); err != nil {
108127
t.Fatal(err)
109128
}
110129

@@ -124,6 +143,10 @@ func TestConfigureMultipleAuthenticationMechanisms(t *testing.T) {
124143
}
125144

126145
func TestDisableAuthentication(t *testing.T) {
146+
ctx := context.Background()
147+
kubeClient, _ := mock.NewDefaultFakeClient()
148+
mdbNamespacedName := &types.NamespacedName{Namespace: "test", Name: "test"}
149+
127150
dep := om.NewDeployment()
128151
conn := om.NewMockedOmConnection(dep)
129152

@@ -133,7 +156,7 @@ func TestDisableAuthentication(t *testing.T) {
133156
return nil
134157
}, zap.S())
135158

136-
if err := Disable(conn, Options{}, true, zap.S()); err != nil {
159+
if err := Disable(kubeClient, ctx, mdbNamespacedName, conn, Options{}, true, zap.S()); err != nil {
137160
t.Fatal(err)
138161
}
139162

@@ -212,7 +235,11 @@ func assertDeploymentMechanismsConfigured(t *testing.T, authMechanism Mechanism,
212235
}
213236

214237
func assertAgentAuthenticationDisabled(t *testing.T, authMechanism Mechanism, conn om.Connection, opts Options) {
215-
err := authMechanism.EnableAgentAuthentication(conn, opts, zap.S())
238+
ctx := context.Background()
239+
kubeClient, _ := mock.NewDefaultFakeClient()
240+
mdbNamespacedName := &types.NamespacedName{Namespace: "test", Name: "test"}
241+
242+
err := authMechanism.EnableAgentAuthentication(kubeClient, ctx, mdbNamespacedName, conn, opts, zap.S())
216243
require.NoError(t, err)
217244

218245
ac, err := conn.ReadAutomationConfig()

controllers/operator/authentication/ldap.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package authentication
22

33
import (
4+
"context"
5+
46
"go.uber.org/zap"
7+
"k8s.io/apimachinery/pkg/types"
58

69
"github.com/mongodb/mongodb-kubernetes/controllers/om"
710
"github.com/mongodb/mongodb-kubernetes/controllers/operator/ldap"
11+
kubernetesClient "github.com/mongodb/mongodb-kubernetes/mongodb-community-operator/pkg/kube/client"
812
"github.com/mongodb/mongodb-kubernetes/pkg/util"
913
"github.com/mongodb/mongodb-kubernetes/pkg/util/stringutil"
1014
)
@@ -15,7 +19,7 @@ func (l *ldapAuthMechanism) GetName() MechanismName {
1519
return LDAPPlain
1620
}
1721

18-
func (l *ldapAuthMechanism) EnableAgentAuthentication(conn om.Connection, opts Options, log *zap.SugaredLogger) error {
22+
func (l *ldapAuthMechanism) EnableAgentAuthentication(client kubernetesClient.Client, ctx context.Context, mdbNamespacedName *types.NamespacedName, conn om.Connection, opts Options, log *zap.SugaredLogger) error {
1923
log.Info("Configuring LDAP authentication")
2024
err := conn.ReadUpdateAutomationConfig(func(ac *om.AutomationConfig) error {
2125
if err := ac.EnsureKeyFileContents(); err != nil {

0 commit comments

Comments
 (0)