def check_output_input(*args, **kwargs): if sys.version_info[0] >= 3: return subprocess.check_output(*args, **kwargs) else: if 'stdout' in kwargs: raise ValueError(_('stdout argument not allowed, ' 'it will be overridden.')) if 'input' in kwargs: if 'stdin' in kwargs: raise ValueError(_('stdin and input arguments ' 'may not both be used.')) inputdata = kwargs['input'] del kwargs['input'] kwargs['stdin'] = subprocess.PIPE else: inputdata = None process = subprocess.Popen(*args, stdout=subprocess.PIPE, **kwargs) try: output, unused_err = process.communicate(inputdata) except Exception as e: process.kill() process.wait() raise e retcode = process.poll() if retcode: cmd = kwargs.get("args") if cmd is None: cmd = args[0] raise subprocess.CalledProcessError(retcode, cmd, output=output) return output
def verify(self, signer_requirements, path, sgn_value): """Verify the authenticity of the incoming data :param signer_requirements: what we expect of the key; right now, the CN of the signer :param path: path where the JSON object was found :param sgn_value: The datastructure found at that path :return: confirmed original value from JWT token. :raise A JWTSigningFailed is raised if the verification fails. """ if sgn_value is None: raise JWTSigningFailed( _("Invalid empty value at path %s") % (path)) try: # Load the certificate and verify that it is both a suitable # certificate for this key and one we trust the origin of vcert_str = sgn_value.get("certificate", "") # ("" is an invalid key) # py3.x note: # In some unit tests, vcert_str is returned as type bytes while in # some others it is type str. A bytes-type object is what the # crypto apis expect and hence the following check. # TODO(JB): replace with more elegant solution if possible if type(vcert_str) is str: vcert_str = bytes(vcert_str, 'ascii') # TODO(ijw): how does this fail? vcert_obj = load_pem_x509_certificate(vcert_str, default_backend()) vpublic_key = vcert_obj.public_key() self._check_node_name(signer_requirements, vcert_obj) # TODO(ijw): what checks the cert is signed with the CA? self._verify_certificate(vcert_str) # Unpack the JWT to its raw data jwtok = sgn_value.get("jwt", "") # ("" is an invalid token) dval = jwt.decode(jwtok, vpublic_key, algorithms='RS256') # Check the ancillary tags of the raw data self._check_path(dval, path) # TODO(ijw): check delta # Get and return the originally provided value return dval["value"] except jwt.InvalidTokenError: raise JWTSigningFailed(_("InvalidTokenError: path :%s") % path)
class GpeVNIInUse(n_exc.NeutronException): """GPE network creation failed exception due to the VNI being in use. :param vni_id: The ID of the GPE VNI that's in use. """ message = _("Invalid GPE VNI value %(vni_id)s for allocation " "The VNI is already in use by another GPE network")
def _check_node_name(self, nodeName, vcert_obj): """Check the common name of the signer certificate. Verify the role of the signer certificate matches the expected role of the signer. :param nodeName: A named tuple containing either the expected signer hostname or a regexp to check the signer hostname. :param vcert_obj: The X509 certificate of the signer raise: JWTSigningError if not valid. """ subject_name = vcert_obj.subject commonNames = subject_name.get_attributes_for_oid( oid.NameOID.COMMON_NAME) commonName = commonNames[0] if nodeName.isRegexp: if re.match(nodeName.value, commonName.value): return elif nodeName.value == commonName.value: return raise JWTSigningFailed( _("cert says node name is %(cn)s and we want %(nn)s") % { 'cn': commonName.value, 'nn': str(nodeName.value) })
class GpeVNIInvalid(n_exc.NeutronException): """GPE network creation failed exception due to the VNI being invalid. :param vni_id: The ID of the GPE VNI that's invalid. """ message = _("Invalid GPE VNI value %(vni_id)s for allocation " "or deallocation ")
def _verify_certificate(self, vcert): """Confirm this certificate is in a chain of trust We have a CA, and we want to know we're seeing a certificate that this CA has signed. """ certificate = crypto.load_certificate(crypto.FILETYPE_PEM, vcert) store_ctx = crypto.X509StoreContext(self.store, certificate) result = store_ctx.verify_certificate() if result is not None: raise JWTSigningFailed(_("Certificate is not trusted"))
def _check_path(self, dval, path): """Check the signed path matches where the data was found :param dval: the signed data :param path: the path at which the signed data was stored :raise JWTSigningError: if not valid. """ if (dval["path"] != path): raise JWTSigningFailed( _("path is %(dpth)s in data and we want %(pth)s") % { 'dpth': dval["path"], 'pth': path })
class GpeVNIRangeError(n_exc.NeutronException): """An exception indicating an invalid GPE VNI range was specified. :param vni_range: The invalid vni range specified in the 'start:end' format """ message = _("Invalid VNI range string for the GPE network. Expect a " "string in the form %(vni_range)s") def __init__(self, **kwargs): # Convert the vni_range tuple to 'start:end' format for display if isinstance(kwargs['vni_range'], tuple): kwargs['vni_range'] = "%d:%d" % kwargs['vni_range'] super(GpeVNIRangeError, self).__init__(**kwargs)
def check_output_input(*args, **kwargs): if sys.version_info[0] >= 3: return subprocess.check_output(*args, **kwargs) else: if 'stdout' in kwargs: raise ValueError( _('stdout argument not allowed, ' 'it will be overridden.')) if 'input' in kwargs: if 'stdin' in kwargs: raise ValueError( _('stdin and input arguments ' 'may not both be used.')) inputdata = kwargs['input'] del kwargs['input'] kwargs['stdin'] = subprocess.PIPE else: inputdata = None process = subprocess.Popen(*args, stdout=subprocess.PIPE, **kwargs) try: output, unused_err = process.communicate(inputdata) except Exception as e: process.kill() process.wait() raise e retcode = process.poll() if retcode: cmd = kwargs.get("args") if cmd is None: cmd = args[0] raise subprocess.CalledProcessError(retcode, cmd, output=output) return output
def run(self): """Run indefinitely, calling callbacks when interfaces change This uses just the socket API and so should be friendly with eventlet. Ensure your callbacks are eventlet-safe if you do this. """ def messages(s): """Iterator providing all messages in a netlink stream""" while True: incoming = s.recv(65535) # Work through the messages in this packet while len(incoming) > 0: try: msg_type, flags, seq, pid, data, incoming = \ unpack_nlmsg(incoming) yield msg_type, flags, seq, pid, data except IncompleteMsg: # We seem to have half a message. # This shouldn't happen, so we go with # discarding it and moving on to the next # packet LOG.warning('Received incomplete message from' ' NETLINK, dropping') addr_offset = 0 while True: s = None try: # Create the netlink socket and bind to RTMGRP.LINK messages s = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE) # Our task is to find a unique number for the socket. Other # processes can use whatever number they like, so the offset # is used to manage possible conflicts. while True: try: s.bind((addr_offset << 16 | os.getpid(), RTMGRP.LINK)) break except OSError as e: if e.errno == errno.EADDRINUSE: LOG.warning( 'Trying another address for netlink socket') addr_offset += 1 # Re-issue a 'tell me all your interfaces' request, allowing # us to resync with either initial state or missed change # messages. get_links = pack_linkrequest(NLMSG.RTM_GETLINK, NLM_F.REQUEST | NLM_F.DUMP) s.send(get_links) resync_links = set() for msg_type, flags, seq, pid, data in messages(s): if msg_type == NLMSG.NOOP: # Meh. continue elif msg_type == NLMSG.ERROR: # Force a netlink reset. raise Exception(_("Error received on netlink socket")) elif msg_type == NLMSG.DONE: # We were presumably resyncing, and now we have # everything. # Having processed all of the incoming message, # consider whether we have either new or dead links: LOG.debug('getlink: saw links %s', ', '.join(resync_links)) new_links = resync_links - self.devices dead_links = self.devices - resync_links for f in new_links: self._dev_add(f) for f in dead_links: self._dev_del(f) resync_links = None continue # We're interested in tap devices appearing and # disappearing. Anything else can pass us by. if msg_type not in (NLMSG.RTM_GETLINK, NLMSG.RTM_NEWLINK, NLMSG.RTM_DELLINK): continue if_type, flags, data = unpack_linkmsg(data) link_name = None while len(data) > 0: # This check comes from RTA_OK, and terminates a string # of routing attributes. attr_type, attr_body, data = unpack_attr(data) # Hoorah, a link is up! if attr_type == IFLA.IFNAME: # As returned, includes a C-style \0 link_name = attr_body[:-1] # py3 note: # link_name is a bytes object so explicitly convert # to string in case of py3 otherwise we get an # exception. link_name = link_name.decode('ascii') if link_name is None: raise Exception(_("Add-link message without if name")) if msg_type == NLMSG.RTM_NEWLINK: if resync_links is not None: # We're actually in a dump resync_links.add(link_name) else: self._dev_add(link_name) else: self._dev_del(link_name) except KeyboardInterrupt: raise except Exception: LOG.exception("Unexpected exception in device watching" " thread - resetting") finally: if s is not None: s.close() s = None
# a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from networking_vpp._i18n import _ from oslo_config import cfg vpp_opts = [ cfg.StrOpt('physnets', help=_("Comma-separated list of net-name:interface-name for " "physical connections")), cfg.StrOpt('vxlan_src_addr', help=_("Source address used for VXLAN tunnel packets.")), cfg.StrOpt('vxlan_bcast_addr', help=_("Broadcast address used to set up VXLAN tunnels.")), cfg.StrOpt('vxlan_vrf', help=_("VPP's VRF for the encapped VXLAN packets.")), cfg.StrOpt('etcd_host', default="127.0.0.1", help=_("Etcd host IP address(es) to connect etcd client." "It takes two formats: single IP/host or a multiple " "hosts list with this format: 'IP:Port,IP:Port'. " "e.g: 192.168.1.1:2379,192.168.1.2:2379. If port " "is absent, etcd_port is used.")), cfg.IntOpt('etcd_port', default=4001,
class InvalidEtcHostsConfig(n_exec.NeutronException): message = _("Invalid etc host config. Expect comma-separated list of " "<Host> or <Host:Port> format")
class InvalidEtcHostConfig(n_exec.NeutronException): message = _("Invalid etc host config. Expect an IP or host name in " "the form <Host> or <Host:Port>")
# # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from networking_vpp._i18n import _ from networking_vpp import etcdutils from oslo_config import cfg _vpp_opts = [ cfg.StrOpt('physnets', help=_("Comma-separated list of net-name:interface-name for " "physical connections")), cfg.StrOpt('gpe_src_cidr', default=None, help=_("The source_IP/Mask used for GPE tunnel packets. ")), cfg.StrOpt('gpe_locators', default=None, help=_("The physnet name(s) used as the underlay " "(i.e. locator) interface by GPE. The agent will " "program the GPE source CIDR on this interface " "and will assume that it has Layer3 reachability " "with all other GPE locator interfaces " "specified on compute and network nodes. In the " "current implementation only a single locator " "is supported.")), cfg.IntOpt('etcd_write_time', default=20, help=_("The period of time alloted to etcd write before it is " "timed out.")), cfg.IntOpt('forward_worker_master_lease_time', default=30,
class InvalidEtcdCAConfig(n_exec.NeutronException): message = _("Invalid etcd CA config.")
# Thrown if the directory is not empty, which we error log LOG.error("Directory path:%s is not empty and cannot be deleted", path) except etcd.EtcdKeyNotFound: # Already gone, so not a problem pass # Base connection to etcd, using standard options. _etcd_conn_opts = [ cfg.StrOpt('etcd_host', default="127.0.0.1", help=_("Etcd host IP address(es) to connect etcd client." "It takes two formats: single IP/host or a multiple " "hosts list with this format: 'IP:Port,IP:Port'. " "e.g: 192.168.1.1:2379,192.168.1.2:2379. If port " "is absent, etcd_port is used.")), cfg.IntOpt('etcd_port', default=4001, help=_("Etcd port to connect the etcd client. This can " "be overridden on a per-host basis if the multiple " "host form of etcd_host is used.")), cfg.StrOpt('etcd_user', default=None, help=_("Username for etcd authentication")), cfg.StrOpt('etcd_pass', default=None, secret=True, help=_("Password for etcd authentication")), # TODO(ijw): make false default
def run(self): """Run indefinitely, calling callbacks when interfaces change This uses just the socket API and so should be friendly with eventlet. Ensure your callbacks are eventlet-safe if you do this. """ def messages(s): """Iterator providing all messages in a netlink stream""" while True: incoming = s.recv(65535) # Work through the messages in this packet while len(incoming) > 0: try: msg_type, flags, seq, pid, data, incoming = \ unpack_nlmsg(incoming) yield msg_type, flags, seq, pid, data except IncompleteMsg: # We seem to have half a message. # This shouldn't happen, so we go with # discarding it and moving on to the next # packet LOG.warning('Received incomplete message from' ' NETLINK, dropping') while True: s = None try: # Create the netlink socket and bind to RTMGRP.LINK messages s = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE) s.bind((os.getpid(), RTMGRP.LINK)) # Re-issue a 'tell me all your interfaces' request, allowing # us to resync with either initial state or missed change # messages. get_links = pack_linkrequest(NLMSG.RTM_GETLINK, NLM_F.REQUEST | NLM_F.DUMP) s.send(get_links) resync_links = set() for msg_type, flags, seq, pid, data in messages(s): if msg_type == NLMSG.NOOP: # Meh. continue elif msg_type == NLMSG.ERROR: # Force a netlink reset. raise Exception(_("Error received on netlink socket")) elif msg_type == NLMSG.DONE: # We were presumably resyncing, and now we have # everything. # Having processed all of the incoming message, # consider whether we have either new or dead links: LOG.debug('getlink: saw links %s', ', '.join(resync_links)) new_links = resync_links - self.devices dead_links = self.devices - resync_links for f in new_links: self._dev_add(f) for f in dead_links: self._dev_del(f) resync_links = None continue # We're interested in tap devices appearing and # disappearing. Anything else can pass us by. if msg_type not in (NLMSG.RTM_GETLINK, NLMSG.RTM_NEWLINK, NLMSG.RTM_DELLINK): continue if_type, flags, data = unpack_linkmsg(data) link_name = None while len(data) > 0: # This check comes from RTA_OK, and terminates a string # of routing attributes. attr_type, attr_body, data = unpack_attr(data) # Hoorah, a link is up! if attr_type == IFLA.IFNAME: # As returned, includes a C-style \0 link_name = attr_body[:-1] # py3 note: # link_name is a bytes object so explicitly convert # to string in case of py3 otherwise we get an # exception. if six.PY3: link_name = link_name.decode('ascii') break if link_name is None: raise Exception(_("Add-link message without if name")) if msg_type == NLMSG.RTM_NEWLINK: if resync_links is not None: # We're actually in a dump resync_links.add(link_name) else: self._dev_add(link_name) else: self._dev_del(link_name) except KeyboardInterrupt: raise except Exception: LOG.exception("Unexpected exception in device watching" " thread - resetting") finally: if s is not None: s.close() s = None
self.etcd_client.delete(path, dir=True) except etcd.EtcdNotFile: # Thrown if the directory is not empty, which we error log LOG.error("Directory path:%s is not empty and cannot be deleted", path) except etcd.EtcdKeyNotFound: # Already gone, so not a problem pass # Base connection to etcd, using standard options. _etcd_conn_opts = [ cfg.StrOpt('etcd_host', default="127.0.0.1", help=_("Etcd host IP address(es) to connect etcd client." "It takes two formats: single IP/host or a multiple " "hosts list with this format: 'IP:Port,IP:Port'. " "e.g: 192.168.1.1:2379,192.168.1.2:2379. If port " "is absent, etcd_port is used.")), cfg.IntOpt('etcd_port', default=4001, help=_("Etcd port to connect the etcd client. This can " "be overridden on a per-host basis if the multiple " "host form of etcd_host is used.")), cfg.StrOpt('etcd_user', default=None, help=_("Username for etcd authentication")), cfg.StrOpt('etcd_pass', default=None, help=_("Password for etcd authentication")), # TODO(ijw): make false default cfg.BoolOpt('etcd_insecure_explicit_disable_https', default=True, help=_("Use TLS to access etcd")), cfg.StrOpt('etcd_ca_cert', default=None, help=_("etcd CA certificate file path")),
class GpeVNIUnavailable(n_exc.NeutronException): """GPE network creation failed exception due to a VNI being unavailable. """ message = _("A GPE VNI is unavailable for allocation")