Portmanager
Django-based web application for centralized configuration of network device access ports.
1 Background
Purpose of this project is to create web tool for viewing/configuration of basic parameters of access ports on network devices (description, VLAN, status, portsec, PoE output, connected MAC addresses), that could serve people with some basic knowledge of computer networks to manage their network devices without using CLI of various device manufacturers. System is currently is able to manage selected devices manufactured by Cisco, HP and Juniper.
2 Install
2.1 Prepare the environment
Application itself is running inside dockerized environment, but you need to complete few steps to get it running.
2.1.1 Docker
- Install Docker. See installation instructions at https://docs.docker.com.
2.1.2 Docker Compose
- Install Docker Compose, see installation instructions at https://docs.docker.com/compose/install/.
2.1.3 TFTP server
- Needed for applying default configurations into Cisco devices.
- Install TFTP on same server where you want to deploy the application.
- Default location for files is
/srv/tftp
. You can change it insideDockerfile
and docker-compose*.yml
files if you prefer different location.
Configure TFTP server for file creation with TFTP_OPTIONS
as you can see in the example below, allow traffic to the
server and test if it runs correctly.
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--ipv4 --secure --create"
2.1.4 Webserver
- You can run the application behind webserver of your choice, application is exposed on
localhost:8888
. - If you use
production-compose.yml
application will expectHTTP_X_REMOTE_USER
header passed from the webserver (used for passing authenticated user ID from SSO). - Feel free to modify
webapp/switches/users.py
to match it to your user authentication. - To test logging in of different users, use
production-compose.yml
and change theDEBUG_USR
insideconfig/environment/development.env
2.2 Build the containers
Automated build and deployment process is described in .gitlab-ci.yml
file. Lets go through the file structure and
process of manual build:
2.2.1 Base image
Dockerfile_base
builds base image with prerequisites that don't often change, like Python,
NetSNMP with Python bindings, vim, etc. so usually, you run this build phase only if you need to update some of these packages.
2.2.2 Main image
The main Dockerfile
of the project is used to do the best. It creates necessary directory structure, downloads Python packages
and copies code of the application.
2.2.3 Docker Compose
- For production/staging deployments, use
production-compose.yml
file, it fetches the already built image from GitLab and redis image from the Docker Hub. Usedocker login
before trying to pull the remote images. - For development, use
devel-compose.yml
file, it builds an image locally and also maps code from a local machine (don't forget to modify file paths to match them to your devel environment). - Container for main appication consumes approx. 1.12 GB, Redis without data approx. 104MB. It should not be a problem, but check if you have enough disk space for that.
2.2.4 Docker & Docker Compose examples
$ docker-compose -f PathToYmlFile build # build images with specified *.yml file
$ docker-compose up [-d] # run in foregroud/background
$ docker-compose logs --follow # see logs for debugging purposes
$ docker-compose down # stop and remove containers
$ docker image prune -a # empty space by removing all images not referenced by any container
$ docker exec -it "container" /bin/bash # execute commands inside
3 Configuration
3.1 Project structure
├── config # files needed for configuration
├── webapp # code of the application
├── devel-compose.yml # docker-compose setup with container orchestration instructions for development
├── Dockerfile # docker setup for building the webapp
├── Dockerfile # base docker setup of basic container with dependencies to speedup build
├── LICENSE # license for this project
├── production-compose.yml # docker-compose setup with container orchestration instructions for prod environment
└── README.md # this file
3.2 Database
Application uses sqlite3 database, for production-compose.yml
it creates var/data/data.db
on
host system. You can change the path in yml
file and other settings in webapp/portmanager/settings.py
:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': '/srv/data/data.db',
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '',
'PORT': '',
}
}
Migrations are not automated for now, so you have to run them manually by following commands:
$ python manage.py makemigrations
$ python manage.py migrate
3.3 Network traffic between the system and devices
To ensure that system will, you need to allow traffic between the system and your network devices. For basic functions, allow SNMP and configure it on your network devices.
Following sections will go through the special needs for different brands caused by different behaviour, security policies and implementation of SNMP:
3.3.1 Cisco
- Uses SNMP for the most of the actions.
- It is not possible to set everything via SNMP, Cisco does not allow setting all PortSec parameters via SNMPSet. To bypass that, applying default port configuration is done by getting whole running-config via TFTP, making changes locally and then uploading changed config back.
- If you want to be able to set arbitrary default config, allow TFTP traffic
Configuration examples:
# Allow SNMP via access-list
ip access-list standard SNMP_portmanager
permit "IP address of the Portmanager server"
deny any
# Set SNMP community and mode to RW
snmp-server community "SNMP_Community" RW SNMP_portmanager
3.3.2 Juniper
- Because of its security policies, Juniper does not allow changing device parameters via SNMP, so SNMP is used only for getting basic information about ports.
- All set methods are implemented by NetConf, so it is also necessary to allow NetConf network traffic between the system and network devices.
Configuration examples:
# Set login with user portmanager (mandatory) and SSH key
system {
login {
user portmanager {
uid "SomeUIDNum";
class super-user;
authentication {
ssh-rsa "ssh-rsa SomeKeyData user@example.com"; ## SECRET-DATA
}
}
...
# Allow NetConf for applying changes
system{
services {
netconf {
ssh;
}
...
# Set SNMP
snmp {
location "SomeLocation";
contact "SomeContact";
community "SNMPCommunity" {
authorization read-write;
clients {
"Portmanager IP address"/32;
}
}
}
...
# Allow SNMP traffic
...
term SNMP {
from {
source-address {
"Portmanager IP address"/32;
}
protocol udp;
destination-port snmp;
}
then accept;
}
...
3.3.3 HP Procurve
- Only SNMP needed for all of the actions.
4 Development
4.1 Add modules for supporting new device type
Inside webapp/switches/switch_modules/
are current implementations for Cisco, HP and Juniper devices. If you need to add new,
create new python file inside that directory, create class based on GeneralSwitch
and customize methods that are not common with methods written inside the GeneralSwitch
class.
4.1 Translation to different language
System uses I18N for Django. Primary language for the whole system is english. For different localization, you need to generate and compile locale
files inside webapp/portmanager_project/locale/
folder and upddate Django configuration.
For now, project is also translated into czech, below are commands used for generating and compiling locale files:
# create files for specified language, use -d djangojs for javascript files
$ django-admin makemessages -d djangojs -l cs --ignore="staticfiles/*" --ignore="node_modules/*"
# compile *.po files into *.mo
$ django-admin compilemessages