No view used sensitive_post_parameters, so once ADMINS is set the error
mail of a failing POST would carry the password or key in plain text.
The user create, edit and password views, the password change, the
compute forms, the host secrets, the VM's root password and its console
settings now mark their POST data sensitive.
The host pages lose their last inline scripts: the overview's charts
(host_graphs.js), the New pool, New network and New interface dialogs
(pool_dialog.js, network_dialog.js, interface_dialog.js), a network's
and a network filter's XML editors and dialogs (network_page.js,
nwfilter_page.js, nwfilters_page.js), the secrets page's labels
(secrets_page.js, its texts from the view as usage_texts) and a pool's
page with the ISO upload (storage_page.js). Their URLs and messages are
data attributes of the elements they belong to; the upload reads its
token and address from its form. No template has an inline script or
an inline event handler any more.
- One searchable card: each secret's type, usage and UUID, whether it is
kept on disk or in memory and private, and the VMs and pools that use it,
linked. A row menu sets its value or deletes it; Delete is disabled while
the secret is in use, and its confirmation says what is not checked.
- One Set value dialog for every secret; its label and help follow the
type (Ceph key, CHAP password, passphrase), and it says a new passphrase
does not encrypt anew what the old one encrypted.
- New secret dialog: the usage's and value's labels and help follow the
type; the value is optional; Private and Ephemeral are switches with help.
- A secret is in use when a VM names it in a disk, a host device or its
vTPM, or a pool in its source, by UUID or by its usage within the usage
type, as they run and as saved. The vTPM, host devices and pools' saved
definitions were not checked before.
- A Ceph key is taken in base64, as `ceph auth get-key` prints it; any other
value is a password or passphrase stored as typed, spaces included.
- A new secret takes its value at once; a value refused leaves no secret.
- TLS and vTPM secrets can be created; the usage has no length limit.
- Every POST redirects; the list is read once and only with its users; a
secret, VM or pool gone meanwhile is left out.
- domain_trees() is shared by the in-use checks of secrets, network filters,
networks and pools; the storage page's Ceph secret picker reads the same
listing.
- The host graphs and the machine/bus lists connect inside their libvirt
error handling, so a down host gives empty answers instead of a 500 page
the polling script drops.
- The Secrets page lists vTPM secrets instead of failing on them, and a
secret without usage data shows an empty cell instead of "None".
- A TCP/TLS host takes a SASL password longer than 14 characters and a
login up to the Linux limit of 32.
- The compute edit page says "Edit Compute"; a host without VMs no longer
closes an extra page element; the memory graph is labelled MiB.
The Logs page now records every change an admin makes to a compute's
libvirt objects, with the compute's name in the host column:
- networks: add, start, stop, delete, autostart, DHCP range, fixed
addresses, QoS and XML edits;
- storage pools: add, start, stop, delete, autostart, from web and
API; volumes: add and delete (web and API), clone and ISO upload;
- host interfaces: add, start, stop, delete;
- secrets: add, set value (never the value), delete;
- network filters: add, clone, delete, XML edits, rules and
references.
A refused or failed change is a failed row with its reason (libvirt
text through safe_text). The volume clone and upload jobs write their
row when they end; a refused submission is a failed row at once. A
volume row names the volume libvirt created (a dir pool adds .qcow2 or
.img). Volume create or delete through the API on an inactive pool
(409) is a failed row.
Network filters: the rows read "Network filter f1: add" instead of
"f1 network filter is created", and their host is the compute's name
instead of its hostname. A duplicate name or UUID no longer raises a
bare exception, and a filter XML that cannot be parsed no longer ends
in UnboundLocalError.
Stopping a network cut the running VMs on it off, deleting one or a
secret kept the VMs that name it from starting, and stopping a pool
took the disks of running VMs away, all without a word. Each is now
refused with the VMs (and, for a secret, the pools) that need it:
stopping while a running VM uses it, deleting while a VM's definition
names it. A disk given by its file path does not need its pool's
definition. The API's pool stop is refused the same way.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The usage list of the create-secret dialog came from the map that names
the usage types of existing secrets, so it offered none and tls too; the
form takes ceph, volume and iscsi only, and picking none or tls always
failed with "Select a valid choice". The dialog now lists the form's own
choices.
The edit dialog of a secret was filled with its current value, so every
readable secret's value was in the secrets page's HTML. A private
secret, or one with no value yet, cannot be read: its field held the
text "None", which is valid base64, and saving the dialog unchanged set
the secret to the three bytes it decodes to. The dialog now only writes
a new value: the field starts empty, is a password field and is
required. The page no longer reads secret values, and get_secret_value,
used only for that, is gone.