Exemplo n.º 1
0
def configure_link(bgp_info, remote_addr):
    CONF_ROUTER_BGP = ['conf t', 'router bgp {}'.format(quagga.get_asn())]
    EXIT_ROUTER_BGP_WRITE = ['exit', 'exit', 'write']

    vtysh_cmd = copy.deepcopy(CONF_ROUTER_BGP)
    ch_core.hookenv.log('DEBUG: configure neighbour {} '
                        'remote-as {}'
                        ''.format(remote_addr, bgp_info['asn']))
    vtysh_cmd += [
        'neighbor {} remote-as {}'
        ''.format(remote_addr, bgp_info['asn'])
    ]
    if bgp_info['passive']:
        vtysh_cmd += ['neighbor {} passive' ''.format(remote_addr)]
    if ch_net_ip.is_ipv6(remote_addr):
        vtysh_cmd += [
            'no neighbor {} activate'.format(remote_addr),
            'address-family ipv6',
            # workaround for quagga redistribute connected
            # not working as expected for IPv6
            'network {}'.format(ch_net_ip.resolve_network_cidr(remote_addr)),
            'neighbor {} activate'.format(remote_addr),
            'exit',
        ]
    # Exit and write
    vtysh_cmd += EXIT_ROUTER_BGP_WRITE
    # Execute the command
    quagga.vtysh(vtysh_cmd)
Exemplo n.º 2
0
def get_certificate_sans(bindings=None):
    """Get all possible IP addresses for certificate SANs.
    """
    _sans = [unit_get('private-address')]
    if bindings:
        # Add default API bindings to bindings list
        bindings = set(bindings + get_default_api_bindings())
    else:
        # Use default API bindings
        bindings = get_default_api_bindings()

    for binding in bindings:
        # Check for config override
        try:
            net_config = config(ADDRESS_MAP[binding]['config'])
        except KeyError:
            # There is no configuration network for this binding name
            net_config = None
        # Using resolve_address is likely redundant. Keeping it here in
        # case there is an edge case it handles.
        net_addr = resolve_address(endpoint_type=binding)
        ip = get_relation_ip(binding, cidr_network=net_config)
        _sans = _sans + [net_addr, ip]
        vip = get_vip_in_network(resolve_network_cidr(ip))
        if vip:
            _sans.append(vip)
    return set(_sans)
Exemplo n.º 3
0
def get_certificate_request(json_encode=True):
    """Generate a certificatee requests based on the network confioguration

    """
    req = CertRequest(json_encode=json_encode)
    req.add_hostname_cn()
    # Add os-hostname entries
    for net_type in [INTERNAL, ADMIN, PUBLIC]:
        net_config = config(ADDRESS_MAP[net_type]['override'])
        try:
            net_addr = resolve_address(endpoint_type=net_type)
            ip = network_get_primary_address(ADDRESS_MAP[net_type]['binding'])
            addresses = [net_addr, ip]
            vip = get_vip_in_network(resolve_network_cidr(ip))
            if vip:
                addresses.append(vip)
            if net_config:
                req.add_entry(net_type, net_config, addresses)
            else:
                # There is network address with no corresponding hostname.
                # Add the ip to the hostname cert to allow for this.
                req.add_hostname_cn_ip(addresses)
        except NoNetworkBinding:
            log(
                "Skipping request for certificate for ip in {} space, no "
                "local address found".format(net_type), WARNING)
    return req.get_request()
def get_certificate_request(json_encode=True):
    """Generate a certificatee requests based on the network confioguration

    """
    req = CertRequest(json_encode=json_encode)
    req.add_hostname_cn()
    # Add os-hostname entries
    for net_type in [INTERNAL, ADMIN, PUBLIC]:
        net_config = config(ADDRESS_MAP[net_type]['override'])
        try:
            net_addr = resolve_address(endpoint_type=net_type)
            ip = network_get_primary_address(
                ADDRESS_MAP[net_type]['binding'])
            addresses = [net_addr, ip]
            vip = get_vip_in_network(resolve_network_cidr(ip))
            if vip:
                addresses.append(vip)
            if net_config:
                req.add_entry(
                    net_type,
                    net_config,
                    addresses)
            else:
                # There is network address with no corresponding hostname.
                # Add the ip to the hostname cert to allow for this.
                req.add_hostname_cn_ip(addresses)
        except NoNetworkBinding:
            log("Skipping request for certificate for ip in {} space, no "
                "local address found".format(net_type), WARNING)
    return req.get_request()
Exemplo n.º 5
0
def get_db_host(client_hostname, interface='shared-db'):
    """Get address of local database host.

    If an access-network has been configured, expect selected address to be
    on that network. If none can be found, revert to primary address.

    If network spaces are supported (Juju >= 2.0), use network-get to
    retrieve the network binding for the interface.

    If vip(s) are configured, chooses first available.
    """
    vips = config('vip').split() if config('vip') else []
    dns_ha = config('dns-ha')
    access_network = config('access-network')
    client_ip = get_host_ip(client_hostname)
    if is_clustered() and dns_ha:
        log("Using DNS HA hostname: {}".format(config('os-access-hostname')))
        return config('os-access-hostname')
    elif access_network:
        if is_address_in_network(access_network, client_ip):
            if is_clustered():
                for vip in vips:
                    if is_address_in_network(access_network, vip):
                        return vip

                log("Unable to identify a VIP in the access-network '%s'" %
                    (access_network),
                    level=WARNING)
            else:
                return get_address_in_network(access_network)
        else:
            log("Client address '%s' not in access-network '%s'" %
                (client_ip, access_network),
                level=WARNING)
    else:
        try:
            # NOTE(jamespage)
            # Try to use network spaces to resolve binding for
            # interface, and to resolve the VIP associated with
            # the binding if provided.
            interface_binding = network_get_primary_address(interface)
            if is_clustered() and vips:
                interface_cidr = resolve_network_cidr(interface_binding)
                for vip in vips:
                    if is_address_in_network(interface_cidr, vip):
                        return vip
            return interface_binding
        except NotImplementedError:
            # NOTE(jamespage): skip - fallback to previous behaviour
            pass

    if is_clustered() and vips:
        return vips[0]  # NOTE on private network

    if config('prefer-ipv6'):
        return get_ipv6_addr(exc_list=vips)[0]

    return unit_get('private-address')
Exemplo n.º 6
0
 def add_hostname_cn(self):
     """Add a request for the hostname of the machine"""
     ip = unit_get('private-address')
     addresses = [ip]
     # If a vip is being used without os-hostname config or
     # network spaces then we need to ensure the local units
     # cert has the approriate vip in the SAN list
     vip = get_vip_in_network(resolve_network_cidr(ip))
     if vip:
         addresses.append(vip)
     self.hostname_entry = {'cn': get_hostname(ip), 'addresses': addresses}
Exemplo n.º 7
0
def get_certificate_request(json_encode=True, bindings=None):
    """Generate a certificate requests based on the network configuration

    :param json_encode: Encode request in JSON or not. Used for setting
                        directly on a relation.
    :type json_encode: boolean
    :param bindings: List of bindings to check in addition to default api
                     bindings.
    :type bindings: list of strings
    :returns: CertRequest request as dictionary or JSON string.
    :rtype: Union[dict, json]
    """
    if bindings:
        # Add default API bindings to bindings list
        bindings = set(bindings + get_default_api_bindings())
    else:
        # Use default API bindings
        bindings = get_default_api_bindings()
    req = CertRequest(json_encode=json_encode)
    req.add_hostname_cn()
    # Add os-hostname entries
    _sans = get_certificate_sans()

    # Handle specific hostnames per binding
    for binding in bindings:
        hostname_override = config(ADDRESS_MAP[binding]['override'])
        try:
            net_addr = resolve_address(endpoint_type=binding)
            ip = network_get_primary_address(ADDRESS_MAP[binding]['binding'])
            addresses = [net_addr, ip]
            vip = get_vip_in_network(resolve_network_cidr(ip))
            if vip:
                addresses.append(vip)
            # Add hostname certificate request
            if hostname_override:
                req.add_entry(binding, hostname_override, addresses)
            # Remove hostname specific addresses from _sans
            for addr in addresses:
                try:
                    _sans.remove(addr)
                except (ValueError, KeyError):
                    pass

        except NoNetworkBinding:
            log(
                "Skipping request for certificate for ip in {} space, no "
                "local address found".format(binding), WARNING)
    # Gurantee all SANs are covered
    # These are network addresses with no corresponding hostname.
    # Add the ips to the hostname cert to allow for this.
    req.add_hostname_cn_ip(_sans)
    return req.get_request()
def get_db_host(client_hostname, interface='shared-db'):
    """Get address of local database host.

    If an access-network has been configured, expect selected address to be
    on that network. If none can be found, revert to primary address.

    If network spaces are supported (Juju >= 2.0), use network-get to
    retrieve the network binding for the interface.

    If vip(s) are configured, chooses first available.
    """
    vips = config('vip').split() if config('vip') else []
    access_network = config('access-network')
    client_ip = get_host_ip(client_hostname)
    if access_network:
        if is_address_in_network(access_network, client_ip):
            if is_clustered():
                for vip in vips:
                    if is_address_in_network(access_network, vip):
                        return vip

                log("Unable to identify a VIP in the access-network '%s'" %
                    (access_network), level=WARNING)
            else:
                return get_address_in_network(access_network)
        else:
            log("Client address '%s' not in access-network '%s'" %
                (client_ip, access_network), level=WARNING)
    else:
        try:
            # NOTE(jamespage)
            # Try to use network spaces to resolve binding for
            # interface, and to resolve the VIP associated with
            # the binding if provided.
            interface_binding = network_get_primary_address(interface)
            if is_clustered() and vips:
                interface_cidr = resolve_network_cidr(interface_binding)
                for vip in vips:
                    if is_address_in_network(interface_cidr, vip):
                        return vip
            return interface_binding
        except NotImplementedError:
            # NOTE(jamespage): skip - fallback to previous behaviour
            pass

    if is_clustered() and vips:
        return vips[0]  # NOTE on private network

    if config('prefer-ipv6'):
        return get_ipv6_addr(exc_list=vips)[0]

    return unit_get('private-address')
    def cluster_network(self):
        """Get CIDR for the Ceph cluster network.

        The cluster network address advertiesed on the relation is mapped to
        the corrensponding local interface from which we get the netmask/cidr
        of the network.

        :returns: CIDR or None
        :rtype: Option[str, None]
        """
        cluster_addr = self.all_joined_units.received['ceph-cluster-address']
        if cluster_addr:
            return ch_ip.resolve_network_cidr(cluster_addr)
Exemplo n.º 10
0
 def add_hostname_cn(self):
     """Add a request for the hostname of the machine"""
     ip = unit_get('private-address')
     addresses = [ip]
     # If a vip is being used without os-hostname config or
     # network spaces then we need to ensure the local units
     # cert has the approriate vip in the SAN list
     vip = get_vip_in_network(resolve_network_cidr(ip))
     if vip:
         addresses.append(vip)
     self.hostname_entry = {
         'cn': get_hostname(ip),
         'addresses': addresses}
 def access_ip(self):
     vips = config().get('vip')
     if vips:
         vips = vips.split()
     clustered = is_clustered()
     net_addr = ch_net_ip.get_relation_ip('tenant-storage')
     bound_cidr = ch_net_ip.resolve_network_cidr(
         ch_net_ip.network_get_primary_address('tenant-storage'))
     if clustered and vips:
         for vip in vips:
             if ch_net_ip.is_address_in_network(bound_cidr, vip):
                 return vip
     return net_addr
Exemplo n.º 12
0
def get_vip(binding=None):
    vip = hookenv.config('vip')
    if not vip:
        return None

    vips = vip.split()
    if len(vips) == 1:
        return vips[0]

    if not binding:
        binding = 'access'

    bound_cidr = resolve_network_cidr(binding_address(binding))
    for vip in vips:
        if is_address_in_network(bound_cidr, vip):
            return vip

    return None
Exemplo n.º 13
0
    def cluster_network(self):
        """Get CIDR for the Ceph cluster network.

        The cluster network address advertiesed on the relation is mapped to
        the corrensponding local interface from which we get the netmask/cidr
        of the network.

        :returns: CIDR or None
        :rtype: Option[str, None]
        """
        cluster_addr = self.all_joined_units.received['ceph-cluster-address']
        if cluster_addr:
            try:
                return ch_ip.resolve_network_cidr(cluster_addr)
            except AddrFormatError:
                # LP#1898299 in some cases the netmask will be None, which
                # leads to an AddrFormatError. In this case, we should return
                # None
                return None
Exemplo n.º 14
0
    def publish_url(self, vault_url, remote_binding=None):
        """ Publish URL for Vault to all Relations

        :param vault_url: api url used by remote client to speak to vault.
        :param remote_binding: if provided, remote units not using this
                               binding will be ignored.
        """
        for relation in self.relations:
            if remote_binding:
                units = relation.units
                if units:
                    addr = units[0].received['ingress-address'] or \
                        units[0].received['access_address']
                    bound_cidr = resolve_network_cidr(
                        network_get_primary_address(remote_binding))
                    if not (addr and is_address_in_network(bound_cidr, addr)):
                        continue

            relation.to_publish['vault_url'] = vault_url
Exemplo n.º 15
0
def get_certificate_sans(bindings=None):
    """Get all possible IP addresses for certificate SANs.

    :param bindings: List of bindings to check in addition to default api
                     bindings.
    :type bindings: list of strings
    :returns: List of binding string names
    :rtype: List[str]
    """
    _sans = [local_address(unit_get_fallback='private-address')]
    if bindings:
        # Add default API bindings to bindings list
        bindings = list(bindings + get_default_api_bindings())
    else:
        # Use default API bindings
        bindings = get_default_api_bindings()

    for binding in bindings:
        # Check for config override
        try:
            net_config = config(ADDRESS_MAP[binding]['config'])
        except KeyError:
            # There is no configuration network for this binding name
            net_config = None
        # Using resolve_address is likely redundant. Keeping it here in
        # case there is an edge case it handles.
        try:
            net_addr = resolve_address(endpoint_type=binding)
        except KeyError:
            net_addr = None
        ip = get_relation_ip(binding, cidr_network=net_config)
        _sans = _sans + [net_addr, ip]
        vip = get_vip_in_network(resolve_network_cidr(ip))
        if vip:
            _sans.append(vip)
    # Clear any Nones and duplicates
    return list(set([i for i in _sans if i]))
Exemplo n.º 16
0
def resolve_address(endpoint_type=PUBLIC, override=True):
    """Return unit address depending on net config.

    If unit is clustered with vip(s) and has net splits defined, return vip on
    correct network. If clustered with no nets defined, return primary vip.

    If not clustered, return unit address ensuring address is on configured net
    split if one is configured, or a Juju 2.0 extra-binding has been used.

    :param endpoint_type: Network endpoing type
    :param override: Accept hostname overrides or not
    """
    resolved_address = None
    if override:
        resolved_address = _get_address_override(endpoint_type)
        if resolved_address:
            return resolved_address

    vips = config('vip')
    if vips:
        vips = vips.split()

    net_type = ADDRESS_MAP[endpoint_type]['config']
    net_addr = config(net_type)
    net_fallback = ADDRESS_MAP[endpoint_type]['fallback']
    binding = ADDRESS_MAP[endpoint_type]['binding']
    clustered = is_clustered()

    if clustered and vips:
        if net_addr:
            for vip in vips:
                if is_address_in_network(net_addr, vip):
                    resolved_address = vip
                    break
        else:
            # NOTE: endeavour to check vips against network space
            #       bindings
            try:
                bound_cidr = resolve_network_cidr(
                    network_get_primary_address(binding)
                )
                for vip in vips:
                    if is_address_in_network(bound_cidr, vip):
                        resolved_address = vip
                        break
            except NotImplementedError:
                # If no net-splits configured and no support for extra
                # bindings/network spaces so we expect a single vip
                resolved_address = vips[0]
    else:
        if config('prefer-ipv6'):
            fallback_addr = get_ipv6_addr(exc_list=vips)[0]
        else:
            fallback_addr = unit_get(net_fallback)

        if net_addr:
            resolved_address = get_address_in_network(net_addr, fallback_addr)
        else:
            # NOTE: only try to use extra bindings if legacy network
            #       configuration is not in use
            try:
                resolved_address = network_get_primary_address(binding)
            except NotImplementedError:
                resolved_address = fallback_addr

    if resolved_address is None:
        raise ValueError("Unable to resolve a suitable IP address based on "
                         "charm state and configuration. (net_type=%s, "
                         "clustered=%s)" % (net_type, clustered))

    return resolved_address
def get_db_host(client_hostname, interface='shared-db'):
    """Get address of local database host for use by db clients

    If an access-network has been configured, expect selected address to be
    on that network. If none can be found, revert to primary address.

    If network spaces are supported (Juju >= 2.0), use network-get to
    retrieve the network binding for the interface.

    If DNSHA is set pass os-access-hostname

    If vip(s) are configured, chooses first available.

    @param client_hostname: hostname of client side relation setting hostname.
                            Only used if access-network is configured
    @param interface: Network space binding to check.
                      Usually the relationship name.
    @returns IP for use with db clients
    """
    vips = config('vip').split() if config('vip') else []
    dns_ha = config('dns-ha')
    access_network = config('access-network')
    if is_clustered() and dns_ha:
        log("Using DNS HA hostname: {}".format(config('os-access-hostname')))
        return config('os-access-hostname')
    elif access_network:
        client_ip = resolve_hostname_to_ip(client_hostname)
        if is_address_in_network(access_network, client_ip):
            if is_clustered():
                for vip in vips:
                    if is_address_in_network(access_network, vip):
                        return vip

                log("Unable to identify a VIP in the access-network '%s'" %
                    (access_network), level=WARNING)
            else:
                return get_address_in_network(access_network)
        else:
            log("Client address '%s' not in access-network '%s'" %
                (client_ip, access_network), level=WARNING)
    else:
        try:
            # NOTE(jamespage)
            # Try to use network spaces to resolve binding for
            # interface, and to resolve the VIP associated with
            # the binding if provided.
            interface_binding = network_get_primary_address(interface)
            if is_clustered() and vips:
                interface_cidr = resolve_network_cidr(interface_binding)
                for vip in vips:
                    if is_address_in_network(interface_cidr, vip):
                        return vip
            return interface_binding
        except NotImplementedError:
            # NOTE(jamespage): skip - fallback to previous behaviour
            pass

    if is_clustered() and vips:
        return vips[0]  # NOTE on private network

    if config('prefer-ipv6'):
        return get_ipv6_addr(exc_list=vips)[0]

    # Last resort
    return unit_get('private-address')