Skip to content

fix(deployments): persist non-SSH app credentials per group and teacher - #173

Merged
Dilmand merged 1 commit into
stagingfrom
fix/persist-app-credentials-for-groups-and-teacher
Jun 29, 2026
Merged

fix(deployments): persist non-SSH app credentials per group and teacher#173
Dilmand merged 1 commit into
stagingfrom
fix/persist-app-credentials-for-groups-and-teacher

Conversation

@Dilmand

@Dilmand Dilmand commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Persist non-SSH credentials (postgres, pgadmin, web_url, …) into deployment_instance_access for both groups and the teacher, so the lecturer UI's "Gruppen"-Tab is populated and students see their credentials via /api/v1/student/.

Problem

For templates whose app.yaml declares per_group credentials of any type other than linux (e.g. ansible-postgres-group-db with per_group: postgres + pgadmin), the lecturer UI showed only the teacher's auto-generated SSH row — no Gruppen-Tab, no per-group entries. Students saw nothing at all.

Root cause in src/tasks/deploy_tasks.py:253-279: the builder for credentials_for_db was hardcoded to SSH/Linux:

"credentials": [
    { "username": s["linux"]["username"], "password": s["linux"]["password"], ... }
    for s in generated.get("deployment_groups", [])
    if s.get("linux", {}).get("password")    # ← filters out groups without linux
],
"admin_credentials": { "username": generated["teacher"]["linux"]["username"], ... },

Templates without per_group.linux produced an empty credentials[]. applications[] was never built. The teacher row only survived because credential_generator_service auto-generates a linux block for the teacher unconditionally (admin SSH key).

A secondary issue: _extract_access_entries already supported user_json["applications"][*], but didn't read group_id from those entries — so even if applications[] had been populated, every database row would have landed with group_id=NULL and been invisible to students.

Changes

src/tasks/deploy_tasks.py

  • SSH section unchanged in behaviour: groups without per_group.linux still don't get SSH access rows (correct — there's no Linux user on the VM to log into).
  • New: build applications[] by discovering every non-bookkeeping key in generated["deployment_groups"][*] and generated["teacher"]. Bookkeeping keys excluded: username, email, group_name, group_index, course_group_id, students, linux.
  • One applications entry per credential type. credentials[] carries group_id per group (from course_group_id); admin_credentials carries the teacher's block (group_id forced to None downstream).

src/services/deployment_credential_service.py

  • _extract_access_entries now reads group_id from each per-group application credential and sets it explicitly to None for admin_credentials — mirrors the existing SSH admin handling.

Effect on existing templates

Template Before After
ansible-postgres-group-db (per_group: postgres + pgadmin) 1 row (teacher SSH) 1 SSH + 2 groups × 2 cred types + 2 teacher cred types = 7 rows
ansible-multiuser (per_group: linux) Group SSH rows + teacher SSH Same as before — no applications[] produced because the template has no non-linux per_group / teacher creds
Future templates with mixed cred types Only linux persisted All cred types persisted, group-stamped

Verified

Tested locally against the staging dilo-pg template (ansible-postgres-group-db). After the fix, the lecturer UI shows the Gruppen-Tab with two groups, each with their postgres + pgadmin entries, and the Dozent-Tab shows the SSH admin row plus the teacher's postgres + pgadmin entries.

Migration / backfill

Existing deployments are not retroactively backfilled — passwords aren't persisted before reaching this stage, so there's nothing to reconstruct them from. Deployments created before this fix will continue to show only the teacher SSH row. Re-deploy to get the full credential set.

Risks

  • The dynamic key discovery loop trusts credential_generator_service.py's output shape. If a future credential generator adds a new top-level bookkeeping key (e.g. metadata), it would leak into applications[] as a cred type. Mitigation: the NON_APP_KEYS set is one line to update.
  • pgadmin_url is read from heat_outputs and applied globally per stack — unchanged behaviour, just exercised more often now.

Previously, deploy_tasks built credentials_for_db with only SSH/Linux
credentials — the per-group loop filtered on s['linux']['password'],
and the teacher block only emitted an SSH admin entry. For templates
whose app.yaml declares per_group credentials of any other type
(postgres, pgadmin, web_url, ...), the resulting user_json had an empty
'instance.credentials' list and no 'applications' section, so
DeploymentInstanceAccess rows were only ever written for the teacher's
auto-generated SSH key. Students saw nothing in the lecturer UI either
(no Gruppen tab) because no group_id-stamped rows existed.

Now deploy_tasks discovers every non-bookkeeping key in
generated['deployment_groups'][*] and generated['teacher'] (i.e.
everything except username/email/group_name/group_index/course_group_id/
students/linux — linux is still handled via the dedicated SSH section)
and emits one applications[] entry per credential type. Each entry
carries group_id pulled from course_group_id for groups, and explicit
None for the teacher's admin_credentials. SSH handling is unchanged.

In the credential service, _extract_access_entries now reads group_id
from each application credential and sets it explicitly to None for
admin_credentials. Without this, even a populated applications[] would
have written rows with group_id NULL and remained invisible to students.

Verified against the ansible-postgres-group-db template
(per_group: postgres + pgadmin, teacher: postgres + pgadmin, no linux):
two groups × two cred types now yields four group-stamped DATABASE
rows and two admin DATABASE rows, plus the existing SSH admin row.
@Dilmand
Dilmand merged commit 1be4c60 into staging Jun 29, 2026
6 checks passed
@Dilmand
Dilmand deleted the fix/persist-app-credentials-for-groups-and-teacher branch June 29, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant