mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 11:16:47 +00:00
- 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.
63 lines
3.1 KiB
Python
63 lines
3.1 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 instances.models import Instance
|
|
from libvirt import libvirtError
|
|
from logs.audit import audit
|
|
from vrtManager.virtsecrets import wvmSecrets
|
|
|
|
from virtsecrets.forms import AddSecret
|
|
|
|
|
|
@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})
|