示例#1
0
文件: config.py 项目: nbartos/calico
    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
示例#2
0
文件: config.py 项目: nbartos/calico
    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
示例#3
0
    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
示例#4
0
文件: config.py 项目: rhelfan/calico
    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"])
示例#5
0
 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"))
示例#6
0
文件: config.py 项目: EasonYi/calico
    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)
示例#7
0
文件: config.py 项目: sudeshm/calico
    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)
示例#8
0
    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)
示例#9
0
 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"))
示例#10
0
    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"])
示例#11
0
文件: config.py 项目: is00hcw/calico
    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)
示例#12
0
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)
示例#13
0
文件: config.py 项目: ninefive/calico
    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)
示例#14
0
    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)
示例#15
0
    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)