def _create_profile_for_netgroup(profile_name): """ Create a profile which allows traffic from other Endpoints in the same profile. """ _log.info("Autocreating profile %s", profile_name) datastore.create_profile(profile_name) prof = datastore.get_profile(profile_name) allow_from_profile = Rule(action="allow", src_tag=profile_name) allow_to_all = Rule(action="allow") prof.rules = Rules(id=profile_name, inbound_rules=[allow_from_profile], outbound_rules=[allow_to_all]) datastore.profile_update_rules(prof)
def _create_profile_for_host_communication(profile_name): """ Create a profile which allows traffic to and from the host. """ _log.info("Autocreating profile %s", profile_name) datastore.create_profile(profile_name) prof = datastore.get_profile(profile_name) host_net = str(_get_host_ip_net()) _log.info("adding accept rule for %s" % host_net) allow_from_slave = Rule(action="allow", src_net=host_net) allow_to_slave = Rule(action="allow", dst_net=host_net) prof.rules = Rules(id=profile_name, inbound_rules=[allow_from_slave], outbound_rules=[allow_to_slave]) datastore.profile_update_rules(prof)
def _create_profile_with_default_mesos_rules(profile): _log.info("Autocreating profile %s", profile) datastore.create_profile(profile) prof = datastore.get_profile(profile) # Set up the profile rules to allow incoming connections from the host # since the slave process will be running there. # Also allow connections from others in the profile. # Deny other connections (default, so not explicitly needed). # TODO: confirm that we're not getting more interfaces than we bargained for ipv4 = get_host_ips(4, exclude=["docker0"]).pop() host_net = str(_get_host_ip_net()) _log.info("adding accept rule for %s" % host_net) allow_slave = Rule(action="allow", src_net=host_net) allow_self = Rule(action="allow", src_tag=profile) allow_all = Rule(action="allow") prof.rules = Rules(id=profile, inbound_rules=[allow_slave, allow_self], outbound_rules=[allow_all]) datastore.profile_update_rules(prof)
def _create_profile_for_public_communication(profile_name): """ Create a public profile which allows open traffic from all. """ _log.info("Creating public profile: %s", profile_name) datastore.create_profile(profile_name) prof = datastore.get_profile(profile_name) allow_all = Rule(action="allow") prof.rules = Rules(id=profile_name, inbound_rules=[allow_all], outbound_rules=[allow_all]) datastore.profile_update_rules(prof)
def profile_rule_add_remove(operation, name, position, action, direction, protocol=None, icmp_type=None, icmp_code=None, src_net=None, src_tag=None, src_ports=None, dst_net=None, dst_tag=None, dst_ports=None): """ Add or remove a rule from a profile. Arguments not documented below are passed through to the rule. :param operation: "add" or "remove". :param name: Name of the profile. :param position: Position to insert/remove rule or None for the default. :param action: Rule action: "allow" or "deny". :param direction: "inbound" or "outbound". :return: """ if icmp_type is not None: icmp_type = int(icmp_type) if icmp_code is not None: icmp_code = int(icmp_code) # Convert the input into a Rule. rule_dict = { k: v for (k, v) in locals().iteritems() if k in Rule.ALLOWED_KEYS and v is not None } rule_dict["action"] = action if (protocol not in ("tcp", "udp")) and (src_ports is not None or dst_ports is not None): print "Ports are not valid with protocol %r" % protocol sys.exit(1) rule = Rule(**rule_dict) # Get the profile. try: nmp = NetworkMappedProfile(name) except KeyError: print "Profile %s not found." % name sys.exit(1) if direction == "inbound": rules = nmp.profile.rules.inbound_rules else: rules = nmp.profile.rules.outbound_rules if operation == "add": if position is None: # Default to append. position = len(rules) + 1 if not 0 < position <= len(rules) + 1: print "Position %s is out-of-range." % position if rule in rules: print "Rule already present, skipping." return rules.insert(position - 1, rule) # Accepts 0 and len(rules). else: # Remove. if position is not None: # Position can only be used on its own so no need to examine the # rule. if 0 < position <= len(rules): # 1-indexed rules.pop(position - 1) else: print "Rule position out-of-range." else: # Attempt to match the rule. try: rules.remove(rule) except ValueError: print "Rule not found." sys.exit(1) nmp.update_rules()
def isolate(cpid, cont_id, ip_str, profile_str): _log.info("Isolating executor with Container ID %s, PID %s.", cont_id, cpid) _log.info("IP: %s, Profile(s) %s", ip_str, profile_str) # Just auto assign ipv4 addresses for now. if ip_str.lower() == "auto": ip = assign_ipv4() else: try: ip = IPAddress(ip_str) except AddrFormatError: _log.warning("IP address %s could not be parsed" % ip_str) sys.exit(1) else: version = "v%s" % ip.version _log.debug('Attempting to assign IP%s address %s', version, ip) pools = datastore.get_ip_pools(version) pool = None for candidate_pool in pools: if ip in candidate_pool: pool = candidate_pool _log.debug('Using IP pool %s', pool) break if not pool: _log.warning( "Requested IP %s isn't in any configured " "pool. Container %s", ip, cont_id) sys.exit(1) if not datastore.assign_address(pool, ip): _log.warning( "IP address couldn't be assigned for " "container %s, IP=%s", cont_id, ip) hostname = socket.gethostname() next_hop_ips = datastore.get_default_next_hops(hostname) endpoint = netns.set_up_endpoint(ip=ip, hostname=hostname, orchestrator_id=ORCHESTRATOR_ID, workload_id=cont_id, cpid=cpid, next_hop_ips=next_hop_ips, veth_name="eth0", proc_alias="/proc") if profile_str == "" or profile_str.lower() == "none": profiles = ["public"] else: parts = profile_str.split(",") profiles = filter(lambda x: len(x) > 0, map(lambda x: x.strip(), parts)) (ipv4, _) = datastore.get_host_ips(hostname) host_net = ipv4 + "/32" allow_slave = Rule(action="allow", src_net=host_net) for profile_id in profiles: if not datastore.profile_exists(profile_id): _log.info("Autocreating profile %s", profile_id) datastore.create_profile(profile_id) prof = datastore.get_profile(profile_id) # Set up the profile rules to allow incoming connections from the # host since the slave process will be running there. # Also allow connections from others in the profile. # Deny other connections (default, so not explicitly needed). allow_self = Rule(action="allow", src_tag=profile_id) allow_all = Rule(action="allow") if profile_id == "public": # 'public' profile is a special case, and we allow anything to # connect to it. prof.rules = Rules(id=profile_id, inbound_rules=[allow_all], outbound_rules=[allow_all]) else: prof.rules = Rules(id=profile_id, inbound_rules=[allow_slave, allow_self], outbound_rules=[allow_all]) datastore.profile_update_rules(prof) else: # Profile already exists. Modify it to accept connections from # this slave if it doesn't already. prof = datastore.get_profile(profile_id) if allow_slave not in prof.rules.inbound_rules: _log.info("Adding %s rule to profile %s", allow_slave.pprint(), profile_id) prof.rules.inbound_rules.append(allow_slave) datastore.profile_update_rules(prof) _log.info("Adding container %s to profile(s) %s", cont_id, profiles) endpoint.profile_ids = profiles _log.info("Finished adding container %s to profiles %s", cont_id, profiles) datastore.set_endpoint(endpoint) _log.info("Finished network for container %s, IP=%s", cont_id, ip)
def isolate(cpid, cont_id, ip_str, profile_str): _log.info("Isolating executor with Container ID %s, PID %s.", cont_id, cpid) _log.info("IP: %s, Profile(s) %s", ip_str, profile_str) # Just auto assign ipv4 addresses for now. if ip_str.lower() == "auto": ip = assign_ipv4() else: try: ip = IPAddress(ip_str) except AddrFormatError: _log.warning("IP address %s could not be parsed" % ip_str) sys.exit(1) else: version = "v%s" % ip.version _log.debug('Attempting to assign IP%s address %s', version, ip) pools = datastore.get_ip_pools(version) pool = None for candidate_pool in pools: if ip in candidate_pool: pool = candidate_pool _log.debug('Using IP pool %s', pool) break if not pool: _log.warning("Requested IP %s isn't in any configured " "pool. Container %s", ip, cont_id) sys.exit(1) if not datastore.assign_address(pool, ip): _log.warning("IP address couldn't be assigned for " "container %s, IP=%s", cont_id, ip) hostname = socket.gethostname() next_hop_ips = datastore.get_default_next_hops(hostname) endpoint = netns.set_up_endpoint(ip=ip, hostname=hostname, orchestrator_id=ORCHESTRATOR_ID, workload_id=cont_id, cpid=cpid, next_hop_ips=next_hop_ips, veth_name="eth0", proc_alias="/proc") if profile_str == "": profiles = ["public"] else: parts = profile_str.split(",") profiles = filter(lambda x: len(x) > 0, map(lambda x: x.strip(), parts)) (ipv4, _) = datastore.get_host_ips(hostname) host_net = ipv4 + "/32" allow_slave = Rule(action="allow", src_net=host_net) for profile_id in profiles: if not datastore.profile_exists(profile_id): _log.info("Autocreating profile %s", profile_id) datastore.create_profile(profile_id) prof = datastore.get_profile(profile_id) # Set up the profile rules to allow incoming connections from the # host since the slave process will be running there. # Also allow connections from others in the profile. # Deny other connections (default, so not explicitly needed). allow_self = Rule(action="allow", src_tag=profile_id) allow_all = Rule(action="allow") if profile_id == "public": # 'public' profile is a special case, and we allow anything to # connect to it. prof.rules = Rules(id=profile_id, inbound_rules=[allow_all], outbound_rules=[allow_all]) else: prof.rules = Rules(id=profile_id, inbound_rules=[allow_slave, allow_self], outbound_rules=[allow_all]) datastore.profile_update_rules(prof) else: # Profile already exists. Modify it to accept connections from # this slave if it doesn't already. prof = datastore.get_profile(profile_id) if allow_slave not in prof.rules.inbound_rules: _log.info("Adding %s rule to profile %s", allow_slave.pprint(), profile_id) prof.rules.inbound_rules.append(allow_slave) datastore.profile_update_rules(prof) _log.info("Adding container %s to profile(s) %s", cont_id, profiles) endpoint.profile_ids = profiles _log.info("Finished adding container %s to profiles %s", cont_id, profiles) datastore.set_endpoint(endpoint) _log.info("Finished network for container %s, IP=%s", cont_id, ip)