1a6896077b1e9c976f3ba7f318d36751a457bb03
[pyi2ncommon] / src / cnfvar / templates.py
1 # The software in this package is distributed under the GNU General
2 # Public License version 2 (with a special exception described below).
3 #
4 # A copy of GNU General Public License (GPL) is included in this distribution,
5 # in the file COPYING.GPL.
6 #
7 # As a special exception, if other files instantiate templates or use macros
8 # or inline functions from this file, or you compile this file and link it
9 # with other works to produce a work based on this file, this file
10 # does not by itself cause the resulting work to be covered
11 # by the GNU General Public License.
12 #
13 # However the source code for this file must still be made available
14 # in accordance with section (3) of the GNU General Public License.
15 #
16 # This exception does not invalidate any other reasons why a work based
17 # on this file might be covered by the GNU General Public License.
18 #
19 # Copyright (c) 2016-2018 Intra2net AG <info@intra2net.com>
20
21 """
22
23 summary
24 ------------------------------------------------------
25 Module for one-step dynamic cnfvar generation from default value templates.
26
27 .. codeauthor:: Intra2net
28
29
30 contents
31 -------------------------------------------------------
32 These templates contain the bare defaults the UI adds upon
33 creation of each major and frequently used cnfvar.
34
35
36 interface
37 ------------------------------------------------------
38
39 """
40
41 import time
42 import logging
43
44 # custom imports
45 from .model import Cnf, CnfList
46
47
48 log = logging.getLogger('pyi2ncommon.cnfvar.templates')
49
50
51 ###############################################################################
52 # MAJOR CNF DEFAULTS
53 ###############################################################################
54
55
56 #: UI defaults for a user instance
57 user_defaults = {
58     "USER_DISABLED": "0",
59     "USER_FULLNAME": "",
60     "USER_GROUPWARE_FOLDER_CALENDAR": "INBOX/Calendar",
61     "USER_GROUPWARE_FOLDER_CONTACTS": "INBOX/Contacts",
62     "USER_GROUPWARE_FOLDER_DRAFTS": "INBOX/Drafts",
63     "USER_GROUPWARE_FOLDER_NOTES": "INBOX/Notes",
64     "USER_GROUPWARE_FOLDER_OUTBOX": "INBOX/Sent Items",
65     "USER_GROUPWARE_FOLDER_TASKS": "INBOX/Tasks",
66     "USER_GROUPWARE_FOLDER_TRASH": "INBOX/Deleted Items",
67     # always a member of the 'Alle' group
68     "USER_GROUP_MEMBER_REF": "2",
69     "USER_LOCALE": "",
70     "USER_PASSWORD": "test1234",
71     "USER_TRASH_DELETEDAYS": "30",
72     "USER_WEBMAIL_MESSAGES_PER_PAGE": "25",
73     "USER_WEBMAIL_SIGNATURE": "",
74 }
75 #: UI defaults for a group instance
76 group_defaults = {
77     "GROUP_COMMENT": "",
78     "GROUP_ACCESS_GO_ONLINE_ALLOWED": "1",
79     "GROUP_EMAILFILTER_BAN_FILTERLIST_REF": "-1",
80     "GROUP_EMAIL_RELAY_RIGHTS": "RELAY_FROM_INTRANET",
81     "GROUP_PROXY_PROFILE_REF": "1",
82 }
83
84
85
86 ###############################################################################
87 # MINOR CONFIGURATION
88 ###############################################################################
89
90
91 def template(name, value, instance=-1, defaults=None, **kwargs):
92     """
93     Generate a template cnf variable from provided defaults.
94
95     :param str name: cnf variable name
96     :param str value: cnf variable data value
97     :param int instance: cnf variable instance number
98     :param defaults: default child variables to populate the cnf variable with
99     :type defaults: {str, str or {}} or None
100     :returns: generated cnf variable
101     :rtype: :py:class:`Cnf`
102
103     All additional keyword arguments will be used to overwrite the defaults.
104     """
105     log.info(f"Generating a template {name} cnfvar")
106     cnf = Cnf(name, value=value, instance=instance)
107     defaults = {} if defaults is None else defaults
108     cnf.add_children(*[(key, value) for key, value in defaults.items()])
109     for key in kwargs.keys():
110         cnf.children.single_with_name(f"{name}_{key}").value = kwargs[key]
111     return cnf
112
113
114 def user(name, password, instance=-1, **kwargs):
115     """
116     Generate a user cnf variable.
117
118     :param str name: username for the user
119     :param str password: password for the user
120     :param int instance: instance number for the user
121     :returns: generated cnf variable
122     :rtype: :py:class:`Cnf`
123     """
124     log.info(f"Generating a user {name} cnfvar")
125     user_cnf = template("user", name, instance=instance, defaults=user_defaults, **kwargs)
126     user_cnf.children.single_with_name("user_fullname").value = name.capitalize()
127     user_cnf.children.single_with_name("user_password").value = password
128     return user_cnf
129
130
131 def group(name, instance=-1, **kwargs):
132     """
133     Generate a group cnf variable.
134
135     :param str name: name for the group
136     :param int instance: instance number for the group
137     :returns: generated cnf variable
138     :rtype: :py:class:`Cnf`
139     """
140     log.info(f"Generating a group {name} cnfvar")
141     group_cnf = template("group", name, instance=instance, defaults=group_defaults, **kwargs)
142     return group_cnf
143
144
145 def nic(instance=0, nictype="NATLAN",
146         ip="1.2.3.4", netmask="255.255.0.0", mac="00:00:00:00:00:00",
147         suffix="host"):
148     """
149     Generate and save a nic configuration file.
150
151     :param int instance: instance number (for multiple nics, -1 for next available)
152     :param str nictype: type of the nic
153     :param str ip: IP address of the nic
154     :param str netmask: network mask of the nic
155     :param str mac: MAC address of the nic
156     :param str suffix: optional suffix to use for config identification
157     :returns: generated config filename
158     :rtype: str
159     """
160     log.info("Create arnied nic configuration")
161     nic_obj = batch_update_cnf(
162         build_nic.BuildNIC(data="", instance=instance, line_no=1),
163         [(Update, ("NIC_TYPE", 0, nictype)),
164          (Update, ("NIC_LAN_IP", 0, ip)),
165          (Update, ("NIC_LAN_NETMASK", 0, netmask)),
166          (Update, ("NIC_MAC", 0, mac))])
167     nic_cnf = "nic-%d-%s.cnf" % (time.time(), suffix)
168     [nic_cnf] = aw.prep_config_paths([nic_cnf], aw.DUMP_CONFIG_DIR)
169     logging.info("Saving nic configuration to %s", nic_cnf)
170     nic_obj.save(nic_cnf)
171     return nic_cnf
172
173
174 def intraclient(name="intraclient", instance=1,
175                 ip="1.2.3.4", mac="00:00:00:00:00:00",
176                 fwrules=5, suffix="host"):
177     """
178     Generate and save an intraclient configuration file.
179
180     :param str name: name of the intraclient
181     :param int instance: instance number (for multiple clients, -1 for next available)
182     :param str ip: IP address of the intraclient
183     :param str mac: MAC address of the intraclient
184     :param int fwrules: instance of the firewall rules to use
185     :param str suffix: optional suffix to use for config identification
186     :returns: generated config filename
187     :rtype: str
188     """
189     log.info("Create arnied intraclient configuration")
190     intraclient_obj = batch_update_cnf(
191         build_intraclient.BuildIntraclient(data=name, instance=instance),
192         [(Update, ("INTRACLIENT_IP", 0, ip)),
193          (Update, ("INTRACLIENT_MAC", 0, mac)),
194          (Update, ("INTRACLIENT_FIREWALL_RULESET_REF", 0, fwrules))])
195
196     intraclient_cnf = "intraclient-%d-%s.cnf" % (time.time(), suffix)
197     [intraclient_cnf] = aw.prep_config_paths([intraclient_cnf], aw.DUMP_CONFIG_DIR)
198     logging.info("Saving intraclient configuration to %s", intraclient_cnf)
199     intraclient_obj.save(intraclient_cnf)
200     return intraclient_cnf
201
202
203 def provider(name="provider", instance=1, mode="ROUTER", ip="1.2.3.4", localip=None,
204              netmask="255.255.0.0", dnsmode="IP", dns="1.2.3.4", fwrules=5,
205              dialretry=None, timeout="", mtumode="AUTO",
206              vlanid=None, mtusize=None, login=None, password=None,
207              modemip=None, providerid=None, localdhcp=None,
208              suffix="host"):
209     """
210     Generate and save a provider configuration file.
211
212     :param str name: name of the provider
213     :param int instance: instance number (for multiple clients, -1 for next available)
214     :param str mode: provider mode
215     :param str ip: IP address of the provider
216     :param localip: IP address of the configured machine (valid for some configurations)
217     :type localip: str or None
218     :param str netmask: netmask of the provider
219     :param str dnsmode: dnsmode of the provider
220     :param str dns: IP address of the DNS server
221     :param int fwrules: instance of the firewall rules to use
222     :param any args: lots of detailed configuration
223     :param str suffix: optional suffix to use for config identification
224     :returns: generated config filename
225     :rtype: str
226     """
227     log.info("Create arnied provider configuration")
228
229     def add_or_del(var, field):
230         if var is not None:
231             return Add, (field, 0, str(var))
232         return Delete, field
233     provider_obj = batch_update_cnf(
234         build_provider.BuildProvider(data=name, instance=instance),
235         [(Update, ("PROVIDER_MODE", 0, mode)),
236          ip and (Update, ("PROVIDER_IP", 0, ip))
237              or (Delete, "PROVIDER_IP"),
238          localip
239          and (Update, ("PROVIDER_LOCALIP", 0, localip))
240          or (Delete, "PROVIDER_LOCALIP"),
241          netmask and (Update, ("PROVIDER_NETMASK", 0,
242                                netmask))
243                   or (Delete, "PROVIDER_NETMASK"),
244          (Update, ("PROVIDER_TIMEOUT", 0, timeout)),
245          (Update, ("PROVIDER_DNS_MODE", 0, dnsmode)),
246          (Update, ("PROVIDER_DNS", 0,
247                    dns if dnsmode == "IP" else "")),
248          (Update, ("PROVIDER_MTU_MODE", 0, mtumode)),
249          (Update, ("PROVIDER_MTU_SIZE", 0,
250                    mtusize if mtumode != "AUTO" else "")),
251          (Update, ("PROVIDER_FIREWALL_RULESET_REF", 0, str(fwrules))),
252          add_or_del(vlanid, "PROVIDER_VLAN_ID"),
253          add_or_del(dialretry, "PROVIDER_DIAL_RETRY"),
254          add_or_del(login, "PROVIDER_LOGIN"),
255          add_or_del(password, "PROVIDER_PASSWORD"),
256          add_or_del(modemip, "PROVIDER_MODEM_IP"),
257          add_or_del(providerid, "PROVIDER_PROVIDERID"),
258          add_or_del(localdhcp, "PROVIDER_LOCAL_DHCP")])
259     provider_cnf = "provider-%d-%s.cnf" % (time.time(), suffix)
260     [provider_cnf] = aw.prep_config_paths([provider_cnf], aw.DUMP_CONFIG_DIR)
261     logging.info("Saving provider configuration to %s", provider_cnf)
262     provider_obj.save(provider_cnf)
263     return provider_cnf
264
265
266 def provider_proxy(mode="ROUTER", ip="1.2.3.4", localip=None, proxy_port=3128, fwrules=7, suffix="host"):
267     """
268     Generate and save a provider configuration file for proxy.
269
270     :param str mode: provider mode
271     :param str ip: IP address of the provider (and DNS server)
272     :param localip: IP address of the configured machine (valid for some configurations)
273     :type localip: str or None
274     :param int proxy_port: port for the provider proxy
275     :param int fwrules: instance of the firewall rules to use
276     :param str suffix: optional suffix to use for config identification
277     :returns: generated config filename
278     :rtype: str
279     """
280     log.info("Create arnied provider configuration.")
281     provider_obj = batch_update_cnf(
282         build_provider.BuildProvider(),
283         [(Update, ("PROVIDER_MODE", 0, mode)),
284          (Update, ("PROVIDER_DNS", 0, ip)),
285          (Update, ("PROVIDER_DYNDNS_ENABLE", 0, "0")),
286          (Update, ("PROVIDER_IP", 0, ip)),
287          (Update, ("PROVIDER_PROXY_SERVER", 0, ip)),
288          (Update, ("PROVIDER_PROXY_PORT", 0, str(proxy_port))),
289          localip
290          and (Update, ("PROVIDER_LOCALIP", 0, localip))
291          or (Delete, "PROVIDER_LOCALIP"),
292          (Update, ("PROVIDER_DNS_MODE", 0, "IP")),
293          (Update, ("PROVIDER_FIREWALL_RULESET_REF", 0, str(fwrules)))])
294     provider_cnf = "provider-%d-%s.cnf" % (time.time(), suffix)
295     [provider_cnf] = aw.prep_config_paths([provider_cnf], aw.DUMP_CONFIG_DIR)
296     logging.info("Saving provider configuration to %s", provider_cnf)
297     provider_obj.save(provider_cnf)
298     return provider_cnf
299
300
301 def port_forwarding(src_port="1234", src_port_end="",
302                     dst_port="1234", dst_port_end="",
303                     dst_ip_ref="1", protocol_type="TCP",
304                     suffix="host"):
305     """
306     Generate and save a port forwarding configuration file.
307
308     :param str src_port: forwarded source port
309     :param str src_port_end: forwarded source port end for a port range
310     :param str dst_port: forwarded destination port
311     :param str dst_port_end: forwarded destination port end for a port range
312     :param str dst_ip_ref: destination nic instance for a port range
313     :param str protocol_type: port forwarding protocol type
314     :param str suffix: optional suffix to use for config identification
315     :returns: generated config filename
316     :rtype: str
317     """
318     log.info("Create port forwarding configuration")
319     value_id = "test"
320     portforward_client_cnf = "portforward-%d-%s.cnf" % (time.time(), suffix)
321     return build_cnf("PORT_FORWARDING",
322                      data=value_id,
323                      filename=portforward_client_cnf,
324                      vals=[(Child, ("PORT_FORWARDING_DST_IP_REF", 0, dst_ip_ref)),
325                            (Child, ("PORT_FORWARDING_DST_PORT", 0, dst_port)),
326                            (Child, ("PORT_FORWARDING_DST_PORT_END", 0, dst_port_end)),
327                            (Child, ("PORT_FORWARDING_PROTOCOL_TYPE", 0, protocol_type)),
328                            (Child, ("PORT_FORWARDING_SRC_PORT", 0, src_port)),
329                            (Child, ("PORT_FORWARDING_SRC_PORT_END", 0, src_port_end))])
330
331
332 def firewall_ruleset_simple(suffix="host"):
333     """
334     Generate and save a simple firewall ruleset configuration file.
335
336     :param str suffix: optional suffix to use for config identification
337     :returns: generated config filename
338     :rtype: str
339     """
340     log.info("Create firewall ruleset")
341     fw_cnf = "fw-%d-%s.cnf" % (time.time(), suffix)
342     return build_cnf("FIREWALL_RULESET",
343                      instance=101,
344                      data="Port Forwarding libfirewall test",
345                      filename=fw_cnf,
346                      vals=[(Update, ("FIREWALL_RULESET_PROFILE_TYPE", 0, "SIMPLE_PROVIDER")),
347                            (Update, ("FIREWALL_RULESET_PROVIDER_HTTPS_OPEN", 0, "0")),
348                            (Update, ("FIREWALL_RULESET_PROVIDER_POP3SIMAPS_OPEN", 0, "0")),
349                            (Update, ("FIREWALL_RULESET_PROVIDER_PORT_FORWARDING_ENABLE", 0, "1")),
350                            (Update, ("FIREWALL_RULESET_PROVIDER_SMTP_OPEN", 0, "0")),
351                            (Update, ("FIREWALL_RULESET_PROVIDER_HTTP_OPEN", 0, "0")),
352                            (Update, ("FIREWALL_RULESET_PROVIDER_VPN_OPEN", 0, "0"))])
353
354
355 def firewall_ruleset_port(suffix="host"):
356     """
357     Generate and save a firewall ruleset configuration file for port forwarding.
358
359     :param str suffix: optional suffix to use for config identification
360     :returns: generated config filename
361     :rtype: str
362     """
363     log.info("Create firewall ruleset")
364     fw_portforward_cnf = "fw-portforward-%d-%s.cnf" % (time.time(), suffix)
365     return build_cnf("FIREWALL_RULESET",
366                      instance=100,
367                      data="Port forwarding only",
368                      filename=fw_portforward_cnf,
369                      vals=[(Update, ("FIREWALL_RULESET_AUTOMATIC_ANSWER_RULE", 0, "1")),
370                            (Update, ("FIREWALL_RULESET_PROFILE_TYPE", 0, "FULL")),
371                            (Add, ("FIREWALL_RULESET_RULE", 1, "")),
372                            (Child, ("FIREWALL_RULESET_RULE_ACTION", 0, "ACCEPT")),
373                            (Child, ("FIREWALL_RULESET_RULE_CHECK_CONNECTION_STATUS", 0, "PORTFORWARDING")),
374                            (Child, ("FIREWALL_RULESET_RULE_CHECK_TCP_FLAGS", 0, "DISABLED")),
375                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_FOR_ACTION_ENABLE", 0, "0")),
376                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_FOR_LOG_ENABLE", 0, "0")),
377                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_AVERAGE_COUNT", 0, "")),
378                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_AVERAGE_PERIOD", 0, "SEC")),
379                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_PEAK_COUNT", 0, "")),
380                            (Child, ("FIREWALL_RULESET_RULE_LOG_ENABLE", 0, "0")),
381                            (Child, ("FIREWALL_RULESET_RULE_LOG_MESSAGE", 0, "")),
382                            (Child, ("FIREWALL_RULESET_RULE_TIME_INCLUDE_TIME_REF", 0, "-1")),
383                            (Update, ("FIREWALL_RULESET_USAGE", 0, "PROVIDER"))])
384
385
386 def firewall_ruleset_dmz(suffix="host"):
387     """
388     Generate and save a firewall ruleset configuration file for DMZ.
389
390     :param str suffix: optional suffix to use for config identification
391     :returns: generated config filename
392     :rtype: str
393     """
394     log.info("Create firewall ruleset")
395     fw_dmz_cnf = "fw-dmz-%d-%s.cnf" % (time.time(), suffix)
396     return build_cnf("FIREWALL_RULESET",
397                      instance=100,
398                      data="DMZ firewall rules",
399                      filename=fw_dmz_cnf,
400                      vals=[(Update, ("FIREWALL_RULESET_AUTOMATIC_ANSWER_RULE", 0, "1")),
401                            (Update, ("FIREWALL_RULESET_PROFILE_TYPE", 0, "FULL")),
402                            (Add, ("FIREWALL_RULESET_RULE", 1, "")),
403                            (Child, ("FIREWALL_RULESET_RULE_ACTION", 0, "ACCEPT")),
404                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_FOR_ACTION_ENABLE", 0, "0")),
405                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_FOR_LOG_ENABLE", 0, "0")),
406                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_AVERAGE_COUNT", 0, "")),
407                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_PEAK_COUNT", 0, "")),
408                            (Child, ("FIREWALL_RULESET_RULE_LOG_ENABLE", 0, "0")),
409                            (Child, ("FIREWALL_RULESET_RULE_LOG_MESSAGE", 0, "")),
410                            (Child, ("FIREWALL_RULESET_RULE_SERVICE_INCLUDE_SERVICEGROUP_REF", 0, "6")),
411                            (Child, ("FIREWALL_RULESET_RULE_DST_INCLUDE_CLIENT_REF", 0, "2")),
412                            (Update, ("FIREWALL_RULESET_USAGE", 0, "LANVPN"))])