1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-08 19:26:48 +00:00
webvirtcloud/virtsecrets/views.py
catborise 2cbcb8ab2c fix: the views that take a password or a key keep it out of error reports
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.
2026-11-05 18:17:00 +03:00

65 lines
3.2 KiB
Python

from admin.decorators import superuser_only
from computes.models import Compute
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.views.decorators.debug import sensitive_post_parameters
from instances.models import Instance
from libvirt import libvirtError
from logs.audit import audit
from vrtManager.virtsecrets import wvmSecrets
from virtsecrets.forms import USAGE_TEXTS, AddSecret
@sensitive_post_parameters()
@superuser_only
def secrets(request, compute_id):
"""The host's secrets with the VMs and pools that use them; one created,
given a value or deleted, after which the list is read again. A value is
never shown or logged."""
compute = get_object_or_404(Compute, pk=compute_id)
secrets_all = []
try:
conn = wvmSecrets(compute.hostname, compute.login, compute.password, compute.type)
if request.method == "POST":
uuid = request.POST.get("uuid", "")
if "create" in request.POST:
form = AddSecret(request.POST)
if form.is_valid():
data = form.cleaned_data
with audit(request, compute, f"Secret {data['usage_type']} {data['usage']}", "add"):
conn.create_secret(data["usage_type"], data["usage"], data["value"],
data["ephemeral"], data["private"])
else:
for msg_err in form.errors.values():
messages.error(request, msg_err.as_text())
elif "set_value" in request.POST:
with audit(request, compute, f"Secret {uuid}", "set value"):
conn.set_secret_value(uuid, request.POST.get("value", ""))
elif "delete" in request.POST:
with audit(request, compute, f"Secret {uuid}", "delete"):
conn.delete_secret(uuid)
return HttpResponseRedirect(request.get_full_path())
# shown only with their users: a list without them would offer to delete secrets in use
secrets = conn.get_secrets_info()
users = conn.get_users(secrets)
vm_ids = dict(Instance.objects.filter(compute=compute).values_list("name", "id"))
labels = dict(AddSecret.base_fields["usage_type"].choices)
for secret in secrets:
used = users.get(secret["uuid"], {"vms": [], "pools": []})
secret["vms"] = [{"name": name, "id": vm_ids.get(name)} for name in used["vms"]]
secret["pools"] = used["pools"]
secret["type_label"] = labels.get(secret["usage_type"], secret["usage_type"])
secrets_all = secrets
except libvirtError as err: # OperationError too: a secret in use, a Ceph key not base64
messages.error(request, err)
if request.method == "POST": # a host not reached or a secret gone as well
return HttpResponseRedirect(request.get_full_path())
usage_choices = AddSecret.base_fields["usage_type"].choices
return render(request, "secrets.html", {"secrets_all": secrets_all, "compute": compute,
"usage_choices": usage_choices, "usage_texts": USAGE_TEXTS})