mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-23 20:03:11 +00:00
Merge branch 'fingerprintssh' into 'master'
Fingerprintssh See merge request federez/re2o!193
This commit is contained in:
commit
2e97af4aba
15 changed files with 386 additions and 4 deletions
|
@ -222,6 +222,13 @@ class SrvSerializer(NamespacedHMSerializer):
|
||||||
fields = ('service', 'protocole', 'extension', 'ttl', 'priority',
|
fields = ('service', 'protocole', 'extension', 'ttl', 'priority',
|
||||||
'weight', 'port', 'target', 'api_url')
|
'weight', 'port', 'target', 'api_url')
|
||||||
|
|
||||||
|
class SshFpSerializer(NamespacedHMSerializer):
|
||||||
|
"""Serialize `machines.models.SSHFP` objects.
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
model = machines.SshFp
|
||||||
|
field = ('machine', 'pub_key_entry', 'algo', 'comment', 'api_url')
|
||||||
|
|
||||||
|
|
||||||
class InterfaceSerializer(NamespacedHMSerializer):
|
class InterfaceSerializer(NamespacedHMSerializer):
|
||||||
"""Serialize `machines.models.Interface` objects.
|
"""Serialize `machines.models.Interface` objects.
|
||||||
|
@ -679,6 +686,26 @@ class SRVRecordSerializer(SrvSerializer):
|
||||||
fields = ('service', 'protocole', 'ttl', 'priority', 'weight', 'port', 'target')
|
fields = ('service', 'protocole', 'ttl', 'priority', 'weight', 'port', 'target')
|
||||||
|
|
||||||
|
|
||||||
|
class SSHFPRecordSerializer(SshFpSerializer):
|
||||||
|
"""Serialize `machines.models.SshFp` objects with the data needed to
|
||||||
|
generate a SSHFP DNS record.
|
||||||
|
"""
|
||||||
|
class Meta(SshFpSerializer.Meta):
|
||||||
|
fields = ('algo_id', 'hash')
|
||||||
|
|
||||||
|
|
||||||
|
class SSHFPInterfaceSerializer(serializers.ModelSerializer):
|
||||||
|
"""Serialize `machines.models.Domain` objects with the data needed to
|
||||||
|
generate a CNAME DNS record.
|
||||||
|
"""
|
||||||
|
hostname = serializers.CharField(source='domain.name', read_only=True)
|
||||||
|
sshfp = SSHFPRecordSerializer(source='machine.sshfp_set', many=True, read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = machines.Interface
|
||||||
|
fields = ('hostname', 'sshfp')
|
||||||
|
|
||||||
|
|
||||||
class ARecordSerializer(serializers.ModelSerializer):
|
class ARecordSerializer(serializers.ModelSerializer):
|
||||||
"""Serialize `machines.models.Interface` objects with the data needed to
|
"""Serialize `machines.models.Interface` objects with the data needed to
|
||||||
generate a A DNS record.
|
generate a A DNS record.
|
||||||
|
@ -729,12 +756,13 @@ class DNSZonesSerializer(serializers.ModelSerializer):
|
||||||
a_records = ARecordSerializer(many=True, source='get_associated_a_records')
|
a_records = ARecordSerializer(many=True, source='get_associated_a_records')
|
||||||
aaaa_records = AAAARecordSerializer(many=True, source='get_associated_aaaa_records')
|
aaaa_records = AAAARecordSerializer(many=True, source='get_associated_aaaa_records')
|
||||||
cname_records = CNAMERecordSerializer(many=True, source='get_associated_cname_records')
|
cname_records = CNAMERecordSerializer(many=True, source='get_associated_cname_records')
|
||||||
|
sshfp_records = SSHFPInterfaceSerializer(many=True, source='get_associated_sshfp_records')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = machines.Extension
|
model = machines.Extension
|
||||||
fields = ('name', 'soa', 'ns_records', 'originv4', 'originv6',
|
fields = ('name', 'soa', 'ns_records', 'originv4', 'originv6',
|
||||||
'mx_records', 'txt_records', 'srv_records', 'a_records',
|
'mx_records', 'txt_records', 'srv_records', 'a_records',
|
||||||
'aaaa_records', 'cname_records')
|
'aaaa_records', 'cname_records', 'sshfp_records')
|
||||||
|
|
||||||
|
|
||||||
# MAILING
|
# MAILING
|
||||||
|
|
|
@ -54,6 +54,7 @@ router.register_viewset(r'machines/ns', views.NsViewSet)
|
||||||
router.register_viewset(r'machines/txt', views.TxtViewSet)
|
router.register_viewset(r'machines/txt', views.TxtViewSet)
|
||||||
router.register_viewset(r'machines/dname', views.DNameViewSet)
|
router.register_viewset(r'machines/dname', views.DNameViewSet)
|
||||||
router.register_viewset(r'machines/srv', views.SrvViewSet)
|
router.register_viewset(r'machines/srv', views.SrvViewSet)
|
||||||
|
router.register_viewset(r'machines/sshfp', views.SshFpViewSet)
|
||||||
router.register_viewset(r'machines/interface', views.InterfaceViewSet)
|
router.register_viewset(r'machines/interface', views.InterfaceViewSet)
|
||||||
router.register_viewset(r'machines/ipv6list', views.Ipv6ListViewSet)
|
router.register_viewset(r'machines/ipv6list', views.Ipv6ListViewSet)
|
||||||
router.register_viewset(r'machines/domain', views.DomainViewSet)
|
router.register_viewset(r'machines/domain', views.DomainViewSet)
|
||||||
|
|
|
@ -177,6 +177,13 @@ class SrvViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
serializer_class = serializers.SrvSerializer
|
serializer_class = serializers.SrvSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class SshFpViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
|
"""Exposes list and details of `machines.models.SshFp` objects.
|
||||||
|
"""
|
||||||
|
queryset = machines.SshFp.objects.all()
|
||||||
|
serializer_class = serializers.SshFpSerializer
|
||||||
|
|
||||||
|
|
||||||
class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
|
class InterfaceViewSet(viewsets.ReadOnlyModelViewSet):
|
||||||
"""Exposes list and details of `machines.models.Interface` objects.
|
"""Exposes list and details of `machines.models.Interface` objects.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -39,11 +39,12 @@ from .models import (
|
||||||
Txt,
|
Txt,
|
||||||
DName,
|
DName,
|
||||||
Srv,
|
Srv,
|
||||||
|
SshFp,
|
||||||
Nas,
|
Nas,
|
||||||
Service,
|
Service,
|
||||||
OuverturePort,
|
OuverturePort,
|
||||||
Ipv6List,
|
Ipv6List,
|
||||||
OuverturePortList
|
OuverturePortList,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,6 +107,11 @@ class SrvAdmin(VersionAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SshFpAdmin(VersionAdmin):
|
||||||
|
""" Admin view of a SSHFP object """
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NasAdmin(VersionAdmin):
|
class NasAdmin(VersionAdmin):
|
||||||
""" Admin view of a Nas object """
|
""" Admin view of a Nas object """
|
||||||
pass
|
pass
|
||||||
|
@ -151,6 +157,7 @@ admin.site.register(Ns, NsAdmin)
|
||||||
admin.site.register(Txt, TxtAdmin)
|
admin.site.register(Txt, TxtAdmin)
|
||||||
admin.site.register(DName, DNameAdmin)
|
admin.site.register(DName, DNameAdmin)
|
||||||
admin.site.register(Srv, SrvAdmin)
|
admin.site.register(Srv, SrvAdmin)
|
||||||
|
admin.site.register(SshFp, SshFpAdmin)
|
||||||
admin.site.register(IpList, IpListAdmin)
|
admin.site.register(IpList, IpListAdmin)
|
||||||
admin.site.register(Interface, InterfaceAdmin)
|
admin.site.register(Interface, InterfaceAdmin)
|
||||||
admin.site.register(Domain, DomainAdmin)
|
admin.site.register(Domain, DomainAdmin)
|
||||||
|
|
|
@ -56,6 +56,7 @@ from .models import (
|
||||||
Service,
|
Service,
|
||||||
Vlan,
|
Vlan,
|
||||||
Srv,
|
Srv,
|
||||||
|
SshFp,
|
||||||
Nas,
|
Nas,
|
||||||
IpType,
|
IpType,
|
||||||
OuverturePortList,
|
OuverturePortList,
|
||||||
|
@ -595,3 +596,18 @@ class EditOuverturePortListForm(FormRevMixin, ModelForm):
|
||||||
prefix=prefix,
|
prefix=prefix,
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SshFpForm(FormRevMixin, ModelForm):
|
||||||
|
"""Edits a SSHFP record."""
|
||||||
|
class Meta:
|
||||||
|
model = SshFp
|
||||||
|
exclude = ('machine',)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||||
|
super(SshFpForm, self).__init__(
|
||||||
|
*args,
|
||||||
|
prefix=prefix,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
33
machines/migrations/0085_sshfingerprint.py
Normal file
33
machines/migrations/0085_sshfingerprint.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.7 on 2018-07-29 11:39
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import re2o.mixins
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('machines', '0084_dname'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SshFp',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('pub_key_entry', models.TextField(help_text='SSH public key', max_length=2048)),
|
||||||
|
('algo', models.CharField(choices=[('ssh-rsa', 'ssh-rsa'), ('ssh-ed25519', 'ssh-ed25519'), ('ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp256'), ('ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp384'), ('ecdsa-sha2-nistp521', 'ecdsa-sha2-nistp521')], max_length=32)),
|
||||||
|
('comment', models.CharField(blank=True, help_text='Comment', max_length=255, null=True)),
|
||||||
|
('machine', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='machines.Machine')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'SSHFP record',
|
||||||
|
'verbose_name_plural': 'SSHFP records',
|
||||||
|
'permissions': (('view_sshfp', 'Can see an SSHFP record'),),
|
||||||
|
},
|
||||||
|
bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model),
|
||||||
|
),
|
||||||
|
]
|
|
@ -32,6 +32,8 @@ import re
|
||||||
from ipaddress import IPv6Address
|
from ipaddress import IPv6Address
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from netaddr import mac_bare, EUI, IPSet, IPRange, IPNetwork, IPAddress
|
from netaddr import mac_bare, EUI, IPSet, IPRange, IPNetwork, IPAddress
|
||||||
|
import hashlib
|
||||||
|
import base64
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_save, post_delete
|
from django.db.models.signals import post_save, post_delete
|
||||||
|
@ -563,6 +565,12 @@ class Extension(RevMixin, AclMixin, models.Model):
|
||||||
entry += "@ IN AAAA " + str(self.origin_v6)
|
entry += "@ IN AAAA " + str(self.origin_v6)
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
|
def get_associated_sshfp_records(self):
|
||||||
|
from re2o.utils import all_active_assigned_interfaces
|
||||||
|
return (all_active_assigned_interfaces()
|
||||||
|
.filter(type__ip_type__extension=self)
|
||||||
|
.filter(machine__id__in=SshFp.objects.values('machine')))
|
||||||
|
|
||||||
def get_associated_a_records(self):
|
def get_associated_a_records(self):
|
||||||
from re2o.utils import all_active_assigned_interfaces
|
from re2o.utils import all_active_assigned_interfaces
|
||||||
return (all_active_assigned_interfaces()
|
return (all_active_assigned_interfaces()
|
||||||
|
@ -755,6 +763,73 @@ class Srv(RevMixin, AclMixin, models.Model):
|
||||||
str(self.port) + ' ' + str(self.target) + '.'
|
str(self.port) + ' ' + str(self.target) + '.'
|
||||||
|
|
||||||
|
|
||||||
|
class SshFp(RevMixin, AclMixin, models.Model):
|
||||||
|
"""A fingerprint of an SSH public key"""
|
||||||
|
|
||||||
|
ALGO = (
|
||||||
|
("ssh-rsa", "ssh-rsa"),
|
||||||
|
("ssh-ed25519", "ssh-ed25519"),
|
||||||
|
("ecdsa-sha2-nistp256", "ecdsa-sha2-nistp256"),
|
||||||
|
("ecdsa-sha2-nistp384", "ecdsa-sha2-nistp384"),
|
||||||
|
("ecdsa-sha2-nistp521", "ecdsa-sha2-nistp521"),
|
||||||
|
)
|
||||||
|
|
||||||
|
machine = models.ForeignKey('Machine', on_delete=models.CASCADE)
|
||||||
|
pub_key_entry = models.TextField(
|
||||||
|
help_text="SSH public key",
|
||||||
|
max_length=2048
|
||||||
|
)
|
||||||
|
algo = models.CharField(
|
||||||
|
choices=ALGO,
|
||||||
|
max_length=32
|
||||||
|
)
|
||||||
|
comment = models.CharField(
|
||||||
|
help_text="Comment",
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
blank=True
|
||||||
|
)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def algo_id(self):
|
||||||
|
"""Return the id of the algorithm for this key"""
|
||||||
|
if "ecdsa" in self.algo:
|
||||||
|
return 3
|
||||||
|
elif "rsa" in self.algo:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def hash(self):
|
||||||
|
"""Return the hashess for the pub key with correct id
|
||||||
|
cf RFC, 1 is sha1 , 2 sha256"""
|
||||||
|
return {
|
||||||
|
"1" : hashlib.sha1(base64.b64decode(self.pub_key_entry)).hexdigest(),
|
||||||
|
"2" : hashlib.sha256(base64.b64decode(self.pub_key_entry)).hexdigest(),
|
||||||
|
}
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
permissions = (
|
||||||
|
("view_sshfp", "Can see an SSHFP record"),
|
||||||
|
)
|
||||||
|
verbose_name = "SSHFP record"
|
||||||
|
verbose_name_plural = "SSHFP records"
|
||||||
|
|
||||||
|
def can_view(self, user_request, *_args, **_kwargs):
|
||||||
|
return self.machine.can_view(user_request, *_args, **_kwargs)
|
||||||
|
|
||||||
|
def can_edit(self, user_request, *args, **kwargs):
|
||||||
|
return self.machine.can_edit(user_request, *args, **kwargs)
|
||||||
|
|
||||||
|
def can_delete(self, user_request, *args, **kwargs):
|
||||||
|
return self.machine.can_delete(user_request, *args, **kwargs)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.algo) + ' ' + str(self.comment)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
|
||||||
""" Une interface. Objet clef de l'application machine :
|
""" Une interface. Objet clef de l'application machine :
|
||||||
- une address mac unique. Possibilité de la rendre unique avec le
|
- une address mac unique. Possibilité de la rendre unique avec le
|
||||||
|
|
|
@ -119,6 +119,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% acl_end %}
|
{% acl_end %}
|
||||||
|
{% can_create SshFp interface.machine.id %}
|
||||||
|
<li>
|
||||||
|
<a href="{% url 'machines:index-sshfp' interface.machine.id %}">
|
||||||
|
<i class="fa fa-edit"></i> Manage the SSH fingerprints
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% acl_end %}
|
||||||
{% can_create OuverturePortList %}
|
{% can_create OuverturePortList %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'machines:port-config' interface.id%}">
|
<a href="{% url 'machines:port-config' interface.id%}">
|
||||||
|
|
54
machines/templates/machines/aff_sshfp.html
Normal file
54
machines/templates/machines/aff_sshfp.html
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
{% comment %}
|
||||||
|
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||||
|
se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
|
quelques clics.
|
||||||
|
|
||||||
|
Copyright © 2018 Gabriel Détraz
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% load acl %}
|
||||||
|
{% load logs_extra %}
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped long_text">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="long_text">SSH public key</th>
|
||||||
|
<th>Algorithm used</th>
|
||||||
|
<th>Comment</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% for sshfp in sshfp_list %}
|
||||||
|
<tr>
|
||||||
|
<td class="long_text">{{ sshfp.pub_key_entry }}</td>
|
||||||
|
<td>{{ sshfp.algo }}</td>
|
||||||
|
<td>{{ sshfp.comment }}</td>
|
||||||
|
<td class="text-right">
|
||||||
|
{% can_edit sshfp %}
|
||||||
|
{% include 'buttons/edit.html' with href='machines:edit-sshfp' id=sshfp.id %}
|
||||||
|
{% acl_end %}
|
||||||
|
{% can_delete sshfp %}
|
||||||
|
{% include 'buttons/suppr.html' with href='machines:del-sshfp' id=sshfp.id %}
|
||||||
|
{% acl_end %}
|
||||||
|
{% history_button sshfp %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
38
machines/templates/machines/index_sshfp.html
Normal file
38
machines/templates/machines/index_sshfp.html
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
{% extends "machines/sidebar.html" %}
|
||||||
|
{% comment %}
|
||||||
|
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
|
||||||
|
se veut agnostique au réseau considéré, de manière à être installable en
|
||||||
|
quelques clics.
|
||||||
|
|
||||||
|
Copyright © 2018 Gabriel Détraz
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% load acl %}
|
||||||
|
|
||||||
|
{% block title %}Machines{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2>SSH fingerprints</h2>
|
||||||
|
{% can_create SshFp machine_id %}
|
||||||
|
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:new-sshfp' machine_id %}">
|
||||||
|
<i class="fa fa-plus"></i> Add an SSH fingerprint
|
||||||
|
</a>
|
||||||
|
{% acl_end %}
|
||||||
|
{% include "machines/aff_sshfp.html" with sshfp_list=sshfp_list %}
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -69,6 +69,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
{% if serviceform %}
|
{% if serviceform %}
|
||||||
{% bootstrap_form_errors serviceform %}
|
{% bootstrap_form_errors serviceform %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if sshfpform %}
|
||||||
|
{% bootstrap_form_errors sshfpform %}
|
||||||
|
{% endif %}
|
||||||
{% if vlanform %}
|
{% if vlanform %}
|
||||||
{% bootstrap_form_errors vlanform %}
|
{% bootstrap_form_errors vlanform %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -133,6 +136,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
<h3>Enregistrement SRV</h3>
|
<h3>Enregistrement SRV</h3>
|
||||||
{% massive_bootstrap_form srvform 'target' %}
|
{% massive_bootstrap_form srvform 'target' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if sshfpform %}
|
||||||
|
<h3>SSHFP record</h3>
|
||||||
|
{% bootstrap_form sshfpform %}
|
||||||
|
{% endif %}
|
||||||
{% if aliasform %}
|
{% if aliasform %}
|
||||||
<h3>Alias</h3>
|
<h3>Alias</h3>
|
||||||
{% bootstrap_form aliasform %}
|
{% bootstrap_form aliasform %}
|
||||||
|
|
|
@ -82,6 +82,18 @@ urlpatterns = [
|
||||||
url(r'^add_srv/$', views.add_srv, name='add-srv'),
|
url(r'^add_srv/$', views.add_srv, name='add-srv'),
|
||||||
url(r'^edit_srv/(?P<srvid>[0-9]+)$', views.edit_srv, name='edit-srv'),
|
url(r'^edit_srv/(?P<srvid>[0-9]+)$', views.edit_srv, name='edit-srv'),
|
||||||
url(r'^del_srv/$', views.del_srv, name='del-srv'),
|
url(r'^del_srv/$', views.del_srv, name='del-srv'),
|
||||||
|
url(r'^new_sshfp/(?P<machineid>[0-9]+)$',
|
||||||
|
views.new_sshfp,
|
||||||
|
name='new-sshfp'),
|
||||||
|
url(r'^edit_sshfp/(?P<sshfpid>[0-9]+)$',
|
||||||
|
views.edit_sshfp,
|
||||||
|
name='edit-sshfp'),
|
||||||
|
url(r'^del_sshfp/(?P<sshfpid>[0-9]+)$',
|
||||||
|
views.del_sshfp,
|
||||||
|
name='del-sshfp'),
|
||||||
|
url(r'^index_sshfp/(?P<machineid>[0-9]+)$',
|
||||||
|
views.index_sshfp,
|
||||||
|
name='index-sshfp'),
|
||||||
url(r'^index_extension/$', views.index_extension, name='index-extension'),
|
url(r'^index_extension/$', views.index_extension, name='index-extension'),
|
||||||
url(r'^add_alias/(?P<interfaceid>[0-9]+)$',
|
url(r'^add_alias/(?P<interfaceid>[0-9]+)$',
|
||||||
views.add_alias,
|
views.add_alias,
|
||||||
|
|
|
@ -54,6 +54,7 @@ from re2o.utils import (
|
||||||
from re2o.acl import (
|
from re2o.acl import (
|
||||||
can_create,
|
can_create,
|
||||||
can_edit,
|
can_edit,
|
||||||
|
can_view,
|
||||||
can_delete,
|
can_delete,
|
||||||
can_view_all,
|
can_view_all,
|
||||||
can_delete_set,
|
can_delete_set,
|
||||||
|
@ -102,13 +103,14 @@ from .forms import (
|
||||||
DelVlanForm,
|
DelVlanForm,
|
||||||
ServiceForm,
|
ServiceForm,
|
||||||
DelServiceForm,
|
DelServiceForm,
|
||||||
|
SshFpForm,
|
||||||
NasForm,
|
NasForm,
|
||||||
DelNasForm,
|
DelNasForm,
|
||||||
SrvForm,
|
SrvForm,
|
||||||
DelSrvForm,
|
DelSrvForm,
|
||||||
Ipv6ListForm,
|
Ipv6ListForm,
|
||||||
EditOuverturePortListForm,
|
EditOuverturePortListForm,
|
||||||
EditOuverturePortConfigForm
|
EditOuverturePortConfigForm,
|
||||||
)
|
)
|
||||||
from .models import (
|
from .models import (
|
||||||
IpType,
|
IpType,
|
||||||
|
@ -127,6 +129,7 @@ from .models import (
|
||||||
Txt,
|
Txt,
|
||||||
DName,
|
DName,
|
||||||
Srv,
|
Srv,
|
||||||
|
SshFp,
|
||||||
OuverturePortList,
|
OuverturePortList,
|
||||||
OuverturePort,
|
OuverturePort,
|
||||||
Ipv6List,
|
Ipv6List,
|
||||||
|
@ -460,6 +463,72 @@ def del_ipv6list(request, ipv6list, **_kwargs):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_create(SshFp)
|
||||||
|
@can_edit(Machine)
|
||||||
|
def new_sshfp(request, machine, **_kwargs):
|
||||||
|
"""Creates an SSHFP record associated with a machine"""
|
||||||
|
sshfp_instance = SshFp(machine=machine)
|
||||||
|
sshfp = SshFpForm(
|
||||||
|
request.POST or None,
|
||||||
|
instance=sshfp_instance
|
||||||
|
)
|
||||||
|
if sshfp.is_valid():
|
||||||
|
sshfp.save()
|
||||||
|
messages.success(request, "The SSHFP record was added")
|
||||||
|
return redirect(reverse(
|
||||||
|
'machines:index-sshfp',
|
||||||
|
kwargs={'machineid': str(machine.id)}
|
||||||
|
))
|
||||||
|
return form(
|
||||||
|
{'sshfpform': sshfp, 'action_name': 'Create'},
|
||||||
|
'machines/machine.html',
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_edit(SshFp)
|
||||||
|
def edit_sshfp(request, sshfp_instance, **_kwargs):
|
||||||
|
"""Edits an SSHFP record"""
|
||||||
|
sshfp = SshFpForm(
|
||||||
|
request.POST or None,
|
||||||
|
instance=sshfp_instance
|
||||||
|
)
|
||||||
|
if sshfp.is_valid():
|
||||||
|
if sshfp.changed_data:
|
||||||
|
sshfp.save()
|
||||||
|
messages.success(request, "The SSHFP record was edited")
|
||||||
|
return redirect(reverse(
|
||||||
|
'machines:index-sshfp',
|
||||||
|
kwargs={'machineid': str(sshfp_instance.machine.id)}
|
||||||
|
))
|
||||||
|
return form(
|
||||||
|
{'sshfpform': sshfp, 'action_name': 'Edit'},
|
||||||
|
'machines/machine.html',
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_delete(SshFp)
|
||||||
|
def del_sshfp(request, sshfp, **_kwargs):
|
||||||
|
"""Deletes an SSHFP record"""
|
||||||
|
if request.method == "POST":
|
||||||
|
machineid = sshfp.machine.id
|
||||||
|
sshfp.delete()
|
||||||
|
messages.success(request, "The SSHFP record was deleted")
|
||||||
|
return redirect(reverse(
|
||||||
|
'machines:index-sshfp',
|
||||||
|
kwargs={'machineid': str(machineid)}
|
||||||
|
))
|
||||||
|
return form(
|
||||||
|
{'objet': sshfp, 'objet_name': 'sshfp'},
|
||||||
|
'machines/delete.html',
|
||||||
|
request
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@can_create(IpType)
|
@can_create(IpType)
|
||||||
def add_iptype(request):
|
def add_iptype(request):
|
||||||
|
@ -1388,7 +1457,20 @@ def index_alias(request, interface, interfaceid):
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@can_edit(Interface)
|
@can_view(Machine)
|
||||||
|
def index_sshfp(request, machine, machineid):
|
||||||
|
"""View used to display the list of existing SSHFP records associated
|
||||||
|
with a machine"""
|
||||||
|
sshfp_list = SshFp.objects.filter(machine=machine)
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
'machines/index_sshfp.html',
|
||||||
|
{'sshfp_list': sshfp_list, 'machine_id': machineid}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@can_view_all(Interface)
|
||||||
def index_ipv6(request, interface, interfaceid):
|
def index_ipv6(request, interface, interfaceid):
|
||||||
""" View used to display the list of existing IPv6 of an interface """
|
""" View used to display the list of existing IPv6 of an interface """
|
||||||
ipv6_list = Ipv6List.objects.filter(interface=interface)
|
ipv6_list = Ipv6List.objects.filter(interface=interface)
|
||||||
|
|
|
@ -113,4 +113,19 @@ footer a {
|
||||||
.modal-dialog {
|
.modal-dialog {
|
||||||
width: 1000px
|
width: 1000px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For tables with long text in cells */
|
||||||
|
|
||||||
|
.table.long_text{
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.long_text{
|
||||||
|
word-wrap: break-word;
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
th.long_text{
|
||||||
|
width: 60%;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue