Introduce use of defaults i.e. UI-default rather than minimal user cnfvars
[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
76
77 ###############################################################################
78 # MINOR CONFIGURATION
79 ###############################################################################
80
81
82 def template(name, value, instance=-1, defaults=None, **kwargs):
83     """
84     Generate a template cnf variable from provided defaults.
85
86     :param str name: cnf variable name
87     :param str value: cnf variable data value
88     :param int instance: cnf variable instance number
89     :param defaults: default child variables to populate the cnf variable with
90     :type defaults: {str, str or {}} or None
91     :returns: generated cnf variable
92     :rtype: :py:class:`Cnf`
93
94     All additional keyword arguments will be used to overwrite the defaults.
95     """
96     log.info(f"Generating a template {name} cnfvar")
97     cnf = Cnf(name, value=value, instance=instance)
98     defaults = {} if defaults is None else defaults
99     cnf.add_children(*[(key, value) for key, value in defaults.items()])
100     for key in kwargs.keys():
101         cnf.children.single_with_name(f"{name}_{key}").value = kwargs[key]
102     return cnf
103
104
105 def user(name, password, instance=-1, **kwargs):
106     """
107     Generate a user cnf variable.
108
109     :param str name: username for the user
110     :param str password: password for the user
111     :param int instance: instance number for the user
112     :returns: generated cnf variable
113     :rtype: :py:class:`Cnf`
114     """
115     log.info(f"Generating a user {name} cnfvar")
116     user_cnf = template("user", name, instance=instance, defaults=user_defaults, **kwargs)
117     user_cnf.children.single_with_name("user_fullname").value = name.capitalize()
118     user_cnf.children.single_with_name("user_password").value = password
119     return user_cnf
120
121
122 def group_admins(proxy_profile="1", activesync_enable=False, xauth_enable=False, suffix="host"):
123     """
124     Generate and save an Administrators group configuration file.
125
126     :param str proxy_profile: proxy profile instance reference
127     :param bool activesync_enable: whether to enable ActiveSync for the group
128     :param bool xauth_enable: whether to enable XAUTH for the group
129     :param str suffix: optional suffix to use for config identification
130     :returns: generated config filename
131     :rtype: str
132     """
133     log.info("Create arnied admin group configuration")
134     group = batch_update_cnf(build_group.BuildGroup(data="Administratoren",
135                                                     instance=1),
136                              [(Update, ("GROUP_ACCESS_REMOTE_ADMINISTRATION_ALLOWED", 0, "1")),
137                               (Update, ("GROUP_EMAILFILTER_BAN_FILTERLIST_REF", 0, "-1")),
138                               (Update, ("GROUP_PROXY_PROFILE_REF", 0, proxy_profile)),
139                               (Update, ("GROUP_ACCESS_GO_ONLINE_ALLOWED", 0, "1")),
140                               (Update, ("GROUP_EMAIL_RELAY_RIGHTS", 0, "RELAY_FROM_INTRANET")),
141                               (Update, ("GROUP_ACTIVESYNC_ENABLE", 0, "1" if activesync_enable else "0")),
142                               (Update, ("GROUP_XAUTH_ENABLE", 0, "1" if xauth_enable else "0")),
143                               (Delete, ("GROUP_COMMENT",))])
144     group_cnf = "group-%d-%s.cnf" % (time.time(), suffix)
145     [group_cnf] = aw.prep_config_paths([group_cnf], aw.DUMP_CONFIG_DIR)
146     logging.info("Saving group configuration to %s", group_cnf)
147     group.save(group_cnf)
148     return group_cnf
149
150
151 def group_all(proxy_profile="1", suffix="host"):
152     """
153     Generate and save an "All" group configuration file.
154
155     :param str proxy_profile: proxy profile instance reference
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 all group configuration")
161     group = batch_update_cnf(build_group.BuildGroup(data="Alle",
162                                                     instance=2),
163                              [(Update, ("GROUP_ACCESS_GO_ONLINE_ALLOWED", 0, "1")),
164                               (Update, ("GROUP_ACCESS_INFORMATION_VERSION_ALLOWED", 0, "1")),
165                               (Update, ("GROUP_ACCESS_MAINPAGE_ALLOWED", 0, "1")),
166                               (Update, ("GROUP_ACCESS_USERMANAGER_OWN_PROFILE_FORWARDING_ALLOWED", 0, "1")),
167                               (Update, ("GROUP_ACCESS_USERMANAGER_OWN_PROFILE_GROUPWARE_ALLOWED", 0, "1")),
168                               (Update, ("GROUP_ACCESS_USERMANAGER_OWN_PROFILE_SETTINGS_ALLOWED", 0, "1")),
169                               (Update, ("GROUP_ACCESS_USERMANAGER_OWN_PROFILE_SORTING_ALLOWED", 0, "1")),
170                               (Update, ("GROUP_ACCESS_USERMANAGER_OWN_PROFILE_SPAMFILTER_ALLOWED", 0, "1")),
171                               (Update, ("GROUP_ACCESS_USERMANAGER_OWN_PROFILE_VACATION_ALLOWED", 0, "1")),
172                               (Update, ("GROUP_ACCESS_GROUPWARE_ALLOWED", 0, "1")),
173                               (Update, ("GROUP_EMAILFILTER_BAN_FILTERLIST_REF", 0, "-1")),
174                               (Update, ("GROUP_EMAIL_RELAY_RIGHTS", 0, "RELAY_FROM_EVERYWHERE")),
175                               (Update, ("GROUP_PROXY_PROFILE_REF", 0, proxy_profile)),
176                               (Delete, ("GROUP_COMMENT",))])
177
178     group_cnf = "group-%d-%s.cnf" % (time.time(), suffix)
179     [group_cnf] = aw.prep_config_paths([group_cnf], aw.DUMP_CONFIG_DIR)
180     logging.info("Saving group configuration to %s", group_cnf)
181     group.save(group_cnf)
182     return group_cnf
183
184
185 def nic(instance=0, nictype="NATLAN",
186         ip="1.2.3.4", netmask="255.255.0.0", mac="00:00:00:00:00:00",
187         suffix="host"):
188     """
189     Generate and save a nic configuration file.
190
191     :param int instance: instance number (for multiple nics, -1 for next available)
192     :param str nictype: type of the nic
193     :param str ip: IP address of the nic
194     :param str netmask: network mask of the nic
195     :param str mac: MAC address of the nic
196     :param str suffix: optional suffix to use for config identification
197     :returns: generated config filename
198     :rtype: str
199     """
200     log.info("Create arnied nic configuration")
201     nic_obj = batch_update_cnf(
202         build_nic.BuildNIC(data="", instance=instance, line_no=1),
203         [(Update, ("NIC_TYPE", 0, nictype)),
204          (Update, ("NIC_LAN_IP", 0, ip)),
205          (Update, ("NIC_LAN_NETMASK", 0, netmask)),
206          (Update, ("NIC_MAC", 0, mac))])
207     nic_cnf = "nic-%d-%s.cnf" % (time.time(), suffix)
208     [nic_cnf] = aw.prep_config_paths([nic_cnf], aw.DUMP_CONFIG_DIR)
209     logging.info("Saving nic configuration to %s", nic_cnf)
210     nic_obj.save(nic_cnf)
211     return nic_cnf
212
213
214 def intraclient(name="intraclient", instance=1,
215                 ip="1.2.3.4", mac="00:00:00:00:00:00",
216                 fwrules=5, suffix="host"):
217     """
218     Generate and save an intraclient configuration file.
219
220     :param str name: name of the intraclient
221     :param int instance: instance number (for multiple clients, -1 for next available)
222     :param str ip: IP address of the intraclient
223     :param str mac: MAC address of the intraclient
224     :param int fwrules: instance of the firewall rules to use
225     :param str suffix: optional suffix to use for config identification
226     :returns: generated config filename
227     :rtype: str
228     """
229     log.info("Create arnied intraclient configuration")
230     intraclient_obj = batch_update_cnf(
231         build_intraclient.BuildIntraclient(data=name, instance=instance),
232         [(Update, ("INTRACLIENT_IP", 0, ip)),
233          (Update, ("INTRACLIENT_MAC", 0, mac)),
234          (Update, ("INTRACLIENT_FIREWALL_RULESET_REF", 0, fwrules))])
235
236     intraclient_cnf = "intraclient-%d-%s.cnf" % (time.time(), suffix)
237     [intraclient_cnf] = aw.prep_config_paths([intraclient_cnf], aw.DUMP_CONFIG_DIR)
238     logging.info("Saving intraclient configuration to %s", intraclient_cnf)
239     intraclient_obj.save(intraclient_cnf)
240     return intraclient_cnf
241
242
243 def provider(name="provider", instance=1, mode="ROUTER", ip="1.2.3.4", localip=None,
244              netmask="255.255.0.0", dnsmode="IP", dns="1.2.3.4", fwrules=5,
245              dialretry=None, timeout="", mtumode="AUTO",
246              vlanid=None, mtusize=None, login=None, password=None,
247              modemip=None, providerid=None, localdhcp=None,
248              suffix="host"):
249     """
250     Generate and save a provider configuration file.
251
252     :param str name: name of the provider
253     :param int instance: instance number (for multiple clients, -1 for next available)
254     :param str mode: provider mode
255     :param str ip: IP address of the provider
256     :param localip: IP address of the configured machine (valid for some configurations)
257     :type localip: str or None
258     :param str netmask: netmask of the provider
259     :param str dnsmode: dnsmode of the provider
260     :param str dns: IP address of the DNS server
261     :param int fwrules: instance of the firewall rules to use
262     :param any args: lots of detailed configuration
263     :param str suffix: optional suffix to use for config identification
264     :returns: generated config filename
265     :rtype: str
266     """
267     log.info("Create arnied provider configuration")
268
269     def add_or_del(var, field):
270         if var is not None:
271             return Add, (field, 0, str(var))
272         return Delete, field
273     provider_obj = batch_update_cnf(
274         build_provider.BuildProvider(data=name, instance=instance),
275         [(Update, ("PROVIDER_MODE", 0, mode)),
276          ip and (Update, ("PROVIDER_IP", 0, ip))
277              or (Delete, "PROVIDER_IP"),
278          localip
279          and (Update, ("PROVIDER_LOCALIP", 0, localip))
280          or (Delete, "PROVIDER_LOCALIP"),
281          netmask and (Update, ("PROVIDER_NETMASK", 0,
282                                netmask))
283                   or (Delete, "PROVIDER_NETMASK"),
284          (Update, ("PROVIDER_TIMEOUT", 0, timeout)),
285          (Update, ("PROVIDER_DNS_MODE", 0, dnsmode)),
286          (Update, ("PROVIDER_DNS", 0,
287                    dns if dnsmode == "IP" else "")),
288          (Update, ("PROVIDER_MTU_MODE", 0, mtumode)),
289          (Update, ("PROVIDER_MTU_SIZE", 0,
290                    mtusize if mtumode != "AUTO" else "")),
291          (Update, ("PROVIDER_FIREWALL_RULESET_REF", 0, str(fwrules))),
292          add_or_del(vlanid, "PROVIDER_VLAN_ID"),
293          add_or_del(dialretry, "PROVIDER_DIAL_RETRY"),
294          add_or_del(login, "PROVIDER_LOGIN"),
295          add_or_del(password, "PROVIDER_PASSWORD"),
296          add_or_del(modemip, "PROVIDER_MODEM_IP"),
297          add_or_del(providerid, "PROVIDER_PROVIDERID"),
298          add_or_del(localdhcp, "PROVIDER_LOCAL_DHCP")])
299     provider_cnf = "provider-%d-%s.cnf" % (time.time(), suffix)
300     [provider_cnf] = aw.prep_config_paths([provider_cnf], aw.DUMP_CONFIG_DIR)
301     logging.info("Saving provider configuration to %s", provider_cnf)
302     provider_obj.save(provider_cnf)
303     return provider_cnf
304
305
306 def provider_proxy(mode="ROUTER", ip="1.2.3.4", localip=None, proxy_port=3128, fwrules=7, suffix="host"):
307     """
308     Generate and save a provider configuration file for proxy.
309
310     :param str mode: provider mode
311     :param str ip: IP address of the provider (and DNS server)
312     :param localip: IP address of the configured machine (valid for some configurations)
313     :type localip: str or None
314     :param int proxy_port: port for the provider proxy
315     :param int fwrules: instance of the firewall rules to use
316     :param str suffix: optional suffix to use for config identification
317     :returns: generated config filename
318     :rtype: str
319     """
320     log.info("Create arnied provider configuration.")
321     provider_obj = batch_update_cnf(
322         build_provider.BuildProvider(),
323         [(Update, ("PROVIDER_MODE", 0, mode)),
324          (Update, ("PROVIDER_DNS", 0, ip)),
325          (Update, ("PROVIDER_DYNDNS_ENABLE", 0, "0")),
326          (Update, ("PROVIDER_IP", 0, ip)),
327          (Update, ("PROVIDER_PROXY_SERVER", 0, ip)),
328          (Update, ("PROVIDER_PROXY_PORT", 0, str(proxy_port))),
329          localip
330          and (Update, ("PROVIDER_LOCALIP", 0, localip))
331          or (Delete, "PROVIDER_LOCALIP"),
332          (Update, ("PROVIDER_DNS_MODE", 0, "IP")),
333          (Update, ("PROVIDER_FIREWALL_RULESET_REF", 0, str(fwrules)))])
334     provider_cnf = "provider-%d-%s.cnf" % (time.time(), suffix)
335     [provider_cnf] = aw.prep_config_paths([provider_cnf], aw.DUMP_CONFIG_DIR)
336     logging.info("Saving provider configuration to %s", provider_cnf)
337     provider_obj.save(provider_cnf)
338     return provider_cnf
339
340
341 def port_forwarding(src_port="1234", src_port_end="",
342                     dst_port="1234", dst_port_end="",
343                     dst_ip_ref="1", protocol_type="TCP",
344                     suffix="host"):
345     """
346     Generate and save a port forwarding configuration file.
347
348     :param str src_port: forwarded source port
349     :param str src_port_end: forwarded source port end for a port range
350     :param str dst_port: forwarded destination port
351     :param str dst_port_end: forwarded destination port end for a port range
352     :param str dst_ip_ref: destination nic instance for a port range
353     :param str protocol_type: port forwarding protocol type
354     :param str suffix: optional suffix to use for config identification
355     :returns: generated config filename
356     :rtype: str
357     """
358     log.info("Create port forwarding configuration")
359     value_id = "test"
360     portforward_client_cnf = "portforward-%d-%s.cnf" % (time.time(), suffix)
361     return build_cnf("PORT_FORWARDING",
362                      data=value_id,
363                      filename=portforward_client_cnf,
364                      vals=[(Child, ("PORT_FORWARDING_DST_IP_REF", 0, dst_ip_ref)),
365                            (Child, ("PORT_FORWARDING_DST_PORT", 0, dst_port)),
366                            (Child, ("PORT_FORWARDING_DST_PORT_END", 0, dst_port_end)),
367                            (Child, ("PORT_FORWARDING_PROTOCOL_TYPE", 0, protocol_type)),
368                            (Child, ("PORT_FORWARDING_SRC_PORT", 0, src_port)),
369                            (Child, ("PORT_FORWARDING_SRC_PORT_END", 0, src_port_end))])
370
371
372 def firewall_ruleset_simple(suffix="host"):
373     """
374     Generate and save a simple firewall ruleset configuration file.
375
376     :param str suffix: optional suffix to use for config identification
377     :returns: generated config filename
378     :rtype: str
379     """
380     log.info("Create firewall ruleset")
381     fw_cnf = "fw-%d-%s.cnf" % (time.time(), suffix)
382     return build_cnf("FIREWALL_RULESET",
383                      instance=101,
384                      data="Port Forwarding libfirewall test",
385                      filename=fw_cnf,
386                      vals=[(Update, ("FIREWALL_RULESET_PROFILE_TYPE", 0, "SIMPLE_PROVIDER")),
387                            (Update, ("FIREWALL_RULESET_PROVIDER_HTTPS_OPEN", 0, "0")),
388                            (Update, ("FIREWALL_RULESET_PROVIDER_POP3SIMAPS_OPEN", 0, "0")),
389                            (Update, ("FIREWALL_RULESET_PROVIDER_PORT_FORWARDING_ENABLE", 0, "1")),
390                            (Update, ("FIREWALL_RULESET_PROVIDER_SMTP_OPEN", 0, "0")),
391                            (Update, ("FIREWALL_RULESET_PROVIDER_HTTP_OPEN", 0, "0")),
392                            (Update, ("FIREWALL_RULESET_PROVIDER_VPN_OPEN", 0, "0"))])
393
394
395 def firewall_ruleset_port(suffix="host"):
396     """
397     Generate and save a firewall ruleset configuration file for port forwarding.
398
399     :param str suffix: optional suffix to use for config identification
400     :returns: generated config filename
401     :rtype: str
402     """
403     log.info("Create firewall ruleset")
404     fw_portforward_cnf = "fw-portforward-%d-%s.cnf" % (time.time(), suffix)
405     return build_cnf("FIREWALL_RULESET",
406                      instance=100,
407                      data="Port forwarding only",
408                      filename=fw_portforward_cnf,
409                      vals=[(Update, ("FIREWALL_RULESET_AUTOMATIC_ANSWER_RULE", 0, "1")),
410                            (Update, ("FIREWALL_RULESET_PROFILE_TYPE", 0, "FULL")),
411                            (Add, ("FIREWALL_RULESET_RULE", 1, "")),
412                            (Child, ("FIREWALL_RULESET_RULE_ACTION", 0, "ACCEPT")),
413                            (Child, ("FIREWALL_RULESET_RULE_CHECK_CONNECTION_STATUS", 0, "PORTFORWARDING")),
414                            (Child, ("FIREWALL_RULESET_RULE_CHECK_TCP_FLAGS", 0, "DISABLED")),
415                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_FOR_ACTION_ENABLE", 0, "0")),
416                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_FOR_LOG_ENABLE", 0, "0")),
417                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_AVERAGE_COUNT", 0, "")),
418                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_AVERAGE_PERIOD", 0, "SEC")),
419                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_PEAK_COUNT", 0, "")),
420                            (Child, ("FIREWALL_RULESET_RULE_LOG_ENABLE", 0, "0")),
421                            (Child, ("FIREWALL_RULESET_RULE_LOG_MESSAGE", 0, "")),
422                            (Child, ("FIREWALL_RULESET_RULE_TIME_INCLUDE_TIME_REF", 0, "-1")),
423                            (Update, ("FIREWALL_RULESET_USAGE", 0, "PROVIDER"))])
424
425
426 def firewall_ruleset_dmz(suffix="host"):
427     """
428     Generate and save a firewall ruleset configuration file for DMZ.
429
430     :param str suffix: optional suffix to use for config identification
431     :returns: generated config filename
432     :rtype: str
433     """
434     log.info("Create firewall ruleset")
435     fw_dmz_cnf = "fw-dmz-%d-%s.cnf" % (time.time(), suffix)
436     return build_cnf("FIREWALL_RULESET",
437                      instance=100,
438                      data="DMZ firewall rules",
439                      filename=fw_dmz_cnf,
440                      vals=[(Update, ("FIREWALL_RULESET_AUTOMATIC_ANSWER_RULE", 0, "1")),
441                            (Update, ("FIREWALL_RULESET_PROFILE_TYPE", 0, "FULL")),
442                            (Add, ("FIREWALL_RULESET_RULE", 1, "")),
443                            (Child, ("FIREWALL_RULESET_RULE_ACTION", 0, "ACCEPT")),
444                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_FOR_ACTION_ENABLE", 0, "0")),
445                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_FOR_LOG_ENABLE", 0, "0")),
446                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_AVERAGE_COUNT", 0, "")),
447                            (Child, ("FIREWALL_RULESET_RULE_LIMIT_PACKETS_PEAK_COUNT", 0, "")),
448                            (Child, ("FIREWALL_RULESET_RULE_LOG_ENABLE", 0, "0")),
449                            (Child, ("FIREWALL_RULESET_RULE_LOG_MESSAGE", 0, "")),
450                            (Child, ("FIREWALL_RULESET_RULE_SERVICE_INCLUDE_SERVICEGROUP_REF", 0, "6")),
451                            (Child, ("FIREWALL_RULESET_RULE_DST_INCLUDE_CLIENT_REF", 0, "2")),
452                            (Update, ("FIREWALL_RULESET_USAGE", 0, "LANVPN"))])