Example #1
0
 def wrapper(*args, **kwargs):
     key = f'{decorated.__name__}{args}{kwargs}'
     ret = cache.get(key)
     metrics_tags = [f'function:{decorated.__name__}']
     if ret is None:
         stats.increment('cache.miss', tags=metrics_tags)
         ret = decorated(*args, **kwargs)
         try:
             cache.set(key, ret, timeout=timeout)
         except AttributeError:
             stats.increment('cache.fail', tags=metrics_tags)
             LOG.warn(event='failed to write result to cache', key=key)
     else:
         stats.increment('cache.hit', tags=metrics_tags)
     return ret
Example #2
0
def match_node(node_value: Any, modify=True, sources: SourceData = None, discovery_type: str = 'default') -> SourceData:
    """
    Checks a node against all sources, using the node_match_key and source_match_key
    to determine if the node should receive the source in its configuration.

    :param discovery_type: type of XDS request, used to determine if a scoped source should be evaluated
    :param node_value: value from the node portion of the envoy discovery request
    :param modify: switch to enable or disable modifications via Modifiers
    :param sources: the data sources to match the node against
    """
    if source_metadata.is_stale:
        # Log/emit metric and manually refresh sources.
        stats.increment('sources.stale')
        LOG.warn(
            'Sources have not been refreshed in 2 minutes',
            last_update=source_metadata.updated.isoformat(),
            instance_count=source_metadata.count
        )
        sources_refresh()

    if sources is None:
        sources: SourceData = read_sources()

    ret = SourceData()
    for scope, instances in sources.scopes.items():
        if config.node_matching is False:
            ret.scopes[scope] = instances
            continue

        for instance in instances:
            source_value = extract_source_key(instance)

            # If a single expression evaluates true, the remaining are not evaluated/executed.
            # This saves (a small amount of) computation, which helps when the server starts
            # to receive thousands of requests. The list has been ordered descending by what
            # we think will more commonly be true.
            match = (
                    contains(source_value, node_value)
                    or node_value == source_value
                    or is_wildcard(node_value)
                    or is_wildcard(source_value)
                    or is_debug_request(node_value)
            )
            if match:
                ret.scopes[scope].append(instance)
    if modify:
        return apply_modifications(ret)
    return ret
from sovereign import config
from sovereign.logs import LOG

disabled_suite = namedtuple('DisabledSuite', ['encrypt', 'decrypt'])
disabled_suite.encrypt = lambda x: 'Unavailable (No Secret Key)'
disabled_suite.decrypt = lambda x: 'Unavailable (No Secret Key)'

try:
    _cipher_suite = Fernet(config.encryption_key)
    KEY_AVAILABLE = True
except TypeError:
    KEY_AVAILABLE = False
    _cipher_suite = disabled_suite
except ValueError as e:
    if config.encryption_key != '':
        LOG.warn(
            f'Fernet key was provided, but appears to be invalid: {repr(e)}')
        _cipher_suite = disabled_suite
    KEY_AVAILABLE = False


def encrypt(data: str, key=None) -> str:
    _local_cipher_suite = _cipher_suite
    if key is not None:
        _local_cipher_suite = Fernet(key)
    try:
        encrypted: bytes = _local_cipher_suite.encrypt(data.encode())
    except (InvalidToken, AttributeError):
        raise HTTPException(status_code=400, detail='Encryption failed')
    return encrypted.decode()