Skip to content
Snippets Groups Projects
Verified Commit 88fea398 authored by Frank Sauerburger's avatar Frank Sauerburger
Browse files

Merge branch '34-add-wireguard-public-key'

parents a5f7288a 8359de1d
No related branches found
No related tags found
No related merge requests found
Pipeline #9345 passed
Showing
with 287 additions and 0 deletions
...@@ -112,6 +112,8 @@ container-test: ...@@ -112,6 +112,8 @@ container-test:
- echo "${CI_REGISTRY_PASSWORD}" | docker login -u ${CI_REGISTRY_USER} --password-stdin ${CI_REGISTRY} - echo "${CI_REGISTRY_PASSWORD}" | docker login -u ${CI_REGISTRY_USER} --password-stdin ${CI_REGISTRY}
- docker-compose -f docker-compose.yml -f docker-compose.ci.yml pull -q - docker-compose -f docker-compose.yml -f docker-compose.ci.yml pull -q
- docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d - docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d
- sleep 10
- docker-compose restart webserver
deploy_staging: deploy_staging:
# Deploy the current image to the production machine. # Deploy the current image to the production machine.
......
...@@ -13,6 +13,7 @@ COPY owlca /app/owlca ...@@ -13,6 +13,7 @@ COPY owlca /app/owlca
COPY pgp /app/pgp COPY pgp /app/pgp
COPY ssh /app/ssh COPY ssh /app/ssh
COPY wkd /app/wkd COPY wkd /app/wkd
COPY wireguard /app/wireguard
RUN useradd -rMd /app app RUN useradd -rMd /app app
RUN chown -R app:app /app RUN chown -R app:app /app
......
...@@ -72,6 +72,7 @@ INSTALLED_APPS = [ ...@@ -72,6 +72,7 @@ INSTALLED_APPS = [
'owlca', 'owlca',
'pgp', 'pgp',
'ssh', 'ssh',
'wireguard',
'guardian', 'guardian',
'fontawesome-free', 'fontawesome-free',
'crispy_forms', 'crispy_forms',
......
...@@ -21,6 +21,7 @@ urlpatterns = [ ...@@ -21,6 +21,7 @@ urlpatterns = [
path('pgp/', include('pgp.urls')), path('pgp/', include('pgp.urls')),
path('ssh/', include('ssh.urls')), path('ssh/', include('ssh.urls')),
path('pks/', include('hkp.urls')), path('pks/', include('hkp.urls')),
path('wireguard/', include('wireguard.urls')),
path('.well-known/openpgpkey/', include('wkd.urls')), path('.well-known/openpgpkey/', include('wkd.urls')),
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('', include('keys_home.urls')), path('', include('keys_home.urls')),
......
...@@ -440,3 +440,61 @@ body { ...@@ -440,3 +440,61 @@ body {
@extend .my-3; @extend .my-3;
} }
} }
/********************************************************/
/* Wireguard Key */
/********************************************************/
.wireguardkey-item {
@extend .border, .my-3, .rounded;
// every (except last) content box should have a border below
& > div {
@extend .border-bottom, .px-4, .py-2;
}
& > div:last-child {
border-bottom: none !important;
@extend .rounded;
}
/********************************/
/* Heading */
/********************************/
h3 {
// dark heading per key
position: relative; // stretched link inside
justify-content: space-between;
display: flex;
@extend .rounded-top, .text-light, .bg-dark, .p-2;
margin-bottom: 0;
a {
@extend .text-light, .stretched-link;
}
}
/********************************/
/* Fingerprint */
/********************************/
.wireguardkey-fingerprint {
@extend .bg-light;
}
.wireguardkey-fingerprint-title {
@extend .text-muted, .mb-1;
i, svg {
@extend .mr-1;
}
}
.wireguardkey-fingerprint-hash {
@extend .input-group, .mb-2;
input {
@extend .form-control, .bg-white;
font-family: monospace;
}
input + div {
@extend .input-group-append;
span {
@extend .input-group-text;
}
}
}
}
...@@ -51,6 +51,11 @@ ...@@ -51,6 +51,11 @@
<i class="fas fa-network-wired"></i> PKI <i class="fas fa-network-wired"></i> PKI
</a> </a>
</li> </li>
<li>
<a href="{% url 'wireguard-list' %}">
<i class="fas fa-dragon"></i> Wireguard
</a>
</li>
{% if request.user.is_anonymous %} {% if request.user.is_anonymous %}
<li class="navbar-login"> <li class="navbar-login">
<a href="{% url 'login' %}"> <a href="{% url 'login' %}">
......
...@@ -16,6 +16,10 @@ ...@@ -16,6 +16,10 @@
<i class="fas fa-network-wired mb-2"></i><br /> <i class="fas fa-network-wired mb-2"></i><br />
CAs and Certificates CAs and Certificates
</a></h3></li> </a></h3></li>
<li><h3><a href="{% url 'wireguard-list' %}">
<i class="fas fa-dragon mb-2"></i><br />
Wireguard
</a></h3></li>
</ul> </ul>
{% endblock %} {% endblock %}
from django.contrib import admin
from guardian.admin import GuardedModelAdmin
from . import models
class WireguardPublicKeyAdmin(GuardedModelAdmin):
pass
admin.site.register(models.WireguardPublicKey, WireguardPublicKeyAdmin)
from django.apps import AppConfig
class WireguardConfig(AppConfig):
name = 'wireguard'
from django import forms
from django.core.exceptions import ValidationError
class PublicKeyCreateForm(forms.Form):
interface = forms.CharField(max_length=128)
key = forms.CharField(max_length=128)
public = forms.BooleanField(required=False)
# Generated by Django 3.1.14 on 2022-06-10 08:28
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='WireguardPublicKey',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('interface', models.CharField(max_length=128)),
('key', models.CharField(max_length=128)),
('created', models.DateTimeField(auto_now_add=True)),
],
),
]
from django.db import models
class WireguardPublicKey(models.Model):
interface = models.CharField(max_length=128)
key = models.CharField(max_length=128)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.interface}"
{% extends 'keys_home/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<nav class="nav-breadcrumb" aria-label="breadcrumb">
<ol>
<li><a href="{% url 'home' %}">Home</a></li>
<li><a href="{% url 'wireguard-list' %}">Wireguard Keys</a></li>
<li aria-current="page">
<a href="{% url 'wireguard-create' %}">Add</a>
</li>
</ol>
</nav>
<h2>Add Wireguard Public Key</h2>
<form action="" method="post">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" type="submit">Add public key</button>
</form>
{% endblock %}
<li class="wireguardkey-item">
<h3>
<div>
<i class="fas fa-dragon" title="Interface"></i>
{{ publickey.interface }}
</a>
</div>
</h3>
<div class="wireguardkey-fingerprint">
<div class="wireguardkey-fingerprint-title">
<i class="fas fa-fingerprint"></i> Public key
</div>
<div class="wireguardkey-fingerprint-hash">
<input title="publickey" type="text" readonly value="{{publickey.key }}" />
<div><span>Base64</span></div>
</div>
</div>
</li>
{% extends 'keys_home/base.html' %}
{% block content %}
<nav class="nav-breadcrumb" aria-label="breadcrumb">
<ol>
<li><a href="{% url 'home' %}">Home</a></li>
<li aria-current="page">
<a href="{% url 'wireguard-list' %}">Wireguard Keys</a>
</li>
</ol>
</nav>
<h2 class="h-control">
<div>Wireguard Public Keys</div>
{% if perms.wireguard.add_wireguardpublickey %}
<a class="btn btn-outline-primary" href="{% url 'wireguard-create' %}">
<i class="fas fa-plus"></i>
</a>
{% endif %}
</h2>
{% if wireguardpublickey_list %}
<ul class="list-unstyled">
{% for publickey in wireguardpublickey_list %}
{% include 'wireguard/wireguardpublickey_item.html' with fingerprint_only=True %}
{% endfor %}
</ul>
{% else %}
<p>There are not public keys.</p>
{% endif %}
{% endblock %}
from django.test import TestCase
from django.urls import reverse
from django.contrib.auth.models import Group
from guardian.shortcuts import assign_perm
from . import models
class WireguardTest(TestCase):
"""Check keys are listed"""
def test_list_public(self):
"""Check that public keys are listed"""
toykey = models.WireguardPublicKey.objects.create(
interface="example.com",
key="mykey",
)
any_user = Group.objects.get(name="any-user")
assign_perm('view_wireguardpublickey', any_user, toykey)
response = self.client.get(
reverse('wireguard-list')
)
self.assertEqual(response.status_code, 200)
self.assertContains(response, toykey.key)
def test_list_private(self):
"""Check that private keys are not listed"""
toykey = models.WireguardPublicKey.objects.create(
interface="example.com",
key="mykey",
)
response = self.client.get(
reverse('wireguard-list')
)
self.assertEqual(response.status_code, 200)
self.assertNotContains(response, toykey.key)
from django.urls import path
from . import views
urlpatterns = [
path("", views.PublicKeyListView.as_view(), name="wireguard-list"),
path("new", views.publickey_create, name="wireguard-create"),
]
from django.shortcuts import render, reverse
from django.views.generic import DetailView, ListView, CreateView
from django.http import HttpResponseRedirect
from django.contrib.auth.models import Group
from guardian.mixins import PermissionRequiredMixin, PermissionListMixin
from guardian.decorators import permission_required
from guardian.shortcuts import assign_perm
from . import models
from . import forms
class PublicKeyListView(PermissionListMixin, ListView):
model = models.WireguardPublicKey
permission_required = ['view_wireguardpublickey']
@permission_required('wireguard.add_wireguardpublickey')
def publickey_create(request):
if request.method == 'POST':
form = forms.PublicKeyCreateForm(request.POST)
if form.is_valid():
pk = models.WireguardPublicKey()
pk.interface = form.cleaned_data['interface']
pk.key = form.cleaned_data['key']
pk.save()
assign_perm('view_wireguardpublickey', request.user, pk)
assign_perm('change_wireguardpublickey', request.user, pk)
if form.cleaned_data['public']:
any_user = Group.objects.get(name="any-user")
assign_perm('view_wireguardpublickey', any_user, pk)
return HttpResponseRedirect(reverse('wireguard-list'))
# if a GET (or any other method) we'll create a blank form
else:
form = forms.PublicKeyCreateForm()
return render(request,
'wireguard/wireguardpublickey_create.html',
{'form': form})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment