Skip to content

bug(mongodb): dashboard shows no usable MongoDB credentials on fresh install #2678

Open

Description

@Arsolitt

Describe the bug

After creating a MongoDB.apps.cozystack.io resource and opening the instance in the Cozystack dashboard, the Secrets tab does not present a usable password to the user. Two distinct defects combine to produce this:

  1. The databaseAdmin system credentials Secret (<release>-credentials) is rendered with empty password and uri on first install.
  2. Per-user credentials Secrets (<release>-user-<username>) generated for entries in .Values.users are not exposed to the dashboard at all — the dashboard Role does not grant get/list/watch on them.

So if a user defines users.testuser: {}, the dashboard shows them either:

  • a databaseAdmin entry with an empty password (defect 1), and
  • no testuser credentials at all (defect 2).

Defect 1 self-heals after a subsequent helm upgrade (flux reconcile helmrelease --force is enough). Defect 2 persists until the chart is changed — the dashboard cannot see the Secret regardless of its contents.


Defect 1 — <release>-credentials rendered with empty password/uri on first install

The chart template packages/apps/mongodb/templates/credentials.yaml reads the admin password via helm lookup of the operator-managed Secret internal-<release>-users:

{{- $operatorSecret := lookup "v1" "Secret" .Release.Namespace (printf "internal-%s-users" .Release.Name) }}
{{- $password := "" }}
{{- if and $operatorSecret (hasKey $operatorSecret.data "MONGODB_DATABASE_ADMIN_PASSWORD") }}
{{- $password = index $operatorSecret.data "MONGODB_DATABASE_ADMIN_PASSWORD" | b64dec }}
{{- end }}

On first install the lookup target does not yet exist — Percona Server MongoDB operator creates it asynchronously — so the lookup returns nil and the dashboard Secret is rendered with empty fields. There is an in-tree comment acknowledging this:

# Note: On first install, password/uri will be empty until operator creates the secret.
# Run 'helm upgrade' after MongoDB is ready to populate credentials.

This is the same class of problem tracked in #1942 (Helm lookup is unreliable for cross-controller secret resolution); this issue is the concrete MongoDB symptom.


Defect 2 — per-user Secrets are invisible to the dashboard

packages/apps/mongodb/templates/user-secrets.yaml generates one Secret per user listed under .Values.users:

{{- range $username, $user := .Values.users }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ $.Release.Name }}-user-{{ $username }}
type: Opaque
stringData:
  password: ...
{{- end }}

These Secrets are then referenced by the Percona PerconaServerMongoDB CR through passwordSecretRef, which requires one Secret per user. The per-user Secret design is therefore necessary for the operator.

However, packages/apps/mongodb/templates/dashboard-resourcemap.yaml only grants the dashboard read access to a single Secret name:

- apiGroups: [""]
  resources: [secrets]
  resourceNames:
    - {{ .Release.Name }}-credentials
  verbs: ["get", "list", "watch"]

No -user-<username> Secrets are listed, so the dashboard cannot show those passwords to the tenant. Verified empirically:

$ kubectl auth can-i --as=system:serviceaccount:tenant-root:tenant-root \
    --namespace tenant-root get secret/mongodb-bug-demo-credentials
yes
$ kubectl auth can-i --as=system:serviceaccount:tenant-root:tenant-root \
    --namespace tenant-root get secret/mongodb-bug-demo-user-testuser
no

For comparison, the Postgres chart sidesteps this by writing all per-user passwords as separate keys of the single <release>-credentials Secret (see packages/apps/postgres/templates/init-script.yaml); the dashboard Role covers them with the existing single resourceNames entry. MongoDB cannot fold per-user passwords into one Secret because Percona's CR requires passwordSecretRef.name per user — so the fix has to be on the RBAC / dashboard mapping side, not by changing the Secret layout.


Environment

  • Cozystack version: built from main (HelmChart [email protected]+e988b8517e6d)
  • Provider: on-prem test cluster

To Reproduce

  1. Create a MongoDB.apps.cozystack.io resource in a tenant namespace:

    apiVersion: apps.cozystack.io/v1alpha1
    kind: MongoDB
    metadata:
      name: bug-demo
      namespace: tenant-root
    spec:
      replicas: 1
      resourcesPreset: t1.nano
      size: 1Gi
      users:
        testuser: {}
      databases:
        testdb:
          roles:
            admin: [testuser]
  2. Wait until the HelmRelease reports InstallSucceeded (~15-30 seconds).

  3. Inspect the dashboard credentials Secret and the per-user Secret:

    kubectl --namespace tenant-root get secret mongodb-bug-demo-credentials \
        --output json | jq '.data | map_values(@base64d)'
    kubectl --namespace tenant-root get secret mongodb-bug-demo-user-testuser \
        --output json | jq '.data | map_values(@base64d)'
    
  4. Open the MongoDB instance in the dashboard and check the Secrets tab.

Expected behaviour

  • mongodb-<release>-credentials should contain a non-empty password and a fully-formed uri from the moment the install completes.
  • Per-user Secrets created for entries in .Values.users should be visible in the dashboard so tenants can retrieve the passwords for the users they declared.

Actual behaviour

Right after install:

// mongodb-bug-demo-credentials  (visible to dashboard, empty)
{
  "host": "mongodb-bug-demo-rs0.tenant-root.svc.cozy.local",
  "password": "",
  "port": "27017",
  "uri": "",
  "username": "databaseAdmin"
}

// mongodb-bug-demo-user-testuser  (NOT visible to dashboard, populated)
{
  "password": "tbQAoctxmnbn6Usn"
}

The operator-managed internal-mongodb-bug-demo-users Secret already contains a valid MONGODB_DATABASE_ADMIN_PASSWORD at this point — the chart simply rendered before that Secret was created.

A forced HelmRelease reconcile repopulates the dashboard Secret (defect 1 only):

flux --namespace tenant-root reconcile helmrelease mongodb-bug-demo --force

After that:

{
  "host": "mongodb-bug-demo-rs0.tenant-root.svc.cozy.local",
  "password": "<actual>",
  "port": "27017",
  "uri": "mongodb://databaseAdmin:<actual>@mongodb-bug-demo-rs0.tenant-root.svc.cozy.local:27017/admin?replicaSet=rs0",
  "username": "databaseAdmin"
}

The default spec.interval: 5m0s on the HelmRelease means natural reconciliation may eventually run helm upgrade and fix defect 1, but it leaves the dashboard broken for at least one reconcile cycle. Defect 2 is unaffected by reconciles.

Logs

helmrelease.helm.toolkit.fluxcd.io/mongodb-bug-demo   60s   True   Helm install succeeded for release tenant-root/mongodb-bug-demo.v1 with chart [email protected]+e988b8517e6d

Screenshots

Dashboard Secrets tab renders password and uri cells empty for databaseAdmin, and testuser is missing from the list entirely while it is defined in the instance's users: values.

Additional context

  • Affected files: packages/apps/mongodb/templates/credentials.yaml, packages/apps/mongodb/templates/dashboard-resourcemap.yaml, packages/apps/mongodb/templates/user-secrets.yaml
  • Defect 1 root cause is the same as feat: Replace Helm lookup with OpenBao + ESO + Operator architecture #1942 (Helm lookup race vs operator-created Secrets).
  • Other DB charts (mysql, postgres, mariadb, redis, …) that use the same lookup-on-operator-secret pattern may share defect 1 — worth a sweep.
  • Defect 2 (per-user Secrets invisible to dashboard) likely affects any chart that creates Secrets outside <release>-credentials but still wants the dashboard to display them. A quick grep across packages/apps/*/templates/dashboard-resourcemap.yaml shows every chart hard-codes a single Secret name in resourceNames — worth checking which of them have per-user or per-resource Secrets that are similarly hidden.
  • Possible local fixes (not selected here, deferred to maintainer discussion):
    • Defect 1: drop <release>-credentials and map dashboard fields directly from internal-<release>-users with key remapping; or add a post-install Job that waits for the operator Secret and patches the dashboard Secret; or move to ExternalSecret once feat: Replace Helm lookup with OpenBao + ESO + Operator architecture #1942 lands.
    • Defect 2: extend the dashboard Role to include <release>-user-<username> Secret names for each declared user; or label per-user Secrets and grant the dashboard a separate list+watch with a labelSelector-based filter on the client side; or change the architecture to store user passwords as keys of <release>-credentials (incompatible with Percona's passwordSecretRef requirement, would need an extra controller to fan them back out).

Checklist

  • I have checked the documentation
  • I have searched for similar issues
  • I have included all required information
  • I have provided clear steps to reproduce
  • I have included relevant logs

Activity

  1. added
    kind/bugCategorizes issue or PR as related to a bug
    area/databaseIssues or PRs related to managed databases (postgres, mariadb, redis, etcd, kafka, clickhouse)
    area/dashboardIssues or PRs related to the dashboard / UI
    on May 19, 2026
  2. dosubot commented on May 19, 2026

    @dosubot

    Good bug report — both defects are confirmed and well-characterized. Here's some additional context from the codebase that may help the discussion:

    On Defect 1 (empty credentials on first install):

    Interestingly, the Redis and MariaDB charts already avoid this exact race by generating a random fallback password when the operator secret doesn't exist yet, rather than leaving it empty [1] [2]. MongoDB could adopt the same pattern: generate a random password on first install, then on subsequent reconciles pick up the operator-managed one from internal-<release>-users. This would give immediate usability without breaking the operator flow.

    The broader architectural fix (replacing all lookup-based patterns with OpenBao + External Secrets Operator) is tracked in #1942 [3], but that issue was marked stale on 2026-05-02 with no concrete implementation timeline yet — so a local fix in credentials.yaml is likely the pragmatic path for now.

    On Defect 2 (per-user secrets invisible to dashboard):

    The dashboard resource map hard-codes a single resourceNames entry across all DB charts [4]. PostgreSQL avoids this by consolidating all user passwords as keys within the single <release>-credentials secret [5], but as you noted, that's incompatible with Percona's passwordSecretRef requirement.

    The simplest fix would be to dynamically extend the resourceNames list in dashboard-resourcemap.yaml by ranging over .Values.users:

    resourceNames:
      - {{ .Release.Name }}-credentials
      {{- range $username, $_ := .Values.users }}
      - {{ $.Release.Name }}-user-{{ $username }}
      {{- end }}

    This keeps the explicit-allow RBAC model while making per-user secrets visible without any architectural changes.

    Sweep across other charts:

    A quick look confirms every chart in packages/apps/*/templates/dashboard-resourcemap.yaml hard-codes a single secret name [6]. Currently MongoDB is the only one generating per-user secrets as separate Secret objects, so Defect 2 appears MongoDB-specific for now.

    To reply, just mention @dosu.


    Share context across your team and agents. Try Dosu.

    Leave Feedback Learn about cozystack with Dosu Add Dosu to your team

  3. added
    triage/acceptedIndicates an issue is ready to be actively worked on
    priority/important-longtermImportant over the long term, but may not be staffed and/or may need multiple releases to complete
    on Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/dashboardIssues or PRs related to the dashboard / UIarea/databaseIssues or PRs related to managed databases (postgres, mariadb, redis, etcd, kafka, clickhouse)kind/bugCategorizes issue or PR as related to a bugpriority/important-longtermImportant over the long term, but may not be staffed and/or may need multiple releases to completetriage/acceptedIndicates an issue is ready to be actively worked on

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions