From ac908ade42413dce462056012c81c71285496cb7 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Wed, 3 Aug 2022 10:43:52 +0100 Subject: [PATCH 01/12] Update the django requirements to 3.0 The tests already use django 3+ so we should align this everywhere. Signed-off-by: Peter Robinson --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3d2334b..7881470 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django>=2.1 +django>=3.0 djangorestframework django-ipware psycopg2 From 8a05a86ec1097c5964e3a8641f5227c21e919958 Mon Sep 17 00:00:00 2001 From: rdotjain Date: Sat, 16 Apr 2022 16:42:16 +0530 Subject: [PATCH 02/12] Add a guide to setup zezere instance Signed-off-by: rdotjain --- SETUP.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 SETUP.md diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..82a4941 --- /dev/null +++ b/SETUP.md @@ -0,0 +1,81 @@ +# Setup a zezere instance locally + +1. To install requirements in a Python virtual environment, set it up first. + ```sh + $ virtualenv venv + $ . venv/bin/activate + ``` + +2. Before installing other Python requirements, you need to install Apache httpd first. Follow the instructions from [mod-wsgi project documentation](https://pypi.org/project/mod-wsgi/). +
+In order to satisfy the `psycopg2` dependency please follow instructions from + [psycopg2 project documentation](https://www.psycopg.org/docs/install.html). + +3. Install the requirements + ```sh + $ (venv) pip install . + ``` + +4. Before using the `zezere-manage` tool, a configuration needs to be created. + Default configuration can be used as a base: + + ``` + $ cp zezere/default.conf ./zezere.conf + ``` + +5. Authentication method and secret key needs to be set in order to satisfy the + tool. Also, make sure that the allowed_hosts is what you want. + + ``` + allowed_hosts = localhost, 127.0.0.1 + secret_key = very-secret + auth_method = local + ``` + +6. Now run the migrations, to create a database file. + ```sh + $ python manage.py migrate --noinput + ``` + +7. To collect the static files, run + ``` + $ python manage.py collectstatic + ``` + +8. Now we can create a superuser: + + ``` + $ zezere-manage createsuperuser --username admin --email user@domain.tld + ``` + +9. After a password has been set, we are ready to run Zezere: + + ``` + ./app.sh + ``` + + Use the admin credentials we created to login to localhost:8080 + +
+ +# Setup using Docker +The easiest way to run Zezere is to run the official container and authenticate + with OpenID Connect: + + ``` + $ docker run --detach --rm --name zezere \ + -e OIDC_RP_CLIENT_ID= \ + -e OIDC_RP_CLIENT_SECRET= \ + -e OIDC_OP_AUTHORIZATION_ENDPOINT= \ + -e OIDC_OP_TOKEN_ENDPOINT= \ + -e OIDC_OP_USER_ENDPOINT= \ + -e OIDC_OP_JWKS_ENDPOINT= \ + -e AUTH_METHOD=oidc \ + -e SECRET_KEY=localtest \ + -e ALLOWED_HOSTS=localhost \ + -p 8080:8080 \ + -t quay.io/fedora-iot/zezere:latest + ``` + + The default signing algorithm is `RS256` but it can also be controlled with the + environment variable `OIDC_OP_SIGN_ALGO` \ No newline at end of file From 89f054c704d16230fbede9717f6b0417335d51cd Mon Sep 17 00:00:00 2001 From: rdotjain Date: Sun, 17 Apr 2022 23:56:20 +0530 Subject: [PATCH 03/12] Update .gitignore for conf file Signed-off-by: rdotjain --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 316a346..b49a9f3 100644 --- a/.gitignore +++ b/.gitignore @@ -106,3 +106,6 @@ venv.bak/ # mypy .mypy_cache/ + +# conf file +zezere.conf \ No newline at end of file From c72c732641955ea8313a2b6d1ae4588161860538 Mon Sep 17 00:00:00 2001 From: rdotjain Date: Tue, 21 Jun 2022 13:58:22 +0530 Subject: [PATCH 04/12] Add endpoint to upload ov Signed-off-by: rdotjain --- zezere/templates/portal/master.html | 3 +++ .../templates/portal/ownership_voucher.html | 20 ++++++++++++++++ zezere/urls.py | 3 +++ zezere/views_portal.py | 24 +++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 zezere/templates/portal/ownership_voucher.html diff --git a/zezere/templates/portal/master.html b/zezere/templates/portal/master.html index 1f6de35..c4076c9 100644 --- a/zezere/templates/portal/master.html +++ b/zezere/templates/portal/master.html @@ -56,6 +56,9 @@
  • Device Management
  • +
  • + Add Ownership Voucher +
  • {% else %}
  • Log In diff --git a/zezere/templates/portal/ownership_voucher.html b/zezere/templates/portal/ownership_voucher.html new file mode 100644 index 0000000..6eed47c --- /dev/null +++ b/zezere/templates/portal/ownership_voucher.html @@ -0,0 +1,20 @@ +{% extends "./master.html" %} + +{% load rules %} + +{% block title %}Add Voucher{% endblock %} + +{% block content %} + +{% if message %} +
    {{ message }}
    +{% endif %} + +Add a new ownership voucher: +
    + {% csrf_token %} +
    + +
    + +{% endblock %} diff --git a/zezere/urls.py b/zezere/urls.py index 370eb4e..eb9b4c4 100644 --- a/zezere/urls.py +++ b/zezere/urls.py @@ -40,6 +40,9 @@ views_portal.remove_ssh_key, name="portal_sshkeys_remove", ), + path("portal/ov/", views_portal.ov, name="portal_ov"), + path("portal/ov/add/", views_portal.add_ov, name="portal_ov_add"), + # path("portal/ov/delete/", views_portal.remove_ov, name="portal_ov_remove"), # API path("api/", include(router.urls), name="apis"), path( diff --git a/zezere/views_portal.py b/zezere/views_portal.py index eaff942..5e4c7b6 100644 --- a/zezere/views_portal.py +++ b/zezere/views_portal.py @@ -1,3 +1,5 @@ +import requests + from django.core.exceptions import PermissionDenied from django.db import transaction from django.http import Http404, HttpResponseBadRequest @@ -104,3 +106,25 @@ def add_ssh_key(request): key.full_clean() key.save() return redirect("portal_sshkeys") + + +@login_required +def ov(request): + return render(request, "portal/ownership_voucher.html") + + +@login_required +@require_POST +def add_ov(request): + ov = request.POST["ov"].strip() + url = "http://localhost:8081/management/v1/ownership_voucher" + headers = {"X-Number-Of-Vouchers": "1", "Content-Type": "application/x-pem-file"} + + response = requests.request("POST", url, headers=headers, data=ov) + + if response.status_code == 201: + message = "Successfully added ownership voucher" + else: + message = "Failed to add ownership voucher" + + return render(request, "portal/ownership_voucher.html", {"message": message}) From 8fc2236dd0d1ef04f7a58c69dbdb90425d55c007 Mon Sep 17 00:00:00 2001 From: rdotjain Date: Mon, 27 Jun 2022 01:33:10 +0530 Subject: [PATCH 05/12] Update endpoint to accept CBOR encoded vouchers Signed-off-by: rdotjain --- .../templates/portal/ownership_voucher.html | 7 ++++-- zezere/views_portal.py | 22 +++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/zezere/templates/portal/ownership_voucher.html b/zezere/templates/portal/ownership_voucher.html index 6eed47c..3afe2a7 100644 --- a/zezere/templates/portal/ownership_voucher.html +++ b/zezere/templates/portal/ownership_voucher.html @@ -11,10 +11,13 @@ {% endif %} Add a new ownership voucher: -
    + {% csrf_token %}
    - + OR
    + Upload a CBOR encoded voucher:
    +
    +
    {% endblock %} diff --git a/zezere/views_portal.py b/zezere/views_portal.py index 5e4c7b6..03c43df 100644 --- a/zezere/views_portal.py +++ b/zezere/views_portal.py @@ -116,11 +116,25 @@ def ov(request): @login_required @require_POST def add_ov(request): - ov = request.POST["ov"].strip() - url = "http://localhost:8081/management/v1/ownership_voucher" - headers = {"X-Number-Of-Vouchers": "1", "Content-Type": "application/x-pem-file"} + payload = None + if request.POST["ov"]: + ov = request.POST["ov"].strip() + content_type = "application/x-pem-file" + payload = ov + elif request.FILES: + ov_file = request.FILES["ov_file"] + content_type = "application/cbor" + payload = ov_file.read() + else: + return redirect("portal_ov") - response = requests.request("POST", url, headers=headers, data=ov) + url = "http://localhost:8081/management/v1/ownership_voucher" + headers = { + "X-Number-Of-Vouchers": "1", + "Content-Type": content_type, + "Authorization": "Bearer", + } + response = requests.request("POST", url, headers=headers, data=payload) if response.status_code == 201: message = "Successfully added ownership voucher" From 3615f68ed91e33dd086b85408006b5aa84b08730 Mon Sep 17 00:00:00 2001 From: rdotjain Date: Mon, 27 Jun 2022 02:15:42 +0530 Subject: [PATCH 06/12] Improve error listing in UI using messages Signed-off-by: rdotjain --- zezere/settings.py | 9 +++++++++ zezere/templates/portal/master.html | 1 + zezere/templates/portal/ownership_voucher.html | 6 ++++-- zezere/views_portal.py | 9 ++++++--- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/zezere/settings.py b/zezere/settings.py index d430ba1..2008516 100644 --- a/zezere/settings.py +++ b/zezere/settings.py @@ -2,6 +2,7 @@ import os +from django.contrib.messages import constants as messages from .settings_external import get, getboolean from .settings_auth import AUTH_INFO @@ -161,3 +162,11 @@ "django.contrib.staticfiles.finders.FileSystemFinder", "django.contrib.staticfiles.finders.AppDirectoriesFinder", ] + +MESSAGE_TAGS = { + messages.DEBUG: 'alert-secondary', + messages.INFO: 'alert-info', + messages.SUCCESS: 'alert-success', + messages.WARNING: 'alert-warning', + messages.ERROR: 'alert-danger', + } \ No newline at end of file diff --git a/zezere/templates/portal/master.html b/zezere/templates/portal/master.html index c4076c9..64e5537 100644 --- a/zezere/templates/portal/master.html +++ b/zezere/templates/portal/master.html @@ -70,6 +70,7 @@
    {% block content %} + {% include 'main/includes/messages.html' %} Master content {% endblock %}
    diff --git a/zezere/templates/portal/ownership_voucher.html b/zezere/templates/portal/ownership_voucher.html index 3afe2a7..bcb9241 100644 --- a/zezere/templates/portal/ownership_voucher.html +++ b/zezere/templates/portal/ownership_voucher.html @@ -6,8 +6,10 @@ {% block content %} -{% if message %} -
    {{ message }}
    +{% if messages %} + {% for message in messages %} + {{ message }} + {% endfor %} {% endif %} Add a new ownership voucher: diff --git a/zezere/views_portal.py b/zezere/views_portal.py index 03c43df..79d16f0 100644 --- a/zezere/views_portal.py +++ b/zezere/views_portal.py @@ -1,6 +1,7 @@ import requests from django.core.exceptions import PermissionDenied +from django.contrib import messages from django.db import transaction from django.http import Http404, HttpResponseBadRequest from django.shortcuts import render, get_object_or_404, redirect @@ -126,6 +127,7 @@ def add_ov(request): content_type = "application/cbor" payload = ov_file.read() else: + messages.error(request, "No ownership voucher provided") return redirect("portal_ov") url = "http://localhost:8081/management/v1/ownership_voucher" @@ -137,8 +139,9 @@ def add_ov(request): response = requests.request("POST", url, headers=headers, data=payload) if response.status_code == 201: - message = "Successfully added ownership voucher" + messages.success(request, "Ownership voucher added") else: - message = "Failed to add ownership voucher" + error_code = response.json()["error_code"] + messages.error(request, "Error adding ownership voucher: {}".format(error_code)) - return render(request, "portal/ownership_voucher.html", {"message": message}) + return redirect("portal_ov") From 1a61411a04b8103f3efca47881fb927d90843481 Mon Sep 17 00:00:00 2001 From: rdotjain Date: Sat, 9 Jul 2022 12:40:52 +0530 Subject: [PATCH 07/12] tweak endpoint to accept multiple vouchers Signed-off-by: rdotjain --- zezere/templates/portal/ownership_voucher.html | 9 +++++---- zezere/views_portal.py | 17 ++++++++++------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/zezere/templates/portal/ownership_voucher.html b/zezere/templates/portal/ownership_voucher.html index bcb9241..48b34b9 100644 --- a/zezere/templates/portal/ownership_voucher.html +++ b/zezere/templates/portal/ownership_voucher.html @@ -15,10 +15,11 @@ Add a new ownership voucher:
    {% csrf_token %} -
    - OR
    - Upload a CBOR encoded voucher:
    -
    + Enter the number of vouchers:

    + Enter your voucher contents (Add a newline between the different entries):
    +

    + OR

    + Upload a CBOR encoded voucher:


    diff --git a/zezere/views_portal.py b/zezere/views_portal.py index 79d16f0..e0e4b04 100644 --- a/zezere/views_portal.py +++ b/zezere/views_portal.py @@ -118,21 +118,24 @@ def ov(request): @require_POST def add_ov(request): payload = None - if request.POST["ov"]: - ov = request.POST["ov"].strip() + no_of_vouchers = request.POST["no_of_vouchers"] + + if request.POST.get("ov"): content_type = "application/x-pem-file" - payload = ov - elif request.FILES: - ov_file = request.FILES["ov_file"] + payload = request.POST["ov"].strip() + elif request.FILES.getlist("ov_file"): content_type = "application/cbor" - payload = ov_file.read() + files = request.FILES.getlist("ov_file") + payload = files[0].read() + for f in files[1:]: + payload += f.read() else: messages.error(request, "No ownership voucher provided") return redirect("portal_ov") url = "http://localhost:8081/management/v1/ownership_voucher" headers = { - "X-Number-Of-Vouchers": "1", + "X-Number-Of-Vouchers": no_of_vouchers, "Content-Type": content_type, "Authorization": "Bearer", } From 40b00b23367feec26b0c566b6ef723821a5e060e Mon Sep 17 00:00:00 2001 From: rdotjain Date: Sat, 9 Jul 2022 20:43:44 +0530 Subject: [PATCH 08/12] bug fix: navbar active tab Signed-off-by: rdotjain --- zezere/templates/portal/master.html | 12 ++++++------ zezere/views_portal.py | 20 ++++++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/zezere/templates/portal/master.html b/zezere/templates/portal/master.html index 64e5537..43825c4 100644 --- a/zezere/templates/portal/master.html +++ b/zezere/templates/portal/master.html @@ -44,19 +44,19 @@