def validate_cfg(self): #*********************************************************************# #* Firewall that the config is not invalid. *# #*********************************************************************# if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self.validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid MetadataPort value : %s" % self.METADATA_PORT, "etcd:/calico/config/MetadataPort") if self.IFACE_PREFIX is None: raise ConfigException("Missing InterfacePrefix value", "etcd:/calico/config/InterfacePrefix") # Log file may be "None" (the literal string, either provided or as # default). In this case no log file should be written. if self.LOGFILE.lower() == "none": # Metadata is not required. self.LOGFILE = None
def validate_cfg(self): #*********************************************************************# #* Firewall that the config is not invalid. *# #*********************************************************************# if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self.validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException( "Invalid MetadataPort value : %s" % self.METADATA_PORT, "etcd:/calico/config/MetadataPort") if self.IFACE_PREFIX is None: raise ConfigException("Missing InterfacePrefix value", "etcd:/calico/config/InterfacePrefix") # Log file may be "None" (the literal string, either provided or as # default). In this case no log file should be written. if self.LOGFILE.lower() == "none": # Metadata is not required. self.LOGFILE = None
def validate_cfg(self): #*********************************************************************# #* Firewall that the config is not invalid. *# #*********************************************************************# if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self.validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException( "Invalid MetadataPort value : %s" % self.METADATA_PORT, self._config_path) #*********************************************************************# #* Now the plugin and ACL manager addresses. These are allowed to be *# #* IP addresses, or DNS resolvable hostnames. *# #*********************************************************************# self.validate_addr("PluginAddress", self.PLUGIN_ADDR) self.validate_addr("ACLAddress", self.ACL_ADDR) #*********************************************************************# #* Bind address must be * or an IPv4 address. We allow hostnames, *# #* but resolve them before use. *# #*********************************************************************# if self.LOCAL_ADDR != "*": self.LOCAL_ADDR = self.validate_addr("LocalAddress", self.LOCAL_ADDR) #*********************************************************************# #* Log file may be "None" (the literal string, either provided or as *# #* default). In this case no log file should be written. *# #*********************************************************************# if self.LOGFILE.lower() == "none": # Metadata is not required. self.LOGFILE = None
def _validate_cfg(self, final=True): """ Firewall that the config is not invalid. Called twice, once when environment variables and config file have been read, and once after those plus the etcd configuration have been read. :param final: Is this after final etcd config has been read? :raises ConfigException """ fields = self.ETCD_ADDR.split(":") if len(fields) != 2: raise ConfigException("Invalid format for field - must be " "hostname:port", self.parameters["EtcdAddr"]) self._validate_addr("EtcdAddr", fields[0]) try: int(fields[1]) except ValueError: raise ConfigException("Invalid port in field", self.parameters["EtcdAddr"]) try: self.LOGLEVFILE = LOGLEVELS[self.LOGLEVFILE.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityFile"]) try: self.LOGLEVSYS = LOGLEVELS[self.LOGLEVSYS.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeveritySys"]) try: self.LOGLEVSCR = LOGLEVELS[self.LOGLEVSCR.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityScreen"]) # Log file may be "None" (the literal string, case insensitive). In # this case no log file should be written. if self.LOGFILE.lower() == "none": self.LOGFILE = None if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self._validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid field value", self.parameters["MetadataPort"]) if self.DEFAULT_INPUT_CHAIN_ACTION not in ("DROP", "RETURN", "ACCEPT"): raise ConfigException( "Invalid field value", self.parameters["DefaultEndpointToHostAction"] ) if not final: # Do not check that unset parameters are defaulted; we have more # config to read. return for name, parameter in self.parameters.iteritems(): if parameter.value is None: # No value, not even a default raise ConfigException("Missing undefaulted value", self.parameters["InterfacePrefix"])
def test_validate_port(self): self.assertFalse(common.validate_port(-1)) self.assertFalse(common.validate_port(0)) self.assertTrue(common.validate_port(3)) self.assertTrue(common.validate_port(3)) self.assertTrue(common.validate_port(65535)) self.assertFalse(common.validate_port(65536)) self.assertFalse(common.validate_port("-1")) self.assertFalse(common.validate_port("0")) self.assertTrue(common.validate_port("3")) self.assertTrue(common.validate_port("3")) self.assertTrue(common.validate_port("65535")) self.assertFalse(common.validate_port("65536")) self.assertFalse(common.validate_port("1-10")) self.assertFalse(common.validate_port("blah"))
def _validate_cfg(self, final=True): """ Firewall that the config is not invalid. Called twice, once when environment variables and config file have been read, and once after those plus the etcd configuration have been read. :param final: Is this after final etcd config has been read? :raises ConfigException """ fields = self.ETCD_ADDR.split(":") if len(fields) != 2: raise ConfigException( "Invalid format for field - must be " "hostname:port", self.parameters["EtcdAddr"]) self._validate_addr("EtcdAddr", fields[0]) try: int(fields[1]) except ValueError: raise ConfigException("Invalid port in field", self.parameters["EtcdAddr"]) try: self.LOGLEVFILE = LOGLEVELS[self.LOGLEVFILE.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityFile"]) try: self.LOGLEVSYS = LOGLEVELS[self.LOGLEVSYS.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeveritySys"]) try: self.LOGLEVSCR = LOGLEVELS[self.LOGLEVSCR.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityScreen"]) # Log file may be "None" (the literal string, case insensitive). In # this case no log file should be written. if self.LOGFILE.lower() == "none": self.LOGFILE = None if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self._validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid field value", self.parameters["MetadataPort"]) if self.DEFAULT_INPUT_CHAIN_ACTION not in ("DROP", "RETURN", "ACCEPT"): raise ConfigException( "Invalid field value", self.parameters["DefaultEndpointToHostAction"]) # For non-positive time values of reporting interval we set both # interval and ttl to 0 - i.e. status reporting is disabled. if self.REPORTING_INTERVAL_SECS <= 0: log.warning("Reporting disabled.") self.REPORTING_TTL_SECS = 0 self.REPORTING_INTERVAL_SECS = 0 # Ensure the TTL is longer than the reporting interval, defaulting # it if not. if (self.REPORTING_TTL_SECS <= self.REPORTING_INTERVAL_SECS or self.REPORTING_TTL_SECS == 0): log.warning("Reporting TTL set to %s.", self.REPORTING_TTL_SECS) self.REPORTING_TTL_SECS = self.REPORTING_INTERVAL_SECS * 5 / 2 if self.ENDPOINT_REPORT_DELAY < 0: log.warning("Endpoint status delay is negative, defaulting to 1.") self.ENDPOINT_REPORT_DELAY = 1 if self.MAX_IPSET_SIZE <= 0: log.warning("Max ipset size is non-positive, defaulting to 2^20.") self.MAX_IPSET_SIZE = 2**20 if not final: # Do not check that unset parameters are defaulted; we have more # config to read. return for parameter in self.parameters.itervalues(): if parameter.value is None: # No value, not even a default raise ConfigException("Missing undefaulted value", parameter)
def _validate_cfg(self, final=True): """ Firewall that the config is not invalid. Called twice, once when environment variables and config file have been read, and once after those plus the etcd configuration have been read. :param final: Is this after final etcd config has been read? :raises ConfigException """ fields = self.ETCD_ADDR.split(":") if len(fields) != 2: raise ConfigException("Invalid format for field - must be " "hostname:port", self.parameters["EtcdAddr"]) self._validate_addr("EtcdAddr", fields[0]) try: int(fields[1]) except ValueError: raise ConfigException("Invalid port in field", self.parameters["EtcdAddr"]) # Set default or python None value for each etcd "none" config value if self.ETCD_SCHEME.lower() == "none": self.ETCD_SCHEME = "http" if self.ETCD_KEY_FILE.lower() == "none": self.ETCD_KEY_FILE = None if self.ETCD_CERT_FILE.lower() == "none": self.ETCD_CERT_FILE = None if self.ETCD_CA_FILE == "none": self.ETCD_CA_FILE = None if self.ETCD_SCHEME == "https": # key and certificate must be both specified or both not specified if bool(self.ETCD_KEY_FILE) != bool(self.ETCD_CERT_FILE): if not self.ETCD_KEY_FILE: raise ConfigException("Missing etcd key file. Key and " "certificate must both be specified " "or both be blank.", self.parameters["EtcdKeyFile"]) else: raise ConfigException("Missing etcd certificate. Key and " "certificate must both be specified " "or both be blank.", self.parameters["EtcdCertFile"]) # Make sure etcd key and certificate are readable if self.ETCD_KEY_FILE and self.ETCD_CERT_FILE: if not (os.path.isfile(self.ETCD_KEY_FILE) and os.access(self.ETCD_KEY_FILE, os.R_OK)): raise ConfigException("Cannot read key file. Key file " "must be a readable path.", self.parameters["EtcdKeyFile"]) if not (os.path.isfile(self.ETCD_CERT_FILE) and os.access(self.ETCD_CERT_FILE, os.R_OK)): raise ConfigException("Cannot read cert file. Cert file " "must be a readable path.", self.parameters["EtcdCertFile"]) # If Certificate Authority cert provided, check it's readable if (self.ETCD_CA_FILE and not (os.path.isfile(self.ETCD_CA_FILE) and os.access(self.ETCD_CA_FILE, os.R_OK))): raise ConfigException("Missing CA certificate or file is " "unreadable. Value must be readable " "file path.", self.parameters["EtcdCaFile"]) elif self.ETCD_SCHEME != "http": raise ConfigException("Invalid protocol scheme. Value must be one " "of: \"\", \"http\", \"https\".", self.parameters["EtcdScheme"]) try: self.LOGLEVFILE = LOGLEVELS[self.LOGLEVFILE.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityFile"]) try: self.LOGLEVSYS = LOGLEVELS[self.LOGLEVSYS.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeveritySys"]) try: self.LOGLEVSCR = LOGLEVELS[self.LOGLEVSCR.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityScreen"]) # Log files may be "None" (the literal string, case insensitive). In # this case no log file should be written. if self.LOGFILE.lower() == "none": self.LOGFILE = None if self.DRIVERLOGFILE.lower() == "none": self.DRIVERLOGFILE = None if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self._validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid field value", self.parameters["MetadataPort"]) if self.DEFAULT_INPUT_CHAIN_ACTION not in ("DROP", "RETURN", "ACCEPT"): raise ConfigException( "Invalid field value", self.parameters["DefaultEndpointToHostAction"] ) # For non-positive time values of reporting interval we set both # interval and ttl to 0 - i.e. status reporting is disabled. if self.REPORTING_INTERVAL_SECS <= 0: log.warning("Reporting disabled.") self.REPORTING_TTL_SECS = 0 self.REPORTING_INTERVAL_SECS = 0 # Ensure the TTL is longer than the reporting interval, defaulting # it if not. if (self.REPORTING_TTL_SECS <= self.REPORTING_INTERVAL_SECS or self.REPORTING_TTL_SECS == 0): log.warning("Reporting TTL set to %s.", self.REPORTING_TTL_SECS) self.REPORTING_TTL_SECS = self.REPORTING_INTERVAL_SECS * 5/2 if self.ENDPOINT_REPORT_DELAY < 0: log.warning("Endpoint status delay is negative, defaulting to 1.") self.ENDPOINT_REPORT_DELAY = 1 if self.MAX_IPSET_SIZE <= 0: log.warning("Max ipset size is non-positive, defaulting to 2^20.") self.MAX_IPSET_SIZE = 2**20 if not final: # Do not check that unset parameters are defaulted; we have more # config to read. return for parameter in self.parameters.itervalues(): if parameter.value is None: # No value, not even a default raise ConfigException("Missing undefaulted value", parameter)
def _validate_cfg(self, final=True): """ Firewall that the config is not invalid. Called twice, once when environment variables and config file have been read, and once after those plus the etcd configuration have been read. :param final: Is this after final etcd config has been read? :raises ConfigException """ # Set default or python None value for each etcd "none" config value if self.ETCD_SCHEME.lower() == "none": self.ETCD_SCHEME = "http" if self.ETCD_KEY_FILE.lower() == "none": self.ETCD_KEY_FILE = None if self.ETCD_CERT_FILE.lower() == "none": self.ETCD_CERT_FILE = None if self.ETCD_CA_FILE == "none": self.ETCD_CA_FILE = None # Determine which etcd scheme and addresses will be used. addrs = [] addr_opt = None scheme = None scheme_opt = None if self.ETCD_ENDPOINTS != "": addr_opt = "EtcdEndpoints" scheme_opt = "EtcdEndpoints" endpoints = [x.strip() for x in self.ETCD_ENDPOINTS.split(",")] try: for e in endpoints: s, a = e.split("://") addrs.append(a) if scheme == None: scheme = s else: if scheme != s: raise ConfigException("Inconsistent protocols in " "EtcdEndpoints.", self.parameters[scheme_opt]) except ValueError: raise ConfigException("Invalid format of EtcdEndpoints, must " "be `ENDPOINT[,ENDPOINT][,...]` where " "ENDPOINT:=`http[s]://ADDRESS:PORT`.", self.parameters[scheme_opt]) else: addr_opt = "EtcdAddr" scheme_opt = "EtcdScheme" addrs = [self.parameters["EtcdAddr"].value] scheme = self.ETCD_SCHEME for addr in addrs: fields = addr.split(":") if len(fields) != 2: raise ConfigException("Invalid format for field - must be " "hostname:port", self.parameters[addr_opt]) self._validate_addr(addr_opt, fields[0]) try: int(fields[1]) except ValueError: raise ConfigException("Invalid port in field", self.parameters[addr_opt]) if scheme == "https": # key and certificate must be both specified or both not specified if bool(self.ETCD_KEY_FILE) != bool(self.ETCD_CERT_FILE): if not self.ETCD_KEY_FILE: raise ConfigException("Missing etcd key file. Key and " "certificate must both be specified " "or both be blank.", self.parameters["EtcdKeyFile"]) else: raise ConfigException("Missing etcd certificate. Key and " "certificate must both be specified " "or both be blank.", self.parameters["EtcdCertFile"]) # Make sure etcd key and certificate are readable if self.ETCD_KEY_FILE and self.ETCD_CERT_FILE: if not (os.path.isfile(self.ETCD_KEY_FILE) and os.access(self.ETCD_KEY_FILE, os.R_OK)): raise ConfigException("Cannot read key file. Key file " "must be a readable path.", self.parameters["EtcdKeyFile"]) if not (os.path.isfile(self.ETCD_CERT_FILE) and os.access(self.ETCD_CERT_FILE, os.R_OK)): raise ConfigException("Cannot read cert file. Cert file " "must be a readable path.", self.parameters["EtcdCertFile"]) # If Certificate Authority cert provided, check it's readable if (self.ETCD_CA_FILE and not (os.path.isfile(self.ETCD_CA_FILE) and os.access(self.ETCD_CA_FILE, os.R_OK))): raise ConfigException("Missing CA certificate or file is " "unreadable. Value must be readable " "file path.", self.parameters["EtcdCaFile"]) elif scheme != "http": raise ConfigException("Invalid protocol scheme. Value must be one " "of: \"\", \"http\", \"https\".", self.parameters[scheme_opt]) try: self.LOGLEVFILE = LOGLEVELS[self.LOGLEVFILE.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityFile"]) try: self.LOGLEVSYS = LOGLEVELS[self.LOGLEVSYS.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeveritySys"]) try: self.LOGLEVSCR = LOGLEVELS[self.LOGLEVSCR.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityScreen"]) # Log files may be "None" (the literal string, case insensitive). In # this case no log file should be written. if self.LOGFILE.lower() == "none": self.LOGFILE = None if self.DRIVERLOGFILE.lower() == "none": self.DRIVERLOGFILE = None if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self._validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid field value", self.parameters["MetadataPort"]) if self.IP_IN_IP_ADDR.lower() == "none": # IP-in-IP tunnel address is not required. self.IP_IN_IP_ADDR = None else: # IP-in-IP tunnel address must be a valid IP address if # supplied. self.IP_IN_IP_ADDR = self._validate_addr("IpInIpTunnelAddr", self.IP_IN_IP_ADDR) if self.DEFAULT_INPUT_CHAIN_ACTION not in ("DROP", "RETURN", "ACCEPT"): raise ConfigException( "Invalid field value", self.parameters["DefaultEndpointToHostAction"] ) if self.ACTION_ON_DROP not in ("DROP", "LOG-and-DROP", "ACCEPT", "LOG-and-ACCEPT"): log.warning("Unknown setting for DropActionOverride setting: %s, " "defaulting to 'DROP'.", self.ACTION_ON_DROP) self.ACTION_ON_DROP = "DROP" if self.ACTION_ON_DROP.endswith("ACCEPT"): log.warning("Security disabled! DropActionOverride set to ACCEPT " "or LOG-and-ACCEPT. DROP rules will be replaced with" "ACCEPT rules. ") # For non-positive time values of reporting interval we set both # interval and ttl to 0 - i.e. status reporting is disabled. if self.REPORTING_INTERVAL_SECS <= 0: log.warning("Reporting disabled.") self.REPORTING_TTL_SECS = 0 self.REPORTING_INTERVAL_SECS = 0 # Ensure the TTL is longer than the reporting interval, defaulting # it if not. if (self.REPORTING_TTL_SECS <= self.REPORTING_INTERVAL_SECS or self.REPORTING_TTL_SECS == 0): log.warning("Reporting TTL set to %s.", self.REPORTING_TTL_SECS) self.REPORTING_TTL_SECS = self.REPORTING_INTERVAL_SECS * 5/2 if self.ENDPOINT_REPORT_DELAY < 0: log.warning("Endpoint status delay is negative, defaulting to 1.") self.ENDPOINT_REPORT_DELAY = 1 if self.HOST_IF_POLL_INTERVAL_SECS < 0: log.warning("Host interface poll interval is negative, " "defaulting to 10s.") self.HOST_IF_POLL_INTERVAL_SECS = 10 if self.MAX_IPSET_SIZE <= 0: log.warning("Max ipset size is non-positive, defaulting to 2^20.") self.MAX_IPSET_SIZE = 2**20 if self.IPTABLES_MARK_MASK <= 0: log.warning("Iptables mark mask contains insufficient bits, " "defaulting to 0xff000000") self.IPTABLES_MARK_MASK = 0xff000000 if self.IPTABLES_MARK_MASK > 0xffffffff: log.warning("Iptables mark mask out of range, " "defaulting to 0xff000000") self.IPTABLES_MARK_MASK = 0xff000000 if not 0 < self.PROM_METRICS_PORT < 65536: log.warning("Prometheus port out-of-range, defaulting to 9091") self.PROM_METRICS_PORT = 9091 if not 0 < self.PROM_METRICS_DRIVER_PORT < 65536: log.warning("Etcd driver Prometheus port out-of-range, " "defaulting to 9092") self.PROM_METRICS_DRIVER_PORT = 9092 for name, ports in [ ("FailsafeInboundHostPorts", self.FAILSAFE_INBOUND_PORTS), ("FailsafeOutboundHostPorts", self.FAILSAFE_OUTBOUND_PORTS)]: for p in ports: if not 0 < p < 65536: raise ConfigException("Out-of-range port %s" % p, self.parameters[name]) if not final: # Do not check that unset parameters are defaulted; we have more # config to read. return for parameter in self.parameters.itervalues(): if parameter.value is None: # No value, not even a default raise ConfigException("Missing undefaulted value", parameter)
def _validate_cfg(self, final=True): """ Firewall that the config is not invalid. Called twice, once when environment variables and config file have been read, and once after those plus the etcd configuration have been read. :param final: Is this after final etcd config has been read? :raises ConfigException """ fields = self.ETCD_ADDR.split(":") if len(fields) != 2: raise ConfigException( "Invalid format for field - must be " "hostname:port", self.parameters["EtcdAddr"]) self._validate_addr("EtcdAddr", fields[0]) try: int(fields[1]) except ValueError: raise ConfigException("Invalid port in field", self.parameters["EtcdAddr"]) try: self.LOGLEVFILE = LOGLEVELS[self.LOGLEVFILE.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityFile"]) try: self.LOGLEVSYS = LOGLEVELS[self.LOGLEVSYS.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeveritySys"]) try: self.LOGLEVSCR = LOGLEVELS[self.LOGLEVSCR.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityScreen"]) # Log file may be "None" (the literal string, case insensitive). In # this case no log file should be written. if self.LOGFILE.lower() == "none": self.LOGFILE = None if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self._validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid field value", self.parameters["MetadataPort"]) if self.DEFAULT_INPUT_CHAIN_ACTION not in ("DROP", "RETURN", "ACCEPT"): raise ConfigException( "Invalid field value", self.parameters["DefaultEndpointToHostAction"]) if not final: # Do not check that unset parameters are defaulted; we have more # config to read. return for name, parameter in self.parameters.iteritems(): if parameter.value is None: # No value, not even a default raise ConfigException("Missing undefaulted value", self.parameters["InterfacePrefix"])
def _validate_cfg(self, final=True): """ Firewall that the config is not invalid. Called twice, once when environment variables and config file have been read, and once after those plus the etcd configuration have been read. :param final: Is this after final etcd config has been read? :raises ConfigException """ # Set default or python None value for each etcd "none" config value if self.ETCD_SCHEME.lower() == "none": self.ETCD_SCHEME = "http" if self.ETCD_KEY_FILE.lower() == "none": self.ETCD_KEY_FILE = None if self.ETCD_CERT_FILE.lower() == "none": self.ETCD_CERT_FILE = None if self.ETCD_CA_FILE == "none": self.ETCD_CA_FILE = None # Determine which etcd scheme and addresses will be used. addrs = [] addr_opt = None scheme = None scheme_opt = None if self.ETCD_ENDPOINTS != "": addr_opt = "EtcdEndpoints" scheme_opt = "EtcdEndpoints" endpoints = [x.strip() for x in self.ETCD_ENDPOINTS.split(",")] try: for e in endpoints: s, a = e.split("://") addrs.append(a) if scheme == None: scheme = s else: if scheme != s: raise ConfigException("Inconsistent protocols in " "EtcdEndpoints.", self.parameters[scheme_opt]) except ValueError: raise ConfigException("Invalid format of EtcdEndpoints, must " "be `ENDPOINT[,ENDPOINT][,...]` where " "ENDPOINT:=`http[s]://ADDRESS:PORT`.", self.parameters[scheme_opt]) else: addr_opt = "EtcdAddr" scheme_opt = "EtcdScheme" addrs = [self.parameters["EtcdAddr"].value] scheme = self.ETCD_SCHEME for addr in addrs: fields = addr.split(":") if len(fields) != 2: raise ConfigException("Invalid format for field - must be " "hostname:port", self.parameters[addr_opt]) self._validate_addr(addr_opt, fields[0]) try: int(fields[1]) except ValueError: raise ConfigException("Invalid port in field", self.parameters[addr_opt]) if scheme == "https": # key and certificate must be both specified or both not specified if bool(self.ETCD_KEY_FILE) != bool(self.ETCD_CERT_FILE): if not self.ETCD_KEY_FILE: raise ConfigException("Missing etcd key file. Key and " "certificate must both be specified " "or both be blank.", self.parameters["EtcdKeyFile"]) else: raise ConfigException("Missing etcd certificate. Key and " "certificate must both be specified " "or both be blank.", self.parameters["EtcdCertFile"]) # Make sure etcd key and certificate are readable if self.ETCD_KEY_FILE and self.ETCD_CERT_FILE: if not (os.path.isfile(self.ETCD_KEY_FILE) and os.access(self.ETCD_KEY_FILE, os.R_OK)): raise ConfigException("Cannot read key file. Key file " "must be a readable path.", self.parameters["EtcdKeyFile"]) if not (os.path.isfile(self.ETCD_CERT_FILE) and os.access(self.ETCD_CERT_FILE, os.R_OK)): raise ConfigException("Cannot read cert file. Cert file " "must be a readable path.", self.parameters["EtcdCertFile"]) # If Certificate Authority cert provided, check it's readable if (self.ETCD_CA_FILE and not (os.path.isfile(self.ETCD_CA_FILE) and os.access(self.ETCD_CA_FILE, os.R_OK))): raise ConfigException("Missing CA certificate or file is " "unreadable. Value must be readable " "file path.", self.parameters["EtcdCaFile"]) elif scheme != "http": raise ConfigException("Invalid protocol scheme. Value must be one " "of: \"\", \"http\", \"https\".", self.parameters[scheme_opt]) try: self.LOGLEVFILE = LOGLEVELS[self.LOGLEVFILE.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityFile"]) try: self.LOGLEVSYS = LOGLEVELS[self.LOGLEVSYS.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeveritySys"]) try: self.LOGLEVSCR = LOGLEVELS[self.LOGLEVSCR.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityScreen"]) # Log files may be "None" (the literal string, case insensitive). In # this case no log file should be written. if self.LOGFILE.lower() == "none": self.LOGFILE = None if self.DRIVERLOGFILE.lower() == "none": self.DRIVERLOGFILE = None if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self._validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid field value", self.parameters["MetadataPort"]) if self.IP_IN_IP_ADDR.lower() == "none": # IP-in-IP tunnel address is not required. self.IP_IN_IP_ADDR = None else: # IP-in-IP tunnel address must be a valid IP address if # supplied. self.IP_IN_IP_ADDR = self._validate_addr("IpInIpTunnelAddr", self.IP_IN_IP_ADDR) if self.DEFAULT_INPUT_CHAIN_ACTION not in ("DROP", "RETURN", "ACCEPT"): raise ConfigException( "Invalid field value", self.parameters["DefaultEndpointToHostAction"] ) # For non-positive time values of reporting interval we set both # interval and ttl to 0 - i.e. status reporting is disabled. if self.REPORTING_INTERVAL_SECS <= 0: log.warning("Reporting disabled.") self.REPORTING_TTL_SECS = 0 self.REPORTING_INTERVAL_SECS = 0 # Ensure the TTL is longer than the reporting interval, defaulting # it if not. if (self.REPORTING_TTL_SECS <= self.REPORTING_INTERVAL_SECS or self.REPORTING_TTL_SECS == 0): log.warning("Reporting TTL set to %s.", self.REPORTING_TTL_SECS) self.REPORTING_TTL_SECS = self.REPORTING_INTERVAL_SECS * 5/2 if self.ENDPOINT_REPORT_DELAY < 0: log.warning("Endpoint status delay is negative, defaulting to 1.") self.ENDPOINT_REPORT_DELAY = 1 if self.HOST_IF_POLL_INTERVAL_SECS < 0: log.warning("Host interface poll interval is negative, " "defaulting to 10s.") self.HOST_IF_POLL_INTERVAL_SECS = 10 if self.MAX_IPSET_SIZE <= 0: log.warning("Max ipset size is non-positive, defaulting to 2^20.") self.MAX_IPSET_SIZE = 2**20 if self.IPTABLES_MARK_MASK <= 0: log.warning("Iptables mark mask contains insufficient bits, " "defaulting to 0xff000000") self.IPTABLES_MARK_MASK = 0xff000000 if self.IPTABLES_MARK_MASK > 0xffffffff: log.warning("Iptables mark mask out of range, " "defaulting to 0xff000000") self.IPTABLES_MARK_MASK = 0xff000000 if not 0 < self.PROM_METRICS_PORT < 65536: log.warning("Prometheus port out-of-range, defaulting to 9091") self.PROM_METRICS_PORT = 9091 if not 0 < self.PROM_METRICS_DRIVER_PORT < 65536: log.warning("Etcd driver Prometheus port out-of-range, " "defaulting to 9092") self.PROM_METRICS_DRIVER_PORT = 9092 for name, ports in [ ("FailsafeInboundHostPorts", self.FAILSAFE_INBOUND_PORTS), ("FailsafeOutboundHostPorts", self.FAILSAFE_OUTBOUND_PORTS)]: for p in ports: if not 0 < p < 65536: raise ConfigException("Out-of-range port %s" % p, self.parameters[name]) if not final: # Do not check that unset parameters are defaulted; we have more # config to read. return for parameter in self.parameters.itervalues(): if parameter.value is None: # No value, not even a default raise ConfigException("Missing undefaulted value", parameter)
def update_ipsets(type, descr, suffix, rule_list, ipset_addr, ipset_port, ipset_icmp, tmp_ipset_addr, tmp_ipset_port, tmp_ipset_icmp): """ Update the ipsets with a given set of rules. If a rule is invalid we do not throw an exception or give up, but just log an error and continue. """ for rule in rule_list: if rule.get('cidr') is None: log.error("Invalid %s rule without cidr for %s : %s" % (descr, suffix, rule)) continue #*********************************************************************# #* The ipset format is something like "10.11.1.3,udp:0" *# #* Further valid examples include *# #* 10.11.1.0/24 *# #* 10.11.1.0/24,tcp *# #* 10.11.1.0/24,80 *# #* *# #*********************************************************************# if rule['cidr'].endswith("/0"): #*****************************************************************# #* We have to handle any CIDR with a "/0" specially, since we *# #* split it into two ipsets entries; ipsets cannot have zero *# #* CIDR length in bits. *# #*****************************************************************# if type == IPV4: cidrs = ["0.0.0.0/1", "128.0.0.0/1"] else: cidrs = ["::/1", "8000::/1"] else: cidrs = [rule['cidr']] #*********************************************************************# #* Now handle the protocol. There are three types of protocol. tcp / *# #* sctp /udp / udplite have an optional port. icmp / icmpv6 have an *# #* optional type and code. Anything else doesn't have ports. *# #* *# #* We build the value to insert without the CIDR, then prepend the *# #* CIDR later (since we may need to use two CIDRs). *# #*********************************************************************# protocol = rule.get('protocol') port = rule.get('port') icmp_type = rule.get('icmp_type') icmp_code = rule.get('icmp_code') if protocol is None: if rule.get('port') is not None: # No protocol, so port is not allowed. log.error( "Invalid %s rule with port but no protocol for %s : %s", descr, suffix, rule) continue ipset_value = "" ipset = tmp_ipset_addr elif protocol in ("tcp", "sctp", "udp", "udplite"): if port is None: # ipsets use port 0 to mean "any port" ipset_value = ",%s:0" % (protocol) ipset = tmp_ipset_port elif isinstance(port, list) and len(port) == 2: # List of two ports - port range if (not common.validate_port(str(port[0])) or not common.validate_port(str(port[1])) ): # Port range was not two valid ports. log.error( "Invalid port range in %s rule for %s : %s", descr, suffix, rule) continue ipset_value = ",%s:%s-%s" % (protocol, port[0], port[1]) ipset = tmp_ipset_port else: if not common.validate_port(str(port)): # Port was supplied but was not an integer or range. log.error( "Invalid port in %s rule for %s : %s", descr, suffix, rule) continue # An integer port was specified. ipset_value = ",%s:%s" % (protocol, port) ipset = tmp_ipset_port elif protocol in ("icmp", "icmpv6"): if rule.get('port') is not None: # No protocol, so port is not allowed. log.error( "Invalid %s rule for %s with port for protocol %s : %s", descr, suffix, protocol, rule) continue if (icmp_type is None and icmp_code is not None): # A code but no type - not allowed. log.error( "Invalid %s rule with ICMP code but no type for %s : %s", descr, suffix, rule) continue if icmp_type is None: # No type - all ICMP to / from the cidr, so use the ICMP ipset. ipset_value = "" ipset = tmp_ipset_icmp else: try: # Assume integer ICMP type first. int(icmp_type) if icmp_code is None: # Code defaults to 0 if not supplied. icmp_code = 0 ipset_value = ",%s:%s/%s" % (protocol, icmp_type, icmp_code) ipset = tmp_ipset_port except ValueError: # Not an integer ICMP type - must be a string code name. ipset_value = ",%s:%s" % (protocol, icmp_type) ipset = tmp_ipset_port else: if port is not None: # The supplied protocol does not allow ports. log.error( "Invalid %s rule with port but no protocol for %s : %s", descr, suffix, rule) continue # ipsets use port 0 to mean "any port" ipset_value = ",%s:0" % (protocol) ipset = tmp_ipset_port # Now add those values to the ipsets. for cidr in cidrs: try: ipsets.add(ipset, cidr + ipset_value) except FailedSystemCall: log.exception("Failed to add %s rule (%s) for %s", descr, cidr + ipset_value, suffix) # Now that we have filled the tmp ipset, swap it with the real one. ipsets.swap(tmp_ipset_addr, ipset_addr) ipsets.swap(tmp_ipset_port, ipset_port) ipsets.swap(tmp_ipset_icmp, ipset_icmp) # Get the temporary ipsets clean again - we leave them existing but empty. ipsets.flush(tmp_ipset_port) ipsets.flush(tmp_ipset_addr) ipsets.flush(tmp_ipset_icmp)
def _validate_cfg(self, final=True): """ Firewall that the config is not invalid. Called twice, once when environment variables and config file have been read, and once after those plus the etcd configuration have been read. :param final: Is this after final etcd config has been read? :raises ConfigException """ fields = self.ETCD_ADDR.split(":") if len(fields) != 2: raise ConfigException("Invalid format for field - must be " "hostname:port", self.parameters["EtcdAddr"]) self._validate_addr("EtcdAddr", fields[0]) try: int(fields[1]) except ValueError: raise ConfigException("Invalid port in field", self.parameters["EtcdAddr"]) try: self.LOGLEVFILE = LOGLEVELS[self.LOGLEVFILE.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityFile"]) try: self.LOGLEVSYS = LOGLEVELS[self.LOGLEVSYS.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeveritySys"]) try: self.LOGLEVSCR = LOGLEVELS[self.LOGLEVSCR.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityScreen"]) # Log file may be "None" (the literal string, case insensitive). In # this case no log file should be written. if self.LOGFILE.lower() == "none": self.LOGFILE = None if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self._validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid field value", self.parameters["MetadataPort"]) if self.DEFAULT_INPUT_CHAIN_ACTION not in ("DROP", "RETURN", "ACCEPT"): raise ConfigException( "Invalid field value", self.parameters["DefaultEndpointToHostAction"] ) # For non-positive time values of reporting interval we set both # interval and ttl to 0 - i.e. status reporting is disabled. if self.REPORTING_INTERVAL_SECS <= 0: log.warning("Reporting disabled.") self.REPORTING_TTL_SECS = 0 self.REPORTING_INTERVAL_SECS = 0 # Ensure the TTL is longer than the reporting interval, defaulting # it if not. if (self.REPORTING_TTL_SECS <= self.REPORTING_INTERVAL_SECS or self.REPORTING_TTL_SECS == 0): log.warning("Reporting TTL set to %s.", self.REPORTING_TTL_SECS) self.REPORTING_TTL_SECS = self.REPORTING_INTERVAL_SECS * 5/2 if self.ENDPOINT_REPORT_DELAY < 0: log.warning("Endpoint status delay is negative, defaulting to 1.") self.ENDPOINT_REPORT_DELAY = 1 if self.MAX_IPSET_SIZE <= 0: log.warning("Max ipset size is non-positive, defaulting to 2^20.") self.MAX_IPSET_SIZE = 2**20 if not final: # Do not check that unset parameters are defaulted; we have more # config to read. return for parameter in self.parameters.itervalues(): if parameter.value is None: # No value, not even a default raise ConfigException("Missing undefaulted value", parameter)
def _validate_cfg(self, final=True): """ Firewall that the config is not invalid. Called twice to let plugins register their config before a second call. :param final: Is this after final etcd config has been read? :raises ConfigException """ try: self.LOGLEVFILE = LOGLEVELS[self.LOGLEVFILE.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityFile"]) try: self.LOGLEVSYS = LOGLEVELS[self.LOGLEVSYS.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeveritySys"]) try: self.LOGLEVSCR = LOGLEVELS[self.LOGLEVSCR.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityScreen"]) # Log files may be "None" (the literal string, case insensitive). In # this case no log file should be written. if self.LOGFILE.lower() == "none": self.LOGFILE = None if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self._validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid field value", self.parameters["MetadataPort"]) if self.IP_IN_IP_ADDR.lower() == "none": # IP-in-IP tunnel address is not required. self.IP_IN_IP_ADDR = None else: # IP-in-IP tunnel address must be a valid IP address if # supplied. self.IP_IN_IP_ADDR = self._validate_addr("IpInIpTunnelAddr", self.IP_IN_IP_ADDR) if self.DEFAULT_INPUT_CHAIN_ACTION not in ("DROP", "RETURN", "ACCEPT"): raise ConfigException( "Invalid field value", self.parameters["DefaultEndpointToHostAction"] ) if self.ACTION_ON_DROP not in ("DROP", "LOG-and-DROP", "ACCEPT", "LOG-and-ACCEPT"): log.warning("Unknown setting for DropActionOverride setting: %s, " "defaulting to 'DROP'.", self.ACTION_ON_DROP) self.ACTION_ON_DROP = "DROP" if self.ACTION_ON_DROP.endswith("ACCEPT"): log.warning("Security disabled! DropActionOverride set to ACCEPT " "or LOG-and-ACCEPT. DROP rules will be replaced with" "ACCEPT rules. ") # For non-positive time values of reporting interval we set both # interval and ttl to 0 - i.e. status reporting is disabled. if self.REPORTING_INTERVAL_SECS <= 0: log.warning("Reporting disabled.") self.REPORTING_INTERVAL_SECS = 0 if self.HOST_IF_POLL_INTERVAL_SECS < 0: log.warning("Host interface poll interval is negative, " "defaulting to 10s.") self.HOST_IF_POLL_INTERVAL_SECS = 10 if self.MAX_IPSET_SIZE <= 0: log.warning("Max ipset size is non-positive, defaulting to 2^20.") self.MAX_IPSET_SIZE = 2**20 if self.IPTABLES_MARK_MASK <= 0: log.warning("Iptables mark mask contains insufficient bits, " "defaulting to 0xff000000") self.IPTABLES_MARK_MASK = 0xff000000 if self.IPTABLES_MARK_MASK > 0xffffffff: log.warning("Iptables mark mask out of range, " "defaulting to 0xff000000") self.IPTABLES_MARK_MASK = 0xff000000 if not 0 < self.PROM_METRICS_DRIVER_PORT < 65536: log.warning("Prometheus port out-of-range, " "defaulting to 9092") self.PROM_METRICS_DRIVER_PORT = 9092 for name, ports in [ ("FailsafeInboundHostPorts", self.FAILSAFE_INBOUND_PORTS), ("FailsafeOutboundHostPorts", self.FAILSAFE_OUTBOUND_PORTS)]: for p in ports: if not 0 < p < 65536: raise ConfigException("Out-of-range port %s" % p, self.parameters[name]) if self.IPV6_SUPPORT not in ("true", "false", "auto"): log.warning("Unrecognized value for Ipv6Support (%s), " "defaulting to 'auto'", self.IPV6_SUPPORT) self.IPV6_SUPPORT = "auto" if self.CHAIN_INSERT_MODE not in ("insert", "append"): raise ConfigException( "Invalid field value", self.parameters["ChainInsertMode"] ) if not final: # Do not check that unset parameters are defaulted; we have more # config to read. return for parameter in self.parameters.itervalues(): if parameter.value is None: # No value, not even a default raise ConfigException("Missing undefaulted value", parameter)
def _validate_cfg(self, final=True): """ Firewall that the config is not invalid. Called twice, once when environment variables and config file have been read, and once after those plus the etcd configuration have been read. :param final: Is this after final etcd config has been read? :raises ConfigException """ fields = self.ETCD_ADDR.split(":") if len(fields) != 2: raise ConfigException( "Invalid format for field - must be " "hostname:port", self.parameters["EtcdAddr"]) self._validate_addr("EtcdAddr", fields[0]) try: int(fields[1]) except ValueError: raise ConfigException("Invalid port in field", self.parameters["EtcdAddr"]) # Set default or python None value for each etcd "none" config value if self.ETCD_SCHEME.lower() == "none": self.ETCD_SCHEME = "http" if self.ETCD_KEY_FILE.lower() == "none": self.ETCD_KEY_FILE = None if self.ETCD_CERT_FILE.lower() == "none": self.ETCD_CERT_FILE = None if self.ETCD_CA_FILE == "none": self.ETCD_CA_FILE = None if self.ETCD_SCHEME == "https": # key and certificate must be both specified or both not specified if bool(self.ETCD_KEY_FILE) != bool(self.ETCD_CERT_FILE): if not self.ETCD_KEY_FILE: raise ConfigException( "Missing etcd key file. Key and " "certificate must both be specified " "or both be blank.", self.parameters["EtcdKeyFile"]) else: raise ConfigException( "Missing etcd certificate. Key and " "certificate must both be specified " "or both be blank.", self.parameters["EtcdCertFile"]) # Make sure etcd key and certificate are readable if self.ETCD_KEY_FILE and self.ETCD_CERT_FILE: if not (os.path.isfile(self.ETCD_KEY_FILE) and os.access(self.ETCD_KEY_FILE, os.R_OK)): raise ConfigException( "Cannot read key file. Key file " "must be a readable path.", self.parameters["EtcdKeyFile"]) if not (os.path.isfile(self.ETCD_CERT_FILE) and os.access(self.ETCD_CERT_FILE, os.R_OK)): raise ConfigException( "Cannot read cert file. Cert file " "must be a readable path.", self.parameters["EtcdCertFile"]) # If Certificate Authority cert provided, check it's readable if (self.ETCD_CA_FILE and not (os.path.isfile(self.ETCD_CA_FILE) and os.access(self.ETCD_CA_FILE, os.R_OK))): raise ConfigException( "Missing CA certificate or file is " "unreadable. Value must be readable " "file path.", self.parameters["EtcdCaFile"]) elif self.ETCD_SCHEME != "http": raise ConfigException( "Invalid protocol scheme. Value must be one " "of: \"\", \"http\", \"https\".", self.parameters["EtcdScheme"]) try: self.LOGLEVFILE = LOGLEVELS[self.LOGLEVFILE.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityFile"]) try: self.LOGLEVSYS = LOGLEVELS[self.LOGLEVSYS.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeveritySys"]) try: self.LOGLEVSCR = LOGLEVELS[self.LOGLEVSCR.lower()] except KeyError: raise ConfigException("Invalid log level", self.parameters["LogSeverityScreen"]) # Log files may be "None" (the literal string, case insensitive). In # this case no log file should be written. if self.LOGFILE.lower() == "none": self.LOGFILE = None if self.DRIVERLOGFILE.lower() == "none": self.DRIVERLOGFILE = None if self.METADATA_IP.lower() == "none": # Metadata is not required. self.METADATA_IP = None self.METADATA_PORT = None else: # Metadata must be supplied as IP or address, but we store as IP self.METADATA_IP = self._validate_addr("MetadataAddr", self.METADATA_IP) if not common.validate_port(self.METADATA_PORT): raise ConfigException("Invalid field value", self.parameters["MetadataPort"]) if self.IP_IN_IP_ADDR.lower() == "none": # IP-in-IP tunnel address is not required. self.IP_IN_IP_ADDR = None else: # IP-in-IP tunnel address must be a valid IP address if # supplied. self.IP_IN_IP_ADDR = self._validate_addr("IpInIpTunnelAddr", self.IP_IN_IP_ADDR) if self.DEFAULT_INPUT_CHAIN_ACTION not in ("DROP", "RETURN", "ACCEPT"): raise ConfigException( "Invalid field value", self.parameters["DefaultEndpointToHostAction"]) # For non-positive time values of reporting interval we set both # interval and ttl to 0 - i.e. status reporting is disabled. if self.REPORTING_INTERVAL_SECS <= 0: log.warning("Reporting disabled.") self.REPORTING_TTL_SECS = 0 self.REPORTING_INTERVAL_SECS = 0 # Ensure the TTL is longer than the reporting interval, defaulting # it if not. if (self.REPORTING_TTL_SECS <= self.REPORTING_INTERVAL_SECS or self.REPORTING_TTL_SECS == 0): log.warning("Reporting TTL set to %s.", self.REPORTING_TTL_SECS) self.REPORTING_TTL_SECS = self.REPORTING_INTERVAL_SECS * 5 / 2 if self.ENDPOINT_REPORT_DELAY < 0: log.warning("Endpoint status delay is negative, defaulting to 1.") self.ENDPOINT_REPORT_DELAY = 1 if self.MAX_IPSET_SIZE <= 0: log.warning("Max ipset size is non-positive, defaulting to 2^20.") self.MAX_IPSET_SIZE = 2**20 if self.IPTABLES_MARK_MASK <= 0: log.warning("Iptables mark mask contains insufficient bits, " "defaulting to 0xff000000") self.IPTABLES_MARK_MASK = 0xff000000 if self.IPTABLES_MARK_MASK > 0xffffffff: log.warning("Iptables mark mask out of range, " "defaulting to 0xff000000") self.IPTABLES_MARK_MASK = 0xff000000 if not final: # Do not check that unset parameters are defaulted; we have more # config to read. return for parameter in self.parameters.itervalues(): if parameter.value is None: # No value, not even a default raise ConfigException("Missing undefaulted value", parameter)