# HG changeset patch # User Branko Majic # Date 2013-02-28 22:56:06 # Node ID 3eadaa71b65520939de767632bafe3a866db2dd0 # Parent 7b9708f0eeda63cc09f5932d79e74feaf07b9073 Added docsctrings. The __unicode__ function for Interface now returns shorter strings for single-IP address. The protocol field in Communication now uses a set fixed choices. Simplified the Communication string representation. The clean function for Communication model now verifies that entities involved for source and estination are not the same, instead of interfaces. Added a dummy function for edit link in the admin site. diff --git a/conntrackt/models.py b/conntrackt/models.py --- a/conntrackt/models.py +++ b/conntrackt/models.py @@ -1,57 +1,227 @@ +# Basic classes needed for creating models. from django.db import models + +# from django.core.exceptions import ValidationError # Create your models here. class Project(models.Model): + """ + Implements a model with information about a project. A project has some + basic settings, and mainly serves the purpose of grouping entities for + easier handling and administration. + + Fields: + + name - String denoting the project name. + description - Free-form description of the project. + """ + name = models.CharField(max_length = 100) description = models.TextField(blank = True) def __unicode__(self): + """ + Returns: + String representation of a project. + """ + return self.name class Location(models.Model): + """ + Implements a model with information about location. Locations can further be + assigned to entities, letting the user group different servers and equipment + based on location. + + Locations are not tied to specific project, and they do not have to be + actual physical locations. Such generic locations are therefore reusable + accross multiple projects. + + For example, locations can be: + + - Main site + - Backup site + - Disaster recovery site + - Belgrade + - Stockholm + + Fields: + + name - String denoting the location name. + description - Free-form description of a location. + """ + name = models.CharField(max_length = 100) description = models.TextField(blank = True) def __unicode__(self): + """ + Returns: + String representation of a location. + """ + return self.name class Entity(models.Model): + """ + Models an entity in a project. An entity can be a server, router, or any + other piece of networking equipment that has its own IP address. + + Entities can also be used for representing subnets etc. This is useful when + the communication restrictions need to be applied across a subnet. + + Entities are tied to specific projects and locations. + + Fields: + + name - String denoting the entity name. + description - Free-form description of an entity. + project - Foreign key pointing to the project to which the entity + belongs. + location - Foreign key pointing to the location at which the entity is + located. + """ + name = models.CharField(max_length = 100) description = models.TextField(blank = True) project = models.ForeignKey(Project) location = models.ForeignKey(Location) class Meta: + """ + Overrides some of the default parameters used by Django for this model. + + Properties: + verbose_name_plural - Changes the way Django Admin displays the model + name in plural. + """ + verbose_name_plural = 'entities' def __unicode__(self): + """ + Returns: + String representation of an entity. This identifier contains name of + entity, its project name, and location name. + """ + return "%s (%s - %s)" % (self.name, self.project, self.location) class Interface(models.Model): - name = models.CharField(max_length = 100) - description = models.TextField(blank = True) + """ + Models a representation of an interface on an entity. It can be used for + representing the subnets as well. + + Each interface is coupled with a specific Entity. + + Fields: + name - String denoting the interface name. For example 'eth0', 'eth1' + etc. + description - Free-form description of an interface. + entity - Foreign key pointing to the entity to which the interface + belongs. + address - IP address of an interface. It's possible to store network + address in it as well. + netmask - Netmask of the interface. By default this is /32 + (255.255.255.255), but in case of subnet entities this can be used for + denoting the network netmask. + """ + + name = models.CharField(max_length = 100, default = 'eth0') + description = models.TextField(blank = True, default = 'Main network interface.') entity = models.ForeignKey(Entity) address = models.IPAddressField() - netmask = models.IPAddressField(default='255.255.255.255') + netmask = models.IPAddressField(default = '255.255.255.255') def __unicode__(self): - return "%s (%s = %s/%s)" % (self.entity.name, self.name, self.address, self.netmask) + """ + Returns: + String representation of an interface. In case of single IP this will + simply be the interface name and IP address. In case of subnet it will + include the netmask as well. + """ + + if self.netmask == '255.255.255.255': + return '%s (%s)' % (self.entity.name, self.address) + else: + return '%s (%s/%s)' % (self.entity.name, self.address, self.netmask) class Communication(models.Model): + """ + Models a representation of allowed network communication. This lets the user + display the possible network connections that should be allowed. Information + from the communication instances is also used for generating the iptables + rules for the entities. + + Communication instances allow the user to specify one of the three possible + protocols and related information: + + - TCP, along with the TCP port. + - UDP, along with the UDP port. + - ICMP, along with the ICMP type. + + Allowed communication is always represented as combination of source + interface, destination interface, protocol, and port/ICMP type. + + Fields: + source - Foreign key to the source (originating) interface. The + communication is expected to come _from_ the source. + destination - Foreign key to the destination interface. The destination + interface is expected to be able to accept incoming connections + (i.e. entity's servers are listening on those). + protocol - Textual field denoting the protocol that is used for + communication. This can be 'TCP', 'UDP', or 'ICMP'. + port - Port number used by the protocol. In case of ICMP, this is an ICMP + type (in numeric form). + description - Free-form text that can be used to describe the + communication. This is also used when generating the iptables rules for + documenting the rules. + """ + + PROTOCOL_CHOICES = ( + ('TCP', 'TCP'), + ('UDP', 'UDP'), + ('ICMP', 'ICMP'), + ) + source = models.ForeignKey(Interface, related_name = 'source_set') destination = models.ForeignKey(Interface, related_name = 'destination_set') - protocol = models.CharField(max_length = 10) + protocol = models.CharField(max_length = 10, choices = PROTOCOL_CHOICES) port = models.IntegerField(default = 0) description = models.TextField(blank = True) def __unicode__(self): - return "%s (%s/%s) -> %s (%s/%s)" % (self.source.entity.name, self.source.address, self.source.netmask, - self.destination.entity.name, self.destination.address, self.destination.netmask) + """ + Returns: + String representation of an interface. This involves showing the + source and destination _entity_ name, protocol, and port. + """ + + return "%s -> %s (%s:%s)" % (self.source.entity.name, self.destination.entity.name, self.protocol, self.port) def clean(self): - if self.source == self.destination: - raise ValidationError('Source and destination must differ.') - if self.protocol.lower() not in ('udp', 'tcp', 'icmp'): + """ + Performs additional validation checks on the submitted data. It will + verify the following: + + - That source and destination interface belongs to distinct entities. + - That the specified protocol is supported. + """ + + if self.source.entity == self.destination.entity: + raise ValidationError('Source and destination entities must differ.') + if (self.protocol.upper(), self.protocol.upper()) not in self.PROTOCOL_CHOICES: raise ValidationError('%s is not a supported protocol.' % self.protocol) + def edit_link(self): + """ + This method is used for providing an additional 'Edit' link in the admin + site for the communication instances (for the display_list). + + This provides ability to let all of the other fields of a communication + instance to be editable. + """ + + return "Edit" +