Esempio n. 1
0
def decrypt_token(token, _from):
    '''
    Decrypt a token.
    '''
    try:
        token_key = '{0}{1}'.format(hashlib.sha256(token).hexdigest(), _from)
    except Exception:
        raise TokenDecryptionError('Authentication error.')
    if token_key not in TOKENS:
        try:
            token = base64.b64decode(token)
            with stats.timer('kms_decrypt_token'):
                data = kms.decrypt(
                    CiphertextBlob=token,
                    EncryptionContext={
                        # This key is sent to us.
                        'to': app.config['AUTH_CONTEXT'],
                        # From a service.
                        'from': _from
                    })
            # Decrypt doesn't take KeyId as an argument. We need to verify the
            # correct key was used to do the decryption.
            # Annoyingly, the KeyId from the data is actually an arn.
            key_arn = data['KeyId']
            if key_arn != get_key_arn(app.config['AUTH_KEY']):
                raise TokenDecryptionError('Authentication error.')
            plaintext = data['Plaintext']
            payload = json.loads(plaintext)
        # We don't care what exception is thrown. For paranoia's sake, fail
        # here.
        except Exception:
            log.exception('Failed to validate token.')
            raise TokenDecryptionError('Authentication error.')
    else:
        payload = TOKENS[token_key]
    time_format = "%Y%m%dT%H%M%SZ"
    now = datetime.datetime.utcnow()
    try:
        not_before = datetime.datetime.strptime(payload['not_before'],
                                                time_format)
        not_after = datetime.datetime.strptime(payload['not_after'],
                                               time_format)
    except Exception:
        log.exception(
            'Failed to get not_before and not_after from token payload.')
        raise TokenDecryptionError('Authentication error.')
    delta = (not_after - not_before).seconds / 60
    if delta > app.config['AUTH_TOKEN_MAX_LIFETIME']:
        log.warning('Token used which exceeds max token lifetime.')
        raise TokenDecryptionError('Authentication error.')
    if not (now >= not_before) and (now <= not_after):
        log.warning('Expired token used.')
        raise TokenDecryptionError('Authentication error.')
    TOKENS[token_key] = payload
    return payload
Esempio n. 2
0
def _get_credentials(credential_ids):
    credentials = []
    with stats.timer('service_batch_get_credentials'):
        for cred in Credential.batch_get(credential_ids):
            data_key = keymanager.decrypt_key(
                cred.data_key, encryption_context={'id': cred.id})
            cipher_version = cred.cipher_version
            cipher = CipherManager(data_key, cipher_version)
            _credential_pairs = cipher.decrypt(cred.credential_pairs)
            _credential_pairs = json.loads(_credential_pairs)
            credentials.append({
                'id': cred.id,
                'name': cred.name,
                'enabled': cred.enabled,
                'revision': cred.revision,
                'credential_pairs': _credential_pairs
            })
    return credentials
Esempio n. 3
0
def _get_credentials(credential_ids):
    credentials = []
    with stats.timer('service_batch_get_credentials'):
        for cred in Credential.batch_get(credential_ids):
            data_key = keymanager.decrypt_key(
                cred.data_key,
                encryption_context={'id': cred.id}
            )
            cipher_version = cred.cipher_version
            cipher = CipherManager(data_key, cipher_version)
            _credential_pairs = cipher.decrypt(cred.credential_pairs)
            _credential_pairs = json.loads(_credential_pairs)
            credentials.append({
                'id': cred.id,
                'name': cred.name,
                'enabled': cred.enabled,
                'revision': cred.revision,
                'credential_pairs': _credential_pairs
            })
    return credentials
Esempio n. 4
0
def decrypt_token(token, _from):
    '''
    Decrypt a token.
    '''
    try:
        token_key = '{0}{1}'.format(
            hashlib.sha256(token).hexdigest(),
            _from
        )
    except Exception:
        raise TokenDecryptionError('Authentication error.')
    if token_key not in TOKENS:
        try:
            token = base64.b64decode(token)
            with stats.timer('kms_decrypt_token'):
                data = kms.decrypt(
                    CiphertextBlob=token,
                    EncryptionContext={
                        # This key is sent to us.
                        'to': app.config['AUTH_CONTEXT'],
                        # From a service.
                        'from': _from
                    }
                )
            # Decrypt doesn't take KeyId as an argument. We need to verify the
            # correct key was used to do the decryption.
            # Annoyingly, the KeyId from the data is actually an arn.
            key_arn = data['KeyId']
            if key_arn != get_key_arn(app.config['AUTH_KEY']):
                raise TokenDecryptionError('Authentication error.')
            plaintext = data['Plaintext']
            payload = json.loads(plaintext)
        # We don't care what exception is thrown. For paranoia's sake, fail
        # here.
        except Exception:
            log.exception('Failed to validate token.')
            raise TokenDecryptionError('Authentication error.')
    else:
        payload = TOKENS[token_key]
    time_format = "%Y%m%dT%H%M%SZ"
    now = datetime.datetime.utcnow()
    try:
        not_before = datetime.datetime.strptime(
            payload['not_before'],
            time_format
        )
        not_after = datetime.datetime.strptime(
            payload['not_after'],
            time_format
        )
    except Exception:
        log.exception(
            'Failed to get not_before and not_after from token payload.'
        )
        raise TokenDecryptionError('Authentication error.')
    delta = (not_after - not_before).seconds / 60
    if delta > app.config['AUTH_TOKEN_MAX_LIFETIME']:
        log.warning('Token used which exceeds max token lifetime.')
        raise TokenDecryptionError('Authentication error.')
    if not (now >= not_before) and (now <= not_after):
        log.warning('Expired token used.')
        raise TokenDecryptionError('Authentication error.')
    TOKENS[token_key] = payload
    return payload
Esempio n. 5
0
    def decorated(*args, **kwargs):
        if not app.config.get('USE_AUTH'):
            return f(*args, **kwargs)

        auth = request.authorization
        headers = request.headers
        using_basic_kms_auth = (auth and auth.get('username')
                                and auth.get('password') != '')
        using_kms_auth = ('X-Auth-Token' in headers
                          and 'X-Auth-From' in headers)

        # User suppplied basic auth info
        if using_basic_kms_auth or using_kms_auth:
            if using_basic_kms_auth:
                _from = auth['username']
                token = auth['password']
            else:
                _from = headers['X-Auth-From']
                token = headers['X-Auth-Token']
            try:
                with stats.timer('decrypt_token'):
                    payload = keymanager.decrypt_token(token, _from)
                log.debug('Auth request had the following payload:'
                          ' {0}'.format(payload))
                role = 'service'
                msg = 'Authenticated {0} with role {1} via kms auth'
                msg = msg.format(_from, role)
                log.debug(msg)
                if role_has_privilege(role, f.func_name):
                    g.auth_role = role
                    g.username = _from
                    return f(*args, **kwargs)
                else:
                    msg = '{0} is not authorized to access {1}.'
                    msg = msg.format(_from, f.func_name)
                    log.warning(msg)
                    return abort(403)
            except keymanager.TokenDecryptionError:
                msg = 'Access denied for {0}. Authentication Failed.'
                msg = msg.format(_from)
                log.warning(msg)
                return abort(403)
        # If not using kms auth, require google auth.
        else:
            role = 'user'
            if not role_has_privilege(role, f.func_name):
                return abort(403)
            if 'email' in session.get('google_oauth2', []):
                if (app.config['USERS_FILE']
                        and get_logged_in_user_email() not in users):
                    msg = 'User not authorized: {0}'
                    log.warning(msg.format(get_logged_in_user_email()))
                    return abort(403)
                else:
                    g.auth_role = role
                    return f(*args, **kwargs)
            response = make_response()
            if request.is_secure:
                secure_cookie = True
            else:
                secure_cookie = False
            result = _authomatic.login(
                WerkzeugAdapter(request, response),
                'google',
                session=session,
                session_saver=lambda: app.save_session(session, response),
                secure_cookie=secure_cookie)
            if result:
                if result.error:
                    msg = 'Google auth failed with error: {0}'
                    log.error(msg.format(result.error.message))
                    return abort(403)
                if result.user:
                    result.user.update()
                    user = result.user
                    email_suffix = app.config['GOOGLE_AUTH_EMAIL_SUFFIX']
                    if email_suffix and not user.email.endswith(email_suffix):
                        return abort(403)
                    session['google_oauth2'] = {}
                    session['google_oauth2']['email'] = user.email
                    session['google_oauth2']['first_name'] = user.first_name
                    session['google_oauth2']['last_name'] = user.last_name
                    g.auth_role = role
                    # TODO: find a way to save the angular args
                    # authomatic adds url params google auth has stripped the
                    # angular args anyway, so let's just redirect back to the
                    # index.
                    return redirect(url_for('index'))
            return response
        return abort(403)
Esempio n. 6
0
    def decorated(*args, **kwargs):
        if not app.config.get('USE_AUTH'):
            return f(*args, **kwargs)

        auth = request.authorization
        headers = request.headers
        using_basic_kms_auth = (
            auth and
            auth.get('username') and
            auth.get('password') != ''
        )
        using_kms_auth = (
            'X-Auth-Token' in headers and
            'X-Auth-From' in headers
        )

        # User suppplied basic auth info
        if using_basic_kms_auth or using_kms_auth:
            if using_basic_kms_auth:
                _from = auth['username']
                token = auth['password']
            else:
                _from = headers['X-Auth-From']
                token = headers['X-Auth-Token']
            try:
                with stats.timer('decrypt_token'):
                    payload = keymanager.decrypt_token(
                        token,
                        _from
                    )
                logging.debug('Auth request had the following payload:'
                              ' {0}'.format(payload))
                role = 'service'
                msg = 'Authenticated {0} with role {1} via kms auth'
                msg = msg.format(_from, role)
                logging.debug(msg)
                if role_has_privilege(role, f.func_name):
                    g.auth_role = role
                    g.username = _from
                    return f(*args, **kwargs)
                else:
                    msg = '{0} is not authorized to access {1}.'
                    msg = msg.format(_from, f.func_name)
                    logging.warning(msg)
                    return abort(403)
            except keymanager.TokenDecryptionError:
                msg = 'Access denied for {0}. Authentication Failed.'
                msg = msg.format(_from)
                logging.warning(msg)
                return abort(403)
        # If not using kms auth, require google auth.
        else:
            role = 'user'
            if not role_has_privilege(role, f.func_name):
                return abort(403)
            if 'email' in session.get('google_oauth2', []):
                if (app.config['USERS_FILE'] and
                        get_logged_in_user_email() not in users):
                    msg = 'User not authorized: {0}'
                    logging.warning(msg.format(get_logged_in_user_email()))
                    return abort(403)
                else:
                    g.auth_role = role
                    return f(*args, **kwargs)
            response = make_response()
            if request.is_secure:
                secure_cookie = True
            else:
                secure_cookie = False
            result = _authomatic.login(
                WerkzeugAdapter(request, response),
                'google',
                session=session,
                session_saver=lambda: app.save_session(session, response),
                secure_cookie=secure_cookie
            )
            if result:
                if result.error:
                    msg = 'Google auth failed with error: {0}'
                    logging.error(msg.format(result.error.message))
                    return abort(403)
                if result.user:
                    result.user.update()
                    user = result.user
                    email_suffix = app.config['GOOGLE_AUTH_EMAIL_SUFFIX']
                    if email_suffix and not user.email.endswith(email_suffix):
                        return abort(403)
                    session['google_oauth2'] = {}
                    session['google_oauth2']['email'] = user.email
                    session['google_oauth2']['first_name'] = user.first_name
                    session['google_oauth2']['last_name'] = user.last_name
                    g.auth_role = role
                    # TODO: find a way to save the angular args
                    # authomatic adds url params google auth has stripped the
                    # angular args anyway, so let's just redirect back to the
                    # index.
                    return redirect(url_for('index'))
            return response
        return abort(403)
Esempio n. 7
0
    def decorated(*args, **kwargs):
        if not app.config.get("USE_AUTH"):
            return f(*args, **kwargs)

        auth = request.authorization
        headers = request.headers
        using_basic_kms_auth = auth and auth.get("username") and auth.get("password") != ""
        using_kms_auth = "X-Auth-Token" in headers and "X-Auth-From" in headers

        # User suppplied basic auth info
        if using_basic_kms_auth or using_kms_auth:
            if using_basic_kms_auth:
                _from = auth["username"]
                token = auth["password"]
            else:
                _from = headers["X-Auth-From"]
                token = headers["X-Auth-Token"]
            try:
                with stats.timer("decrypt_token"):
                    payload = keymanager.decrypt_token(token, _from)
                log.debug("Auth request had the following payload:" " {0}".format(payload))
                role = "service"
                msg = "Authenticated {0} with role {1} via kms auth"
                msg = msg.format(_from, role)
                log.debug(msg)
                if role_has_privilege(role, f.func_name):
                    g.auth_role = role
                    g.username = _from
                    return f(*args, **kwargs)
                else:
                    msg = "{0} is not authorized to access {1}."
                    msg = msg.format(_from, f.func_name)
                    log.warning(msg)
                    return abort(403)
            except keymanager.TokenDecryptionError:
                msg = "Access denied for {0}. Authentication Failed."
                msg = msg.format(_from)
                log.warning(msg)
                return abort(403)
        # If not using kms auth, require google auth.
        else:
            role = "user"
            if not role_has_privilege(role, f.func_name):
                return abort(403)
            if "email" in session.get("google_oauth2", []):
                if app.config["USERS_FILE"] and get_logged_in_user_email() not in users:
                    msg = "User not authorized: {0}"
                    log.warning(msg.format(get_logged_in_user_email()))
                    return abort(403)
                else:
                    g.auth_role = role
                    return f(*args, **kwargs)
            response = make_response()
            if request.is_secure:
                secure_cookie = True
            else:
                secure_cookie = False
            result = _authomatic.login(
                WerkzeugAdapter(request, response),
                "google",
                session=session,
                session_saver=lambda: app.save_session(session, response),
                secure_cookie=secure_cookie,
            )
            if result:
                if result.error:
                    msg = "Google auth failed with error: {0}"
                    log.error(msg.format(result.error.message))
                    return abort(403)
                if result.user:
                    result.user.update()
                    user = result.user
                    email_suffix = app.config["GOOGLE_AUTH_EMAIL_SUFFIX"]
                    if email_suffix and not user.email.endswith(email_suffix):
                        return abort(403)
                    session["google_oauth2"] = {}
                    session["google_oauth2"]["email"] = user.email
                    session["google_oauth2"]["first_name"] = user.first_name
                    session["google_oauth2"]["last_name"] = user.last_name
                    g.auth_role = role
                    # TODO: find a way to save the angular args
                    # authomatic adds url params google auth has stripped the
                    # angular args anyway, so let's just redirect back to the
                    # index.
                    return redirect(url_for("index"))
            return response
        return abort(403)