Skip to content

Commit

Permalink
Cachesecret (#232)
Browse files Browse the repository at this point in the history
* https://infoblox.atlassian.net/browse/ATLAS-18815

* updating to latest psql client
  • Loading branch information
bjeevan-ib authored Mar 8, 2024
1 parent 3953d8e commit 71be670
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 59 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o manager cmd/manager/mai
# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM alpine:3.18
RUN apk --update add postgresql15-client=15.5-r0 --repository=http://dl-cdn.alpinelinux.org/alpine/v3.18/main
RUN apk --update add postgresql15-client=15.6-r0 --repository=http://dl-cdn.alpinelinux.org/alpine/v3.18/main
WORKDIR /
COPY --from=builder /workspace/manager .
COPY --from=builder /workspace/config/ /config/
Expand Down
146 changes: 103 additions & 43 deletions controllers/databaseclaim_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,25 @@ type Error string
func (e Error) Error() string { return string(e) }

const (
defaultPassLen = 32
defaultNumDig = 10
defaultNumSimb = 10
minRotationTime = 60 // rotation time in minutes
maxRotationTime = 1440
maxWaitTime = 10
maxNameLen = 44 // max length of dbclaim name
defaultRotationTime = minRotationTime
serviceNamespaceEnvVar = "SERVICE_NAMESPACE"
defaultPostgresStr = "postgres"
defaultAuroraPostgresStr = "aurora-postgresql"
defaultRestoreFromSource = "Snapshot"
defaultBackupPolicyKey = "Backup"
tempTargetPassword = "targetPassword"
tempSourceDsn = "sourceDsn"
masterSecretSuffix = "-master"
masterPasswordKey = "password"
ErrMaxNameLen = Error("dbclaim name is too long. max length is 44 characters")
defaultPassLen = 32
defaultNumDig = 10
defaultNumSimb = 10
minRotationTime = 60 // rotation time in minutes
maxRotationTime = 1440
maxWaitTime = 10
maxNameLen = 44 // max length of dbclaim name
defaultRotationTime = minRotationTime
serviceNamespaceEnvVar = "SERVICE_NAMESPACE"
defaultPostgresStr = "postgres"
defaultAuroraPostgresStr = "aurora-postgresql"
defaultRestoreFromSource = "Snapshot"
defaultBackupPolicyKey = "Backup"
tempTargetPassword = "targetPassword"
tempSourceDsn = "sourceDsn"
cachedMasterPasswdForExistingDB = "cachedMasterPasswdForExistingDB"
masterSecretSuffix = "-master"
masterPasswordKey = "password"
ErrMaxNameLen = Error("dbclaim name is too long. max length is 44 characters")
// InfoLevel is used to set V level to 0 as suggested by official docs
// https://github.com/kubernetes-sigs/controller-runtime/blob/main/TMP-LOGGING.md
InfoLevel = 0
Expand Down Expand Up @@ -609,6 +610,18 @@ func (r *DatabaseClaimReconciler) reconcileUseExistingDB(ctx context.Context, db
dbClaim.Status.NewDB.SourceDataFrom = dbClaim.Spec.SourceDataFrom.DeepCopy()

logr.Info("creating database client")
masterPassword, err := r.getMasterPasswordForExistingDB(ctx, dbClaim)
if err != nil {
logr.Error(err, "get master password for existing db error")
return err
}
//cache master password for existing db
err = r.setMasterPasswordInTempSecret(ctx, masterPassword, dbClaim)
if err != nil {
logr.Error(err, "cache master password error")
return err
}
existingDBConnInfo.Password = masterPassword
dbClient, err := r.getClientForExistingDB(ctx, logr, dbClaim, existingDBConnInfo)
if err != nil {
logr.Error(err, "creating database client error")
Expand Down Expand Up @@ -780,6 +793,7 @@ func (r *DatabaseClaimReconciler) reconcileMigrationInProgress(ctx context.Conte
}
sourceMasterConn.Password, err = r.getSrcAdminPasswdFromSecret(ctx, dbClaim)
if err != nil {
logr.Error(err, "source master secret and cached master secret not found")
return r.manageError(ctx, dbClaim, err)
}
} else if r.Mode == M_UpgradeDBInProgress ||
Expand Down Expand Up @@ -1107,12 +1121,34 @@ func (r *DatabaseClaimReconciler) manageOperationalTagging(ctx context.Context,

}

func (r *DatabaseClaimReconciler) getClientForExistingDB(ctx context.Context, logr logr.Logger,
dbClaim *persistancev1.DatabaseClaim, connInfo *persistancev1.DatabaseClaimConnectionInfo) (dbclient.Client, error) {
func (r *DatabaseClaimReconciler) getMasterPasswordForExistingDB(ctx context.Context,
dbClaim *persistancev1.DatabaseClaim) (string, error) {

secretKey := "password"
gs := &corev1.Secret{}

ns := dbClaim.Spec.SourceDataFrom.Database.SecretRef.Namespace
if ns == "" {
ns = dbClaim.Namespace
}
err := r.Client.Get(ctx, client.ObjectKey{
Namespace: ns,
Name: dbClaim.Spec.SourceDataFrom.Database.SecretRef.Name,
}, gs)
if err != nil {
return "", err
}
password := string(gs.Data[secretKey])

if password == "" {
return "", fmt.Errorf("invalid credentials (password)")
}
return password, nil
}

func (r *DatabaseClaimReconciler) getClientForExistingDB(ctx context.Context, logr logr.Logger,
dbClaim *persistancev1.DatabaseClaim, connInfo *persistancev1.DatabaseClaimConnectionInfo) (dbclient.Client, error) {

if connInfo == nil {
return nil, fmt.Errorf("invalid connection info")
}
Expand All @@ -1133,21 +1169,6 @@ func (r *DatabaseClaimReconciler) getClientForExistingDB(ctx context.Context, lo
return nil, fmt.Errorf("invalid sslMode")
}

r.Log.Info("using credentials from secret")

ns := dbClaim.Spec.SourceDataFrom.Database.SecretRef.Namespace
if ns == "" {
ns = dbClaim.Namespace
}
err := r.Client.Get(ctx, client.ObjectKey{
Namespace: ns,
Name: dbClaim.Spec.SourceDataFrom.Database.SecretRef.Name,
}, gs)
if err != nil {
return nil, err
}
connInfo.Password = string(gs.Data[secretKey])

if connInfo.Password == "" {
return nil, fmt.Errorf("invalid credentials (password)")
}
Expand Down Expand Up @@ -1622,11 +1643,7 @@ func (r *DatabaseClaimReconciler) manageUser(dbClient dbclient.Client, status *p
if err != nil {
return err
}
err = dbClient.ManageCreateRole(status.ConnectionInfo.Username, r.Input.EnableSuperUser)
if err != nil {
return err
}
err = dbClient.ManageCreateRole(dbu.NextUser(status.ConnectionInfo.Username), r.Input.EnableSuperUser)
err = dbClient.ManageCreateRole(baseUsername, r.Input.EnableSuperUser)
if err != nil {
return err
}
Expand Down Expand Up @@ -2586,6 +2603,7 @@ func (r *DatabaseClaimReconciler) updateSecret(ctx context.Context, dsnName, dsn
exSecret.Data["uri_"+dsnName] = []byte(dbURI)
exSecret.Data["hostname"] = []byte(connInfo.Host)
exSecret.Data["port"] = []byte(connInfo.Port)
exSecret.Data["database"] = []byte(connInfo.DatabaseName)
exSecret.Data["username"] = []byte(connInfo.Username)
exSecret.Data["password"] = []byte(connInfo.Password)
exSecret.Data["sslmode"] = []byte(connInfo.SSLMode)
Expand Down Expand Up @@ -2748,10 +2766,19 @@ func (r *DatabaseClaimReconciler) getSrcAdminPasswdFromSecret(ctx context.Contex
Namespace: ns,
Name: dbClaim.Spec.SourceDataFrom.Database.SecretRef.Name,
}, gs)
if err == nil {
return string(gs.Data[secretKey]), nil
}
//err!=nil
if !errors.IsNotFound(err) {
return "", err
}
//not found - check temp secret
p, err := r.getMasterPasswordFromTempSecret(ctx, dbClaim)
if err != nil {
return "", err
}
return string(gs.Data[secretKey]), nil
return p, nil
}

func (r *DatabaseClaimReconciler) getSrcAppDsnFromSecret(ctx context.Context, dbClaim *persistancev1.DatabaseClaim) (string, error) {
Expand Down Expand Up @@ -2848,6 +2875,26 @@ func (r *DatabaseClaimReconciler) getTargetPasswordFromTempSecret(ctx context.Co
return string(gs.Data[tempTargetPassword]), nil
}

func (r *DatabaseClaimReconciler) getMasterPasswordFromTempSecret(ctx context.Context, dbClaim *persistancev1.DatabaseClaim) (string, error) {

secretName := "temp-" + dbClaim.Spec.SecretName

gs := &corev1.Secret{}

ns := dbClaim.Namespace
if ns == "" {
ns = "default"
}
err := r.Client.Get(ctx, client.ObjectKey{
Namespace: ns,
Name: secretName,
}, gs)
if err != nil {
return "", err
}
return string(gs.Data[cachedMasterPasswdForExistingDB]), nil
}

func (r *DatabaseClaimReconciler) setSourceDsnInTempSecret(ctx context.Context, dsn string, dbClaim *persistancev1.DatabaseClaim) error {

tSecret, err := r.getTempSecret(ctx, dbClaim)
Expand All @@ -2872,6 +2919,18 @@ func (r *DatabaseClaimReconciler) setTargetPasswordInTempSecret(ctx context.Cont
return r.Client.Update(ctx, tSecret)
}

func (r *DatabaseClaimReconciler) setMasterPasswordInTempSecret(ctx context.Context, password string, dbClaim *persistancev1.DatabaseClaim) error {

tSecret, err := r.getTempSecret(ctx, dbClaim)
if err != nil {
return err
}

r.Log.Info("updating temp secret target password")
tSecret.Data[cachedMasterPasswdForExistingDB] = []byte(password)
return r.Client.Update(ctx, tSecret)
}

func (r *DatabaseClaimReconciler) getTempSecret(ctx context.Context, dbClaim *persistancev1.DatabaseClaim) (*corev1.Secret, error) {

gs := &corev1.Secret{}
Expand Down Expand Up @@ -2904,8 +2963,9 @@ func (r *DatabaseClaimReconciler) getTempSecret(ctx context.Context, dbClaim *pe
},
},
Data: map[string][]byte{
tempTargetPassword: nil,
tempSourceDsn: nil,
tempTargetPassword: nil,
tempSourceDsn: nil,
cachedMasterPasswdForExistingDB: nil,
},
}

Expand Down
34 changes: 19 additions & 15 deletions controllers/dbc_end2end_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,15 @@ var _ = Describe("db-controller end to end testing", Label("integration"), Order
})
Context("Migrate Use Existing RDS to a local RDS", func() {
It("should create a new RDS and migrate Existing database", func() {
By("Removing the useExistingFlag in dbclaim")
By("deleting master secret to access existing RDS")
//delete master secret if it exists
e2e_k8sClient.Delete(ctx, &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: newdbcMasterSecretName,
Namespace: dbcNamespace,
},
})
By("Removing the useExistingFlag in dbclaim and forcing the use of cached secret")
MigrateUseExistingToNewRDS()
})
})
Expand All @@ -154,15 +162,6 @@ var _ = Describe("db-controller end to end testing", Label("integration"), Order

cleanupdb(db1)
cleanupdb(db2)
//delete master secret if it exists
By("deleting the master secret")
e2e_k8sClient.Delete(ctx, &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: newdbcMasterSecretName,
Namespace: dbcNamespace,
},
})

//delete the namespace
By("deleting the namespace")
e2e_k8sClient.Delete(ctx, &corev1.Namespace{
Expand Down Expand Up @@ -254,10 +253,15 @@ func MigrateUseExistingToNewRDS() {
//check if eventually the secret sample-secret is created
By("checking if the secret is created and host name contains 1ec9b27c")
//box-3-end2end-test-2-dbclaim-1ec9b27c
Eventually(func() error {
return e2e_k8sClient.Get(ctx, types.NamespacedName{Name: "sample-secret", Namespace: namespace}, &corev1.Secret{})
}, timeout_e2e, interval_e2e).Should(BeNil())

newSecret := &corev1.Secret{}
Eventually(func() bool {
e2e_k8sClient.Get(ctx, types.NamespacedName{Name: "sample-secret", Namespace: namespace}, newSecret)
if string(newSecret.Data["database"]) == "sample_db_new" {
return true
} else {
return false
}
}, timeout_e2e, interval_e2e).Should(BeTrue())
}

func UseExistingPostgresRDSTest() {
Expand All @@ -277,7 +281,7 @@ func UseExistingPostgresRDSTest() {
Spec: persistancev1.DatabaseClaimSpec{
Class: &class,
AppID: "sample-app",
DatabaseName: "sample_db",
DatabaseName: "sample_db_new",
SecretName: "sample-secret",
Username: "sample_user",
Type: "postgres",
Expand Down

0 comments on commit 71be670

Please sign in to comment.