Ejemplo n.º 1
0
 def add_hostname_cn(self):
     """Add a request for the hostname of the machine"""
     ip = local_address(unit_get_fallback='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}
Ejemplo n.º 2
0
def create_ip_cert_links(ssl_dir, custom_hostname_link=None, bindings=None):
    """Create symlinks for SAN records

    :param ssl_dir: str Directory to create symlinks in
    :param custom_hostname_link: str Additional link to be created
    :param bindings: List of bindings to check in addition to default api
                     bindings.
    :type bindings: list of strings
    """

    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()

    # This includes the hostname cert and any specific bindng certs:
    # admin, internal, public
    req = get_certificate_request(json_encode=False, bindings=bindings)["cert_requests"]
    # Specific certs
    for cert_req in req.keys():
        requested_cert = os.path.join(
            ssl_dir,
            'cert_{}'.format(cert_req))
        requested_key = os.path.join(
            ssl_dir,
            'key_{}'.format(cert_req))
        for addr in req[cert_req]['sans']:
            cert = os.path.join(ssl_dir, 'cert_{}'.format(addr))
            key = os.path.join(ssl_dir, 'key_{}'.format(addr))
            if os.path.isfile(requested_cert) and not os.path.isfile(cert):
                os.symlink(requested_cert, cert)
                os.symlink(requested_key, key)

    # Handle custom hostnames
    hostname = get_hostname(local_address(unit_get_fallback='private-address'))
    hostname_cert = os.path.join(
        ssl_dir,
        'cert_{}'.format(hostname))
    hostname_key = os.path.join(
        ssl_dir,
        'key_{}'.format(hostname))
    if custom_hostname_link:
        custom_cert = os.path.join(
            ssl_dir,
            'cert_{}'.format(custom_hostname_link))
        custom_key = os.path.join(
            ssl_dir,
            'key_{}'.format(custom_hostname_link))
        if os.path.isfile(hostname_cert) and not os.path.isfile(custom_cert):
            os.symlink(hostname_cert, custom_cert)
            os.symlink(hostname_key, custom_key)
Ejemplo n.º 3
0
    def get_local_addresses(self):
        """Return list of local addresses on each configured network

        For each network return an address the local unit has on that network
        if one exists.

        :returns: [private_addr, admin_addr, public_addr, ...]
        :rtype: List[str]
        """
        addresses = [
            os_utils.get_host_ip(ch_os_ip.local_address(
                unit_get_fallback='private-address'))]
        for addr_type in os_ip.ADDRESS_MAP.keys():
            laddr = os_ip.resolve_address(endpoint_type=addr_type)
            if laddr:
                addresses.append(laddr)
        return sorted(list(set(addresses)))
Ejemplo n.º 4
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]))
Ejemplo n.º 5
0
def resolve_address(endpoint_type=PUBLIC, override=True):
    """Return unit address depending on net config.

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

    If no vip is configured, 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 = hookenv.config('vip')
    if vips:
        vips = vips.split()

    net_type = ADDRESS_MAP[endpoint_type]['config']
    net_addr = hookenv.config(net_type)
    net_fallback = ADDRESS_MAP[endpoint_type]['fallback']
    binding = ADDRESS_MAP[endpoint_type]['binding']

    if vips:
        if net_addr:
            for vip in vips:
                if net_ip.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 net_ip.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 hookenv.config('prefer-ipv6'):
            fallback_addr = net_ip.get_ipv6_addr(exc_list=vips)[0]
        else:
            fallback_addr = ch_os_ip.local_address(
                unit_get_fallback=net_fallback)

        if net_addr:
            resolved_address = net_ip.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={})".format(net_type))

    return resolved_address