Browse Source

fixed ntp bugs, CRUD dns resolver

Roberto Berto 4 năm trước cách đây
mục cha
commit
4df0befeef

+ 15 - 7
README.md

@@ -3,9 +3,16 @@
 </p>
 
 
-VyControl is frontend interface to manage a single or multiple VyoS servers. 
+VyControl is web frontend interface to manage a single or multiple VyoS servers. It is developed in Python/Django using VyOS API.
 
-Datacenters can to offer their customers (with users, groups and granular control) firewall and router as a service.
+
+# Use Cases:
+
+VyControl can be a web gui for one single VyOS installation, but it requires a separeted webserver from VyOS to a single network admin user or a TI department from a company
+
+VyControl can be a web gui for multiple VyOS installation in a same enterprise, to a single network admin user or a TI department from a company
+
+VyControl can be a web gui for multiple VyOS installation in a datacenter. Each of datacenter customer have a VyControl user to manage their own VyOSes (each user can manage several VyOS).
 
 
 # Main links
@@ -94,13 +101,14 @@ EMAIL_USE_TLS = True
 - [ ] Discussion VyControl at VyOS forum https://forum.vyos.io/t/vycenter-alpha-stage-announcement-vyos-web-interface/5221/4
 
 # changelog
-- [x] change email/change password user profile
-- [x] edit/add/delete interfaces
+- [x] create/read/update/delete DNS Resolver
+- [x] create/read/update/delete email/password in user profile
+- [x] create/read/update/delete interfaces and vlans
 - [x] lost password recovery using external SMTP server
-- [x] NTP servers add/list/delete
-- [x] zone based firewall
+- [x] create/read/update/delete NTP Serrves
+- [x] create/read/update/delete zone based firewall
 - [x] improve firewall UI and error returns to end users
-- [x] working firewall without zones 
+- [x] working firewall
 - [x] version created to start project framework, organize permission systems and concept test with some firewall and interface functions and statics routes
 
 # roadmap

+ 4 - 1
vycontrol/config/templates/config/groups_list.html

@@ -12,7 +12,10 @@
 
 {% block content %}
 
-
+<p class="submenu1">
+    {% if is_superuser %}<a href="{% url 'config:group-add' %}">Add new group</a>{% endif %}
+</p>
+<p class="submenu2"></p>
 
 
 

+ 1 - 1
vycontrol/config/templates/config/instance_add.html

@@ -10,7 +10,7 @@
 {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
 
 
-<p class="margin-topbottom">To add a new VyOS <a href="https://docs.vyos.io/en/latest/appendix/http-api.html" target="_blank">read documentation</a>.</p>
+<p class="margin-topbottom">To add a new VyOS <a href="https://docs.vyos.io/" target="_blank">read documentation</a>.</p>
 
 <form action="{% url 'config:instance-add' %}" method="post">
 

+ 6 - 0
vycontrol/config/templates/config/instances.html

@@ -12,6 +12,12 @@
 
 {% block content %}
 
+<p class="submenu1">
+    {% if is_superuser %}<a href="{% url 'config:instance-add' %}">Add new instance</a>{% endif %}
+</p>
+<p class="submenu2"></p>
+
+
 {% if instances %}
 
     <table border="1" width="100%">

+ 4 - 1
vycontrol/config/templates/config/users_list.html

@@ -14,7 +14,10 @@
 {% block content %}
 
 
-
+<p class="submenu1">
+    {% if is_superuser %}<a href="{% url 'config:user-add' %}">Add new user</a>{% endif %}
+</p>
+<p class="submenu2"></p>
 
 
 

+ 0 - 0
vycontrol/dnsresolver/__init__.py


+ 3 - 0
vycontrol/dnsresolver/admin.py

@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.

+ 4 - 0
vycontrol/dnsresolver/apps.py

@@ -0,0 +1,4 @@
+from django.apps import AppConfig
+
+class DnsresolverConfig(AppConfig):
+    name = 'dnsresolver'

+ 0 - 0
vycontrol/dnsresolver/migrations/__init__.py


+ 3 - 0
vycontrol/dnsresolver/models.py

@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.

+ 34 - 0
vycontrol/dnsresolver/templates/dnsresolver/add.html

@@ -0,0 +1,34 @@
+{% extends "base.html" %}
+
+{% block header_title %}dnsresolver{% endblock %}
+{% block section_title %}dnsresolver{% endblock %}
+
+{% block debug %}
+{% endblock %}
+
+{% block content %}
+
+<p class="submenu1">
+    <a href="{% url 'dnsresolver:dnsresolver-list' %}">List dnsresolver servers</a>
+</p>
+<p class="submenu2">
+    
+</p>
+
+
+<h2>Add new dnsresolver server</h2>
+
+<form action="{% url 'dnsresolver:dnsresolver-add'  %}" method="post">
+    {% csrf_token %}
+    
+    <p>
+        <label for="server">server</label><br>
+        <input type="text" name="server" id="server" value="{{ server }}" size="30">
+    </p>
+
+    <input type="submit" value="Add dnsresolver Server">
+</form>
+
+
+
+{% endblock %}

+ 43 - 0
vycontrol/dnsresolver/templates/dnsresolver/list.html

@@ -0,0 +1,43 @@
+{% extends "base.html" %}
+
+{% block header_title %}dnsresolver{% endblock %}
+{% block section_title %}dnsresolver{% endblock %}
+
+{% block debug %}
+{% endblock %}
+
+{% block content %}
+
+<p class="submenu1">
+    <a href="{% url 'dnsresolver:dnsresolver-add' %}">Add new dnsresolver server</a>
+</p>
+<p class="submenu2">
+    
+</p>
+
+
+{% if dnsresolver_servers %}
+
+    <table border="1" width="100%">
+    <tr>
+        <th>server</th>
+        <th>action</th>
+    </tr>
+
+    {% for server in dnsresolver_servers %}
+    <tr>
+        <td>{{ server }}</td>
+        <td>
+            <a href="{% url 'dnsresolver:dnsresolver-remove' server=server %}">delete</a></td>
+        </td>
+    </tr>
+
+    {% endfor %}
+
+    </table>   
+{% else %}
+<p>No dnsresolver Server defined.</p>
+{% endif %}
+
+{% endblock %}
+

+ 3 - 0
vycontrol/dnsresolver/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 14 - 0
vycontrol/dnsresolver/urls.py

@@ -0,0 +1,14 @@
+from django.urls import path
+
+from . import views
+
+app_name = 'dnsresolver'
+
+
+urlpatterns = [
+    path('', views.index, name='dnsresolver-list'),
+    path('add', views.add, name='dnsresolver-add'),
+    path('remove/<str:server>', views.remove, name='dnsresolver-remove'),
+]
+
+

+ 78 - 0
vycontrol/dnsresolver/views.py

@@ -0,0 +1,78 @@
+from django.shortcuts import render
+from django.http import HttpResponse
+from django.template import loader
+from django.shortcuts import redirect
+from django.conf import settings
+from django.urls import reverse
+from django.contrib.auth.decorators import login_required
+
+import vyos
+import vycontrol_vyos_api as vapi
+import vycontrol_messages as vmsg
+import perms
+import validators
+
+@login_required
+def index(request):
+    all_instances = vyos.instance_getall()
+    hostname_default = vyos.get_hostname_prefered(request)
+    is_superuser = perms.get_is_superuser(request.user)
+
+    dnsresolver_srv = vapi.get_dnsresolver(hostname_default)
+    dnsresolver_servers = {}
+    if dnsresolver_srv.success:
+        if dnsresolver_srv.data['name-server'] != None:
+            dnsresolver_servers = dnsresolver_srv.data['name-server']
+
+    context = {
+        'instances':                                all_instances,
+        'hostname_default':                         hostname_default,
+        'dnsresolver_servers' :                     dnsresolver_servers,
+        'is_superuser' :                            is_superuser,
+    }
+
+    return render(request, 'dnsresolver/list.html', context)
+
+
+@login_required
+def add(request):
+    msg = vmsg.msg()
+
+    all_instances = vyos.instance_getall()
+    hostname_default = vyos.get_hostname_prefered(request)
+    is_superuser = perms.get_is_superuser(request.user)
+
+    if 'server' in request.POST:
+        if validators.ipv6(request.POST['server'].strip()) or validators.ipv4(request.POST['server'].strip()):
+            v = vapi.set_dnsresolver(hostname_default, request.POST['server'].strip())
+            if v.success == False: 
+                msg.add_error("dnsresolver server add fail - " + v.reason)
+            else:
+                msg.add_success("dnsresolver server added")
+        else:
+            msg.add_error("dnsresolver server add fail - insert only IPv4 or IPv6")
+
+    context = {
+        'instances':                                all_instances,
+        'hostname_default':                         hostname_default,
+        'is_superuser' :                            is_superuser,
+        'msg' :                                     msg.get_all(),
+    }
+
+    return render(request, 'dnsresolver/add.html', context)
+
+
+@login_required
+def remove(request, server):
+    hostname_default = vyos.get_hostname_prefered(request)
+
+    dnsresolver_srv = vapi.get_dnsresolver(hostname_default)
+    if len(dnsresolver_srv.data['name-server']) == 0:
+        return redirect('dnsresolver:dnsresolver-list')
+
+    if dnsresolver_srv.success:
+        if 'name-server' in dnsresolver_srv.data:
+            if validators.ipv6(server.strip()) or validators.ipv4(server.strip()):
+                v = vapi.delete_dnsresolver(hostname_default, server.strip())
+
+    return redirect('dnsresolver:dnsresolver-list')

+ 16 - 12
vycontrol/ntp/views.py

@@ -10,7 +10,7 @@ import vyos
 import vycontrol_vyos_api as vapi
 import vycontrol_messages as vmsg
 import perms
-
+import validators
 
 @login_required
 def index(request):
@@ -43,11 +43,14 @@ def add(request):
     is_superuser = perms.get_is_superuser(request.user)
 
     if 'server' in request.POST:
-        v = vapi.set_ntp(hostname_default, request.POST['server'])
-        if v.success == False: 
-            msg.add_error("NTP server add fail - " + v.reason)
+        if validators.ipv6(request.POST['server'].strip()) or validators.ipv4(request.POST['server'].strip()) or validators.domain(request.POST['server'].strip()):
+            v = vapi.set_ntp(hostname_default, request.POST['server'].strip())
+            if v.success == False: 
+                msg.add_error("NTP server add fail - " + v.reason)
+            else:
+                msg.add_success("NTP server added")
         else:
-            msg.add_success("NTP server added")
+            msg.add_error("ntp server add fail - insert only domains or IPv4 or IPv6")
 
     context = {
         'instances':                                all_instances,
@@ -63,13 +66,14 @@ def add(request):
 def remove(request, server):
     hostname_default = vyos.get_hostname_prefered(request)
 
-    ntp_srv = vapi.get_ntp(hostname_default)
-    ntp_servers = {}
-    if ntp_srv.success:
-        if ntp_srv.data['server'] != None:
-            ntp_servers = ntp_srv.data['server']
+    ntp_servers = vapi.get_ntp(hostname_default)
+
+    if len(ntp_servers.data['name-server']) == 0:
+        return redirect('ntp:ntp-list')
 
-    if server in ntp_servers:
-        return1 = vapi.delete_ntp(hostname_default, server)
+    if ntp_servers.success:
+        if 'server' in ntp_servers.data:
+            if validators.ipv6(server.strip()) or validators.ipv4(server.strip()) or validators.domain(server.strip()):
+                v = vapi.delete_ntp(hostname_default, server.strip())
 
     return redirect('ntp:ntp-list')

+ 12 - 23
vycontrol/vycontrol/settings/base.py

@@ -14,26 +14,18 @@ import os
 from pathlib import Path
 
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-#VYCONTROL_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 BASE_DIR = str(Path(__file__).resolve().parents[2])
 
-
-
-
 # Quick-start development settings - unsuitable for production
 # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
 
-
-
 SESSION_EXPIRE_AT_BROWSER_CLOSE = True
 SESSION_COOKIE_AGE = 60 * 60 # 60 minutes
 
 # put all your hosts here
 ALLOWED_HOSTS = ['127.0.0.1']
 
-
 # Application definition
-
 INSTALLED_APPS = [
  
     'django.contrib.contenttypes',
@@ -41,25 +33,24 @@ INSTALLED_APPS = [
     'django.contrib.messages',
     'django.contrib.staticfiles',
 
-    #'vauth.apps.VauthConfig',
     'accounts.apps.AccountsConfig',
-
     'config.apps.ConfigConfig',
-
     'interface.apps.InterfaceConfig',
     'firewall.apps.FirewallConfig',
     'static.apps.StaticConfig',
-    'arp.apps.ArpConfig',
-    'bgp.apps.BgpConfig',
-    'dhcp.apps.DhcpConfig',
-    'ipsec.apps.IpsecConfig',
-    'nat.apps.NatConfig',
     'ntp.apps.NtpConfig',
-    'qos.apps.QosConfig',
-    'openvpn.apps.OpenvpnConfig',
-    'ospf.apps.OspfConfig',
-    'ssh.apps.SshConfig',
-    'wanlb.apps.WanlbConfig',
+    'dnsresolver.apps.DnsresolverConfig',
+
+    #'arp.apps.ArpConfig',
+    #'bgp.apps.BgpConfig',
+    #'dhcp.apps.DhcpConfig',
+    #'ipsec.apps.IpsecConfig',
+    #'nat.apps.NatConfig',
+    #'qos.apps.QosConfig',
+    #'openvpn.apps.OpenvpnConfig',
+    #'ospf.apps.OspfConfig',
+    #'ssh.apps.SshConfig',
+    #'wanlb.apps.WanlbConfig',
 
     'django.contrib.auth',
     'django.contrib.admin',
@@ -175,5 +166,3 @@ STATICFILES_DIRS = [
     BASE_DIR + '/s/'
 ]
 STATIC_URL = '/s/'
-
-

+ 9 - 12
vycontrol/vycontrol/templates/base.html

@@ -64,26 +64,23 @@
       </p>
 
 
+    <h2>Router</h2>
 
-    <h2>Manage VyOS</h2>
     <ul>
     <li><a href="{% url 'interface:interface-list' %}">Interfaces</a></li>
     <li><a href="{% url 'firewall:firewall-list' %}">Firewall</a></li>
-    <li><a href="{% url 'static:static-list' %}">Static Routing</a></li>
+    <li><a href="{% url 'static:static-list' %}">Static Routes</a></li>
+    <li><a href="{% url 'dnsresolver:dnsresolver-list' %}">DNS resolver</a></li>
     <li><a href="{% url 'ntp:ntp-list' %}">NTP</a></li>
+    </ul>
+    
 
 
-  </ul>
-
-
-    <h2>Manage VyControl</h2>
+    <h2>Configuration</h2>
     <ul>
-    {% if is_superuser %}<li><a href="{% url 'config:instance-add' %}">Add new instance</a></li>{% endif %}
-    <li><a href="{% url 'config:instances' %}">List instances</a></li>
-    {% if is_superuser %}<li><a href="{% url 'config:users-list' %}">List users</a></li>{% endif %}
-    {% if is_superuser %}<li><a href="{% url 'config:user-add' %}">Add new user</a></li>{% endif %}
-    {% if is_superuser %}<li><a href="{% url 'config:groups-list' %}">List groups</a></li>{% endif %}
-    {% if is_superuser %}<li><a href="{% url 'config:group-add' %}">Add new group</a></li>{% endif %}
+    <li><a href="{% url 'config:instances' %}">Instances</a></li>
+    {% if is_superuser %}<li><a href="{% url 'config:users-list' %}">Users</a></li>{% endif %}
+    {% if is_superuser %}<li><a href="{% url 'config:groups-list' %}">Groups</a></li>{% endif %}
 
   </ul>
 

+ 7 - 11
vycontrol/vycontrol/urls.py

@@ -38,30 +38,26 @@ urlpatterns = [
     path('accounts/', include('accounts.urls')),
     path('config/', include('config.urls')),
     path('dashboard/', include('dashboard.urls')),
-    #path('', views.vycontrol_login, name='vycontrol-login'),
     path('admin/', admin.site.urls, name="django-admin"),
-    #path('change-password/', auth_views.PasswordChangeView.as_view()),
     path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name="accounts-login"),
     path('logout/', auth_views.LogoutView.as_view(template_name='accounts/logout.html'), name="accounts-logout"),
     path('password_reset/', auth_views.PasswordResetView.as_view(template_name = 'accounts/password_reset.html'), name ='reset_password'),
     path('password_reset_sent/', auth_views.PasswordResetDoneView.as_view(template_name = 'accounts/password_reset_sent.html'), name ='password_reset_done'),
     path('password_reset_token/<uidb64>/<token>', auth_views.PasswordResetConfirmView.as_view(template_name = 'accounts/password_reset_token.html'), name ='password_reset_confirm'),
     path('password_reset_complete/', auth_views.PasswordResetCompleteView.as_view(template_name = 'accounts/password_reset_complete.html'), name ='password_reset_complete'),
-
-
-
+    path('static/', include('static.urls')),
     path('interface/', include('interface.urls')),
-    #path('arp/', include('arp.urls')),
-    #path('bgp/', include('bgp.urls')),
-    #path('dhcp/', include('dhcp.urls')),
     path('firewall/', include('firewall.urls')),
+    path('ntp/', include('ntp.urls')),
+    path('dnsresolver/', include('dnsresolver.urls')),
     #path('ipsec/', include('ipsec.urls')),
     #path('nat/', include('nat.urls')),
-    path('ntp/', include('ntp.urls')),
     #path('openvpn/', include('openvpn.urls')),
     #path('ospf/', include('ospf.urls')),
     #path('qos/', include('qos.urls')),
-    #path('ssh/', include('ssh.urls')),
-    path('static/', include('static.urls')),
+    #path('ssh/', include('ssh.urls')),  
+    #path('arp/', include('arp.urls')),
+    #path('bgp/', include('bgp.urls')),
+    #path('dhcp/', include('dhcp.urls')),
     #path('wanlb/', include('wanlb.urls')),
 ]

+ 38 - 0
vycontrol/vycontrol_vyos_api.py

@@ -531,6 +531,35 @@ def delete_interface_firewall_zone_rule_firewall(hostname, dstzone, srczone, fir
     )
     return v  
 
+def get_dnsresolver(hostname):
+    v = vapilib.api (
+        hostname=   hostname,
+        api =       "get",
+        op =        "showConfig",
+        cmd =       ["system","name-server"],
+        description = "get_dnsresolver",
+    )
+    return v
+    
+def set_dnsresolver(hostname, server):
+    v = vapilib.api (
+        hostname=   hostname,
+        api =       "post",
+        op =        "set",
+        cmd =       ["system","name-server",server],
+        description = "set_dnsresolverntp",
+    )
+    return v  
+def delete_dnsresolver(hostname, server):
+    v = vapilib.api (
+        hostname=   hostname,
+        api =       "post",
+        op =        "delete",
+        cmd =       ["system","name-server",server],
+        description = "delete_dnsresolver",
+    )
+    return v
+
 def get_ntp(hostname):
     v = vapilib.api (
         hostname=   hostname,
@@ -541,6 +570,15 @@ def get_ntp(hostname):
     )
     return v
 
+def set_ntp(hostname, server):
+    v = vapilib.api (
+        hostname=   hostname,
+        api =       "post",
+        op =        "set",
+        cmd =       ["system","ntp","server",server],
+        description = "set_ntp",
+    )
+    return v  
 def delete_ntp(hostname, server):
     v = vapilib.api (
         hostname=   hostname,