From 696fd6a0b69eca18757dc46286cc3fdfe7731771 Mon Sep 17 00:00:00 2001 From: Daniel STAN Date: Thu, 13 Feb 2014 23:05:06 +0100 Subject: [PATCH] munin-node: allow by regex for ipv4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parce que c'est quand-même plus propre avec des cidr, donc on le fait pour les ipv6, au moins. Malheureusement, un bug dans munin/un plugin netaddr de Perl rend l'usage des cidr ipv4 et ipv6 simultanés buggés. Cf: https://bugs.debian.org/cgi-bin/bugreport.cgi?msg=20;bug=645292 Source vers la fonction de conversion cidr ipv4 -> regex: https://chris-lamb.co.uk/posts/matching-ips-regexes-concidrd-harmful --- Python/etc/munin/munin-node.conf | 23 ++++++++++--- etc/python/ip.py | 57 ++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/Python/etc/munin/munin-node.conf b/Python/etc/munin/munin-node.conf index c2ac746..713e2f4 100644 --- a/Python/etc/munin/munin-node.conf +++ b/Python/etc/munin/munin-node.conf @@ -51,15 +51,28 @@ http://munin.projects.linpro.no/wiki/munin-node.conf @# Nom d'hôte reporté au serveur munin print "host_name %s" % munin_hostname @ +@# Attention: allow_cidr ne peut être utilisé à la fois avec des IPv4 et IPv6 +@# (merci munin et debian). Comme c'est vachement mieux d'utiliser des cidr +@# plutôt que des regexp, on utilise les regexp uniquement pour les IPv4 +@# utilisant une fonction de conversion et la directive allow. + +def allow(cidr): + """On fait des regex pour les IPv4 uniquement. Retirer ce kludge + quand cidr_allow sera supporté pour les deux types d'IPs. + Cf https://bugs.debian.org/cgi-bin/bugreport.cgi?msg=20;bug=645292""" + if ':' in cidr: + print "cidr_allow " + cidr + else: + print "allow " + cidr_to_regex(cidr) + if not has("users"): @# On autorise tout adm et localhost - @allow ^127\.0\.0\.1$ - @cidr_allow 127.0.0.0/8 - @cidr_allow ::1/128 + allow('127.0.0.0/8') + allow('::1/128') for net in config.NETs['adm'] + config.prefix['adm']: - print "cidr_allow " + net + allow(net) else: @# On autorise seulement le serveur munin for ip in ips_of_metadata(metadata.query.by_profiles(['munin-server'])): - print "cidr_allow %s/%d" % (ip, (128 if ':' in ip else 32)) + allow(ip + (128 if ':' in ip else 32)) diff --git a/etc/python/ip.py b/etc/python/ip.py index a9ce799..796fab7 100644 --- a/etc/python/ip.py +++ b/etc/python/ip.py @@ -103,3 +103,60 @@ def isolementip(): return ip_vlan[hostname]["vlan-isolement"] else: raise NotImplementedError, "Ce serveur n'a rien a faire sur le VLAN isolement" + +def cidr_to_regex(cidr): + """Get a ipv4 cidr string and return a regexp for it. + https://chris-lamb.co.uk/posts/matching-ips-regexes-concidrd-harmful + """ + ip, prefix = cidr.split('/') + + base = 0 + for val in map(int, ip.split('.')): + base = (base << 8) | val + + shift = 32 - int(prefix) + start = base >> shift << shift + end = start | (1 << shift) - 1 + + def regex(lower, upper): + if lower == upper: + return str(lower) + + from math import log10 + exp = int(log10(upper - lower)) + delta = 10 ** exp + + if lower == 0 and upper == 255: + return "\d+" + + if delta == 1: + val = "" + for a, b in zip(str(lower), str(upper)): + if a == b: + val += str(a) + elif (a, b) == ("0", "9"): + val += '\d' + elif int(b) - int(a) == 1: + val += '[%s%s]' % (a, b) + else: + val += '[%s-%s]' % (a, b) + return val + + def gen_classes(): + floor_ = lambda x: int(round(x / delta, 0) * delta) + + xs = range(floor_(upper) - delta, floor_(lower), -delta) + for x in map(str, xs): + yield '%s%s' % (x[:-exp], r'\d' * exp) + + yield regex(lower, floor_(lower) + (delta - 1)) + yield regex(floor_(upper), upper) + + return '|'.join(gen_classes()) + + def get_parts(): + for x in range(24, -1, -8): + yield regex(start >> x & 255, end >> x & 255) + + return '^%s$' % r'\.'.join(get_parts()) +