예제 #1
0
파일: jwe.py 프로젝트: p15r/distributey
def get_wrapped_key_as_jwe(priv_dek: bytearray,
                           tenant: str,
                           jwe_kid: str,
                           nonce: str = '') -> str:
    """Creates a JWE."""
    trace_enter(inspect.currentframe())

    logger.info('Creating JWE token for request with kid "%s"...', jwe_kid)

    # Generate a 256 bit AES content encryption key (32 bytes * 8).
    try:
        cek = bytearray(get_random_bytes(32))
    except Exception as exc:
        ret = ''
        logger.error('Failed to get random bytes: %s', exc)
        trace_exit(inspect.currentframe(), ret)
        return ret

    if config.get_config_by_keypath('DEV_MODE'):
        logger.debug('Generated cek (BYOK AES key): %s (hex)', cek.hex())

    if not (b64_cek_ciphertext := _encrypt_cek_with_key_consumer_key(
            tenant, jwe_kid, cek)):

        logger.error(
            'Cannot encrypt content encryption key with key consumer '
            'key of %s/%s.', tenant, jwe_kid)

        trace_exit(inspect.currentframe(), '')
        return ''
예제 #2
0
파일: jwe.py 프로젝트: p15r/distributey
def _create_jwe_token_json(jwe_kid: str, b64_protected_header: bytes,
                           b64_cek_ciphertext: bytes, b64_iv: bytes,
                           b64_encrypted_dek: bytes, b64_tag: bytes) -> str:
    """
    Creates JWE token according to:
        https://tools.ietf.org/html/rfc7516#section-3.3

    Compact Serialization representation:
        BASE64URL(UTF8(JWE Protected Header)) || '.' ||
        BASE64URL(JWE Encrypted Key) || '.' ||
        BASE64URL(JWE Initialization Vector) || '.' ||
        BASE64URL(JWE Ciphertext) || '.' ||
        BASE64URL(JWE Authentication Tag)
    """
    trace_enter(inspect.currentframe())

    try:
        jwe = b64_protected_header + b'.' + b64_cek_ciphertext + b'.' + \
            b64_iv + b'.' + b64_encrypted_dek + b'.' + b64_tag

        jwe_token = {'kid': jwe_kid, 'jwe': jwe.decode()}

        json_jwe_token = json.dumps(jwe_token)
    except Exception as exc:
        ret = ''
        logger.error('Failed to create JWE token: %s', exc)
        trace_exit(inspect.currentframe(), ret)
        return ret

    logger.debug('Created JWE token: %s', json_jwe_token)

    trace_exit(inspect.currentframe(), json_jwe_token)
    return json_jwe_token
예제 #3
0
파일: jwe.py 프로젝트: p15r/distributey
def _get_key_consumer_cert(tenant: str, jwe_kid: str) -> str:
    """
    Retrieves the key consumer certificate. This cert is used to wrap
    the cek (content encryption key)
    """
    trace_enter(inspect.currentframe())

    # try to fetch dedicated key consumer cert
    key_consumer_cert_path = config.get_key_consumer_cert(tenant, jwe_kid)

    if not key_consumer_cert_path:
        ret = ''
        logger.error(
            'Cannot find dedicated key consumer certificate'
            'nor backend-wide key consumer certificate for'
            '"%s/%s"', tenant, jwe_kid)

        trace_exit(inspect.currentframe(), ret)
        return ret

    try:
        with open(key_consumer_cert_path) as file:
            cert = file.read().strip()
    except Exception as exc:
        ret = ''

        logger.error('Cannot read key consumer certificate at '
                     '"%s": %s.', key_consumer_cert_path, exc)

        trace_exit(inspect.currentframe(), ret)
        return ret

    trace_exit(inspect.currentframe(), cert)
    return cert
예제 #4
0
def get_wrapped_key(view_args: Dict, query_args: Dict, header_args: Dict,
                    **kwargs):
    """
    tenant:     Tenant (key consumer) that makes a request. E.g. Salesforce.
                Mandatory.
    jwe_kid:    kid provided by key consumer. Mandatory.
    nonce:      Nonce (?requestId=x) provided by key consumer
                (to prevent replay attacks). Mandatory.
    """
    trace_enter(inspect.currentframe())

    session['view_args'] = view_args
    session['query_args'] = query_args
    session['header_args'] = header_args

    if _is_replay_attack(query_args['requestId']):
        ret = ''
        err_msg = 'Replay attack detected for nonce: %s' % \
            query_args['requestId']

        app.logger.error(err_msg)

        ret = '{"status": "fail", "output": "%s"}' % err_msg
        trace_exit(inspect.currentframe(), ret)
        _http_error(500, ret)

    if not (token := _authenticate(view_args['tenant'],
                                   header_args['priv_jwt'])):
        if not (jwt_audience := config.get_jwt_audience_by_tenant(
                view_args['tenant'])):
            jwt_audience = 'unknown'
예제 #5
0
def _is_cfg_path_valid(path: str) -> bool:
    """Validates format of config path supplied via env var."""
    trace_enter(inspect.currentframe())

    if not isinstance(path, str):
        logger.error('Config path is not a string.')
        ret = False
        trace_exit(inspect.currentframe(), ret)
        return ret

    max_path_length = 150
    if len(path) > max_path_length:
        logger.error('Config path is longer than %i chars.', max_path_length)
        ret = False
        trace_exit(inspect.currentframe(), ret)
        return ret

    parts = path.split('/')

    path_end = 'config.json'
    if parts[-1] != path_end:
        logger.error('Config path does not end with "%s"', path_end)
        ret = False
        trace_exit(inspect.currentframe(), ret)
        return ret

    ret = True
    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #6
0
def __x_real_ip_validator(x_real_ip: str) -> None:
    """Validates the X-Real-IP header."""
    trace_enter(inspect.currentframe())

    if not 6 < len(x_real_ip) < 16:
        err_msg = 'X-Real-Ip must be between 7 and 15 characters long.'
        logger.error(err_msg)
        trace_exit(inspect.currentframe(), err_msg)
        raise ValidationError(err_msg, status_code=422)

    parts = x_real_ip.split('.')

    if len(parts) != 4:
        err_msg = ('X-Real-Ip format does not match: '
                   'digits.digits.digits.digits.')
        logger.error(err_msg)
        trace_exit(inspect.currentframe(), err_msg)
        raise ValidationError(err_msg, status_code=422)

    for part in parts:
        if not 0 < len(part) < 4:
            err_msg = ('X-Real-Ip format does not match: '
                       'x.x.x.x-xxx.xxx.xxx.xxx')
            logger.error(err_msg)
            trace_exit(inspect.currentframe(), err_msg)
            raise ValidationError(err_msg, status_code=422)
예제 #7
0
def __user_agent_validator(user_agent: str) -> None:
    """
    Validates the user agent header.

    User agent specs: https://developer.mozilla.org/en-US/docs/Web/
        HTTP/Headers/User-Agent

    Enforce a minimum pattern of "uname/version".
    """
    trace_enter(inspect.currentframe())

    if len(user_agent) > 150:
        err_msg = 'User agent contains more than 150 characters.'
        logger.error(err_msg)
        trace_exit(inspect.currentframe(), err_msg)
        raise ValidationError(err_msg, status_code=422)

    parts = user_agent.split('/')

    err_msg = 'User agent pattern does not match "name/version"'
    if len(parts) < 2:
        logger.error(err_msg)
        trace_exit(inspect.currentframe(), err_msg)
        raise ValidationError(err_msg, status_code=422)

    if (len(parts[0]) < 1) or (len(parts[1]) < 1):
        logger.error(err_msg)
        trace_exit(inspect.currentframe(), err_msg)
        raise ValidationError(err_msg, status_code=422)
예제 #8
0
def _get_jwt_from_header(priv_token: str) -> str:
    trace_enter(inspect.currentframe())

    if not priv_token.startswith('Bearer'):
        ret = ''
        app.logger.error('Cannot fetch Bearer token from Authorization '
                         'header.')
        app.logger.debug('Malformed token w/o Bearer: %s', priv_token)
        trace_exit(inspect.currentframe(), ret)
        return ret

    parts = priv_token.split('Bearer')

    if len(parts) != 2:
        ret = ''
        app.logger.error('Token format does not match "Bearer Token".')
        trace_exit(inspect.currentframe(), ret)
        return ret

    if len(parts[1].strip()) == 0:
        ret = ''
        app.logger.error('Found "Bearer" string in auth header, but no JWT.')
        trace_exit(inspect.currentframe(), ret)
        return ret

    ret = parts[1].strip()

    trace_exit(inspect.currentframe(), CAMOUFLAGE_SIGN)
    return ret
예제 #9
0
def get_jwt_issuer_by_tenant(tenant: str) -> str:
    """Returns JWT issuer claim."""
    trace_enter(inspect.currentframe())

    cfg_keypath = f'TENANT_CFG.{tenant}.auth.jwt_issuer'
    ret = get_config_by_keypath(cfg_keypath)

    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #10
0
def get_vault_path_by_tenant_and_kid(tenant: str, jwe_kid: str) -> str:
    """Returns Vault path."""
    trace_enter(inspect.currentframe())

    cfg_keypath = f'TENANT_CFG.{tenant}.backend.{jwe_kid}.vault_path'
    ret = get_config_by_keypath(cfg_keypath)

    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #11
0
def _http_20x(status_code: int, msg: str, headers: dict = None) -> Response:
    trace_enter(inspect.currentframe())

    ret = Response(response=msg,
                   status=status_code,
                   content_type='application/json; charset=utf-8',
                   headers=headers)

    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #12
0
def get_jwt_validation_cert_by_tenant_and_kid(tenant: str,
                                              jwt_kid: str) -> str:
    """Returns JWT validation certificate."""
    trace_enter(inspect.currentframe())

    cfg_keypath = f'TENANT_CFG.{tenant}.auth.jwt_validation_certs.{jwt_kid}'
    ret = get_config_by_keypath(cfg_keypath)

    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #13
0
def _get_dek_from_vault(priv_jwt_token: str, tenant: str,
                        jwe_kid: str) -> bytearray:
    trace_enter(inspect.currentframe())

    if not (vault_path := config.get_vault_path_by_tenant_and_kid(
            tenant, jwe_kid)):
        # kid not found in config,
        # assume kid and vault path are the same
        # and fetch latest version of secret
        vault_path = jwe_kid + ':latest'
예제 #14
0
def get_vault_ca_cert(tenant: str) -> str:
    trace_enter(inspect.currentframe())

    precedence: List[str] = []
    precedence.append(f'TENANT_CFG.{tenant}.backend.VAULT.cacert')
    precedence.append('VAULT.cacert')

    ret = get_config_by_keypath(precedence)

    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #15
0
def _authenticate(tenant: str, priv_auth_header: str) -> str:
    """
    Authentication requires a bearer token in JWT format.
    """
    trace_enter(inspect.currentframe())

    if not (token := _get_jwt_from_header(priv_auth_header)):
        ret = ''
        app.logger.error('Cannot get JWT from request.')
        app.logger.debug('Request header: %s', priv_auth_header)
        trace_exit(inspect.currentframe(), ret)
        return ret
예제 #16
0
def __authenticate_vault_client(client: hvac.Client, tenant: str,
                                priv_jwt_token: str) -> hvac.Client:

    trace_enter(inspect.currentframe())

    vault_auth_jwt_path = config.get_vault_auth_jwt_path(tenant)

    if not vault_auth_jwt_path:
        logger.error('Failed to load auth jwt path for tenant "%s"', tenant)
        return None

    if config.get_config_by_keypath('DEV_MODE'):
        logger.debug('Attempting to authenticate against Vault using JWT: %s',
                     priv_jwt_token)

    cache_id = utils.get_vault_token_cache_id(tenant, priv_jwt_token)

    if cache_id in __VAULT_TOKEN_CACHE:
        logger.debug('Cache hit: Found token for "%s".', cache_id)
        client.token = __VAULT_TOKEN_CACHE[cache_id]
    else:
        logger.debug('Cache miss: Token for "%s" not found.', cache_id)

        token = __get_vault_token(client, tenant, priv_jwt_token,
                                  vault_auth_jwt_path)

        if not token:
            ret = None
            logger.error('Failed to get Vault token.')
            trace_exit(inspect.currentframe(), ret)
            return ret

        client.token = token
        __VAULT_TOKEN_CACHE[cache_id] = token

    if not client.is_authenticated():
        # token might be invalid/has expired
        del __VAULT_TOKEN_CACHE[cache_id]

        ret = None

        logger.error('Failed to validate Vault client. '
                     'Review configuration (config/config.json). '
                     'Retry as token might have expired.')

        trace_exit(inspect.currentframe(), ret)
        return ret

    logger.debug('Successfully authenticated Vault client '
                 'for tenant "%s"', tenant)

    trace_exit(inspect.currentframe(), client)
    return client
예제 #17
0
파일: jwe.py 프로젝트: p15r/distributey
def _encrypt_dek_with_cek(priv_cek: bytearray, initialization_vector: bytes,
                          priv_dek: bytearray,
                          ascii_b64_protected_header: bytes) \
        -> Tuple[bytes, bytes]:
    """
    Wrap dek with cek:
    - Perform authenticated encryption on dek with the AES GCM algorithm.
    - Use cek as encryption key, the initialization vector,
      and the protected header as Additional Authenticated Data value.
    - Request a 128-bit Authentication Tag output.
    """
    trace_enter(inspect.currentframe())

    try:
        # mac_len=16 bytes: 128 bit authentication tag
        dek_cipher = AES.new(priv_cek,
                             AES.MODE_GCM,
                             nonce=initialization_vector,
                             mac_len=16)

        # add additional authenticated data (aad)
        dek_cipher.update(ascii_b64_protected_header)

        # TODO: Autom. padding helpful? Might replace pycryptodome anyway.
        # from Cryptodome.Util.Padding import pad
        # encrypted_dek, tag = \
        #   dek_cipher.encrypt_and_digest(pad(dek, AES.block_size))
        encrypted_dek, tag = dek_cipher.encrypt_and_digest(priv_dek)

        # Remove sensitive data from memory
        del priv_dek[:]
        del priv_cek[:]

        b64_encrypted_dek = base64.urlsafe_b64encode(encrypted_dek)
        b64_tag = base64.urlsafe_b64encode(tag)
    except Exception as exc:
        ret = (b'', b'')
        logger.error('Failed to encrypt dek: %s', exc)
        trace_exit(inspect.currentframe(), ret)
        return ret

    if config.get_config_by_keypath('DEV_MODE'):
        logger.debug('Additional authenticated data (aad): '
                     '%s', ascii_b64_protected_header.decode())
        logger.debug('Encrypted dek: "%s" (hex), '
                     'tag :"%s" (hex).', encrypted_dek.hex(), tag.hex())

    trace_exit(inspect.currentframe(), (b64_encrypted_dek, b64_tag))
    return b64_encrypted_dek, b64_tag
예제 #18
0
파일: jwe.py 프로젝트: p15r/distributey
def _encrypt_cek_with_key_consumer_key(tenant: str, jwe_kid: str,
                                       priv_cek: bytearray) -> bytes:
    trace_enter(inspect.currentframe())

    # Encrypt cek with public key from key consumer using RSAES-OAEP
    # (BASE64URL(JWE Encrypted CEK Key))
    if not (key_consumer_cert := _get_key_consumer_cert(tenant, jwe_kid)):
        ret = b''

        logger.error(
            'Cannot get key consumer certificate for tenant '
            '"%s" with JWE kid "%s".', tenant, jwe_kid)

        trace_exit(inspect.currentframe(), ret)
        return ret
예제 #19
0
def _decode_jwt(tenant: str, priv_jwt_token: str, cert: str) \
        -> Tuple[str, str]:
    """
    The jwt_token must...
    - have a valid signature,
    - contain 'iss' & 'sub' claims
    - not have expired (leeway of 10s for clock skew is tolerated)
    """
    trace_enter(inspect.currentframe())

    if not (aud := config.get_jwt_audience_by_tenant(tenant)):
        app.logger.error(
            'Cannot get JWT audience for tenant "%s" from '
            'config.', tenant)
        trace_exit(inspect.currentframe(), ('', ''))
        _http_error(500, '{"error": "internal error"}')
예제 #20
0
def __get_vault_token(client: hvac.Client, tenant: str, priv_jwt_token: str,
                      vault_auth_jwt_path: str) -> str:

    trace_enter(inspect.currentframe())

    default_role = config.get_vault_default_role(tenant)

    if not default_role:
        logger.error('Failed to load Vault default role for tenant "%s"',
                     tenant)
        return ''

    try:
        response = client.auth.jwt.jwt_login(role=default_role,
                                             jwt=priv_jwt_token,
                                             path=vault_auth_jwt_path)
    except Exception as exc:
        ret = ''
        logger.error('Failed to authenticate against Vault: %s', exc)
        trace_exit(inspect.currentframe(), ret)
        return ret

    if config.get_config_by_keypath('DEV_MODE'):
        logger.debug('Vault login response: %s', response)

    try:
        vault_token = response['auth']['client_token']
    except KeyError as exc:
        ret = ''

        logger.error(
            'Failed to access the Vault token from auth response: '
            'KeyError on key %s. '
            'This is most likely a permission issue.', exc)

        trace_exit(inspect.currentframe(), ret)
        return ret

    if config.get_config_by_keypath('DEV_MODE'):
        logger.debug('Vault client token returned: %s', vault_token)

    logger.debug('Retrieved new Vault token.')

    trace_exit(inspect.currentframe(), CAMOUFLAGE_SIGN)
    return vault_token
예제 #21
0
def get_vault_token_cache_id(tenant: str, priv_token) -> str:
    """
    Returns cache id to reference a Vault token in distributey's IN-MEM cache.
    Cache id is base64 encoded concatenation of `tenant + jwt kid`.
    """
    trace_enter(inspect.currentframe())

    jwt_kid = get_kid_from_jwt(priv_token)
    if not jwt_kid:
        ret = ''
        trace_exit(inspect.currentframe(), ret)
        return ret

    cache_id = f'{tenant}-{jwt_kid}'
    ret = base64.b64encode(cache_id.encode()).decode()

    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #22
0
def get_kid_from_jwt(priv_token: str) -> str:
    """
    Extracts KID from JWT token. Only use this method after JWT token
    has been validated.
    """
    trace_enter(inspect.currentframe())

    try:
        protected_header_unverified = jwt.get_unverified_header(priv_token)
    except jwt.DecodeError as exc:
        ret = ''
        logger.error('Cannot decode JWT to get kid: %s', exc)
        logger.debug('JWT: %s', priv_token)
        trace_exit(inspect.currentframe(), ret)
        return ret

    ret = protected_header_unverified.get('kid', '')
    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #23
0
def get_healthz():
    """
    This healthz implementation adheres to:
        https://tools.ietf.org/html/draft-inadarei-api-health-check-04

    TODO: add user-agent & x-real-ip to input validation &
          flask.session in order to log request properly.
    """
    trace_enter(inspect.currentframe())

    if not config.get_config_by_keypath('LOG_LEVEL'):
        ret = '{"status": "fail", "output": "Config not loaded"}'
        trace_exit(inspect.currentframe(), ret)
        _http_error(500, ret)

    ret = _http_20x(200, '{"status": "pass"}')

    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #24
0
def get_key_consumer_cert(tenant: str, jwe_kid: str) -> str:
    """
    First, attempt fetching key consumer cert specific to a service of a
    tenant. If no specific cert exists, attempt fetching key consumer cert
    specific to tenant(backend-wide cert).
    """
    trace_enter(inspect.currentframe())

    cfg_keypath = f'TENANT_CFG.{tenant}.backend.{jwe_kid}.key_consumer_cert'
    ret = get_config_by_keypath(cfg_keypath)

    if ret:
        trace_exit(inspect.currentframe(), ret)
        return ret

    cfg_keypath = f'TENANT_CFG.{tenant}.backend.backend_wide_key_consumer_cert'
    ret = get_config_by_keypath(cfg_keypath)

    trace_exit(inspect.currentframe(), ret)
    return ret
예제 #25
0
파일: jwe.py 프로젝트: p15r/distributey
def _get_jwe_protected_header(jwe_kid: str, nonce: str) -> bytes:
    """Creates JWE protected header (BASE64URL(UTF8(JWE Protected Header)))."""
    trace_enter(inspect.currentframe())

    protected_header = {'alg': 'RSA-OAEP', 'enc': 'A256GCM', 'kid': jwe_kid}

    if nonce:
        protected_header['jti'] = nonce

    try:
        b64_protected_header = base64.urlsafe_b64encode(
            json.dumps(protected_header).encode('utf-8'))
    except Exception as exc:
        ret = b''
        logger.error('Failed to create protected header: %s', exc)
        trace_exit(inspect.currentframe(), ret)
        return ret

    trace_exit(inspect.currentframe(), b64_protected_header)
    return b64_protected_header
예제 #26
0
def __handle_request_parsing_error(
        validation_error: typeValidationError,
        request: werkzeug.local.LocalProxy,
        schema: SchemaABC,
        error_status_code: int = None,
        error_headers: Mapping[str, str] = None) -> None:
    """Handles errors, or raised exceptions respectively."""
    trace_enter(inspect.currentframe())

    input_data = validation_error.__dict__['data']

    logger.error('Input validation failed with error "%s". '
                 'Input: "%s".', validation_error, input_data)

    resp = Response(response=json.dumps(validation_error.__dict__['messages']),
                    status=422,
                    content_type='application/json; charset=utf-8')

    trace_exit(inspect.currentframe(), resp)
    abort(resp)
예제 #27
0
def __request_id_validator(request_id: str) -> None:
    # Replay attack detection specs of Salesforce's cache-only service:
    # https://developer.salesforce.com/docs/atlas.en-us.securityImplGuide.meta/
    #   securityImplGuide/security_pe_byok_cache_replay.htm
    trace_enter(inspect.currentframe())

    request_id_length = 32

    if len(request_id) != request_id_length:
        err_msg = ('requestId/nonce length must be %s alphanummeric '
                   'chars.' % request_id_length)
        logger.error(err_msg)
        trace_exit(inspect.currentframe(), err_msg)
        raise ValidationError(err_msg, status_code=422)

    result = re.match('^[a-zA-Z0-9]+$', request_id)

    if not result:
        err_msg = ('requestId/nonce must consist of alphanummeric chars only.')
        logger.error(err_msg)
        trace_exit(inspect.currentframe(), err_msg)
        raise ValidationError(err_msg, status_code=422)
예제 #28
0
def _dev_mode_warning_banner() -> None:
    trace_enter(inspect.currentframe())

    dev_mode = config.get_config_by_keypath('DEV_MODE')
    log_level = config.get_config_by_keypath('LOG_LEVEL')

    banner = r"""

      _____  ________      __  __  __  ____  _____  ______
     |  __ \|  ____\ \    / / |  \/  |/ __ \|  __ \|  ____|
     | |  | | |__   \ \  / /  | \  / | |  | | |  | | |__
     | |  | |  __|   \ \/ /   | |\/| | |  | | |  | |  __|
     | |__| | |____   \  /    | |  | | |__| | |__| | |____
     |_____/|______|   \/     |_|  |_|\____/|_____/|______|

     Sensitive data, such as data encryption keys are logged in plain-text.

     """

    if dev_mode and log_level == 'debug':
        app.logger.info(banner)

    trace_exit(inspect.currentframe(), None)
예제 #29
0
def get_config_by_keypath(keypath: Union[str, list]) -> Any:
    """Returns config by key path."""
    trace_enter(inspect.currentframe())

    try:
        with open(__CFG_PATH, 'r') as file:
            cfg = json.load(file)
    except FileNotFoundError as exc:
        ret = False
        logger.error(
            'Config not found. Has "01-fix-cfg-perms.sh" '
            'been executed? %s', exc)
        trace_exit(inspect.currentframe(), ret)
        return ret
    except Exception as exc:
        ret = False
        logger.error('Failed to load config: %s', exc)
        trace_exit(inspect.currentframe(), ret)
        return ret

    # normalize to list
    if isinstance(keypath, str):
        keypath = [keypath]

    for kp in keypath:
        try:
            cfg_value = glom.glom(cfg, kp)
            trace_exit(inspect.currentframe(), cfg_value)
            return cfg_value
        except glom.core.PathAccessError:
            continue

    # no cfg found
    cfg_value = False
    logger.error('Failed to load config at: %s', keypath)
    trace_exit(inspect.currentframe(), cfg_value)
    return cfg_value
예제 #30
0
def _initialize_cache_db() -> bool:
    """Init temporary database to store nonces to prevent replay attacks."""
    trace_enter(inspect.currentframe())

    cache_db = Path(__CACHE_DB)

    if cache_db.is_file():
        ret = True
        trace_exit(inspect.currentframe(), ret)
        return ret

    try:
        # create empty file
        with open(__CACHE_DB, 'a') as file:
            file.write('')
    except Exception as exc:
        ret = False
        app.logger.error('Failed to create cache db: %s', exc)
        trace_exit(inspect.currentframe(), ret)
        return ret

    ret = True
    trace_exit(inspect.currentframe(), ret)
    return ret