]> git.llucax.com Git - software/pymin.git/blob - pymin/services/firewall/__init__.py
Use ListSubHandler in firewall rules.
[software/pymin.git] / pymin / services / firewall / __init__.py
1 # vim: set encoding=utf-8 et sw=4 sts=4 :
2
3 # TODO See if it's better (more secure) to execute commands via python instead
4 # of using script templates.
5
6 from os import path
7
8 from pymin.seqtools import Sequence
9 from pymin.dispatcher import Handler, handler, HandlerError
10 from pymin.services.util import Restorable, ConfigWriter, ServiceHandler, \
11                                 TransactionalHandler, ListSubHandler
12
13 __ALL__ = ('FirewallHandler', 'Error')
14
15 class Error(HandlerError):
16     r"""
17     Error(command) -> Error instance :: Base FirewallHandler exception class.
18
19     All exceptions raised by the FirewallHandler inherits from this one, so you can
20     easily catch any FirewallHandler exception.
21
22     message - A descriptive error message.
23     """
24     pass
25
26 class Rule(Sequence):
27     r"""Rule(chain, target[, src[, dst[, ...]]]) -> Rule instance.
28
29     chain - INPUT, OUTPUT or FORWARD.
30     target - ACCEPT, REJECT or DROP.
31     src - Source subnet as IP/mask.
32     dst - Destination subnet as IP/mask.
33     protocol - ICMP, UDP, TCP or ALL.
34     src_port - Source port (only for UDP or TCP protocols).
35     dst_port - Destination port (only for UDP or TCP protocols).
36     """
37
38     def __init__(self, chain, target, src=None, dst=None, protocol=None,
39                        src_port=None, dst_port=None):
40         r"Initialize object, see class documentation for details."
41         self.chain = chain
42         self.target = target
43         self.src = src
44         self.dst = dst
45         self.protocol = protocol
46         # TODO Validate that src_port and dst_port could be not None only
47         # if the protocol is UDP or TCP
48         self.src_port = src_port
49         self.dst_port = dst_port
50
51     def update(self, chain=None, target=None, src=None, dst=None, protocol=None,
52                        src_port=None, dst_port=None):
53         r"update([chain[, ...]]) -> Update the values of a rule (see Rule doc)."
54         if chain is not None: self.chain = chain
55         if target is not None: self.target = target
56         if src is not None: self.src = src
57         if dst is not None: self.dst = dst
58         if protocol is not None: self.protocol = protocol
59         # TODO Validate that src_port and dst_port could be not None only
60         # if the protocol is UDP or TCP
61         if src_port is not None: self.src_port = src_port
62         if dst_port is not None: self.dst_port = dst_port
63
64     def __cmp__(self, other):
65         r"Compares two Rule objects."
66         return cmp(self.as_tuple(), other.as_tuple())
67
68     def as_tuple(self):
69         r"Return a tuple representing the rule."
70         return (self.chain, self.target, self.src, self.dst, self.protocol,
71                     self.src_port, self.dst_port)
72
73 class RuleHandler(ListSubHandler):
74     r"""RuleHandler(parent) -> RuleHandler instance :: Handle a list of rules.
75
76     This class is a helper for FirewallHandler to do all the work related to rules
77     administration.
78
79     parent - The parent service handler.
80     """
81
82     handler_help = u"Manage firewall rules"
83
84     _list_subhandler_attr = 'rules'
85     _list_subhandler_class = Rule
86
87 class FirewallHandler(Restorable, ConfigWriter, ServiceHandler,
88                       TransactionalHandler):
89     r"""FirewallHandler([pickle_dir[, config_dir]]) -> FirewallHandler instance.
90
91     Handles firewall commands using iptables.
92
93     pickle_dir - Directory where to write the persistent configuration data.
94
95     config_dir - Directory where to store de generated configuration files.
96
97     Both defaults to the current working directory.
98     """
99
100     handler_help = u"Manage firewall service"
101
102     _persistent_attrs = 'rules'
103
104     _restorable_defaults = dict(rules=list())
105
106     _config_writer_files = 'iptables.sh'
107     _config_writer_tpl_dir = path.join(path.dirname(__file__), 'templates')
108
109     def __init__(self, pickle_dir='.', config_dir='.'):
110         r"Initialize the object, see class documentation for details."
111         self._persistent_dir = pickle_dir
112         self._config_writer_cfg_dir = config_dir
113         self._service_start = ('sh', path.join(self._config_writer_cfg_dir,
114                                         self._config_writer_files))
115         self._service_stop = ('iptables', '-t', 'filter', '-F')
116         self._service_restart = self._service_start
117         self._service_reload = self._service_start
118         self._config_build_templates()
119         self._restore()
120         self.rule = RuleHandler(self)
121
122     def _get_config_vars(self, config_file):
123         return dict(rules=self.rules)
124
125
126 if __name__ == '__main__':
127
128     import os
129
130     fw_handler = FirewallHandler()
131
132     def dump():
133         print '-' * 80
134         print 'Rules:'
135         print fw_handler.rule.show()
136         print '-' * 80
137
138     dump()
139
140     fw_handler.rule.add('input','drop','icmp')
141
142     fw_handler.rule.update(0, dst='192.168.0.188/32')
143
144     fw_handler.rule.add('output','accept', '192.168.1.0/24')
145
146     fw_handler.commit()
147
148     fw_handler.stop()
149
150     dump()
151
152     os.system('rm -f *.pkl iptables.sh')
153