Commit 3496fcc2 authored by Morten Knutsen's avatar Morten Knutsen

Support protocol "ip" as a way to open all ports/protocols to a given security group member.

parent 9870f867
......@@ -16,8 +16,11 @@ APP = "nova_sg_configurator"
DESCRIPTION = "Configure ipset based on data from etcd"
IPTABLES_ANY = "-A FORWARD -m set --match-set {} dst,dst -j ACCEPT\n"
IPTABLES_ANY_IP = "-A FORWARD -m set --match-set {} dst -j ACCEPT\n"
IPTABLES_CIDR = "-A FORWARD -m set --match-set {} dst,dst,src -j ACCEPT\n"
IPTABLES_CIDR_IP = "-A FORWARD -m set --match-set {} dst,src -j ACCEPT\n"
IPTABLES_SG = "-A FORWARD -m set --match-set {} src -m set --match-set {} dst,dst -j ACCEPT\n"
IPTABLES_SG_IP = "-A FORWARD -m set --match-set {} src -m set --match-set {} dst -j ACCEPT\n"
IPTABLES_OPEN_GROUP = "-A FORWARD -m set --match-set {0} src -m set --match-set {0} dst -j ACCEPT\n"
......@@ -31,7 +34,7 @@ class Generator(object):
logging.getLogger("").addHandler(handler)
# maps security group id from etcd to the name of a ipset containing its members
self.group_members_groups = {}
# maps security group id from etcd to a ipset containing all rules with this group as source
# maps security group id from etcd to a tuple of ipsets containing all rules with this group as source
self.by_source_groups = {}
self.generation = 0
self.serial = 0
......@@ -64,7 +67,7 @@ class Generator(object):
def add_ipset_member(self, name, member, protocol="tcp", port=None, net=None, source=None):
suffix = ""
if port is not None:
if port is not None and protocol in ['tcp', 'udp']:
suffix += ",{}:{}".format(protocol, port)
if net is not None:
suffix += ",{}".format(net)
......@@ -95,20 +98,34 @@ class Generator(object):
for rule in rules:
for member in members:
if rule["source_type"] == "any":
self.add_ipset_member("rules_from_any", member,
rule["protocol"], rule["destination_port"])
if rule["protocol"] == "ip":
self.add_ipset_member("rules_from_any_to_ip", member,
rule["protocol"])
else:
self.add_ipset_member("rules_from_any", member,
rule["protocol"], rule["destination_port"])
elif rule["source_type"] == "cidr":
self.add_ipset_member("rules_from_cidr", member,
rule["protocol"], rule["destination_port"],
rule["source_cidr"])
if rule["protocol"] == "ip":
self.add_ipset_member("rules_from_cidr_to_ip", member,
rule["protocol"], None, rule["source_cidr"])
else:
self.add_ipset_member("rules_from_cidr", member,
rule["protocol"], rule["destination_port"],
rule["source_cidr"])
elif rule["source_type"] == "security_group":
source_group = rule["source_security_group"]
if not source_group in self.by_source_groups:
setname = self.create_ipset("rules_by_source", "hash:ip,port", True)
self.by_source_groups[source_group] = setname
group_name = self.by_source_groups[source_group]
self.add_ipset_member(group_name, member, rule["protocol"],
rule["destination_port"])
setname_ip = self.create_ipset("rules_by_source_to_ip", "hash:ip", True)
self.by_source_groups[source_group] = (setname, setname_ip)
group_names = self.by_source_groups[source_group]
if rule["protocol"] == "ip":
self.add_ipset_member(group_names[1], member, rule["protocol"])
else:
self.add_ipset_member(group_names[0], member, rule["protocol"],
rule["destination_port"])
else:
logging.warning("Unhandled source type: %s", rule["source_type"])
......@@ -153,7 +170,9 @@ class Generator(object):
self.generation = 0
logging.debug("Building ipsets with generation %d", self.generation)
self.create_ipset("rules_from_any", "hash:ip,port")
self.create_ipset("rules_from_any_to_ip", "hash:ip")
self.create_ipset("rules_from_cidr", "hash:ip,port,net")
self.create_ipset("rules_from_cidr_to_ip", "hash:ip,net")
groups = security_groups.get_security_groups(self.etcd_client)
for group_id, group in groups.items():
self.process_security_group(group_id, group['name'])
......@@ -171,10 +190,19 @@ class Generator(object):
output.write(IPTABLES_ANY.format(from_any))
from_cidr = self.set_name("rules_from_cidr", family)
output.write(IPTABLES_CIDR.format(from_cidr))
for group, ipset in self.by_source_groups.items():
source = self.set_name(self.group_members_groups[group], family)
dest = self.set_name(ipset, family)
output.write(IPTABLES_SG.format(source, dest))
from_any_ip = self.set_name("rules_from_any_to_ip", family)
output.write(IPTABLES_ANY_IP.format(from_any_ip))
from_cidr_ip = self.set_name("rules_from_cidr_to_ip", family)
output.write(IPTABLES_CIDR_IP.format(from_cidr_ip))
for group, ipsets in self.by_source_groups.items():
for ipset in ipsets:
source = self.set_name(self.group_members_groups[group], family)
dest = self.set_name(ipset, family)
if ipset.endswith("_ip"):
output.write(IPTABLES_SG_IP.format(source, dest))
else:
output.write(IPTABLES_SG.format(source, dest))
for group in self.open_groups:
set_name = self.set_name(self.group_members_groups[group], family)
output.write(IPTABLES_OPEN_GROUP.format(set_name))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment