Ejemplo n.º 1
0
    def process_request(self, req, resp):
        # http basic auth
        if self.config['server'].get('enable_basic_auth'):
            hdr_auth = req.get_header('AUTHORIZATION')
            if not hdr_auth:
                raise falcon.HTTPUnauthorized('Access denied',
                                              'No auth header', [])

            auth = re.sub('^Basic ', '', hdr_auth)
            usr, pwd = decodestring(auth).split(':')
            if not equals(self.basic_auth.get(usr, ''), pwd):
                logger.warning('basic auth failure: %s', usr)
                raise falcon.HTTPUnauthorized('Access denied',
                                              'Basic auth failure', [])

        segments = req.path.strip('/').split('/')
        if segments[0] == 'api':
            if len(segments) >= 3:
                # twilio validation
                if segments[2] == 'twilio':
                    sig = req.get_header('X_TWILIO_SIGNATURE')
                    if sig is None:
                        logger.warning("no twilio signature found!")
                        raise falcon.HTTPUnauthorized('Access denied',
                                                      'No Twilio signature',
                                                      [])
                    uri = [
                        req.protocol, '://',
                        req.get_header('HOST'),
                        self.config['server'].get('lb_routing_path',
                                                  ''), req.path
                    ]
                    if req.query_string:
                        uri.append('?')
                        uri.append(req.query_string)
                    post_body = req.context['body']
                    expected_sigs = [
                        compute_signature(t, ''.join(uri), post_body)
                        for t in self.twilio_auth_token
                    ]
                    if sig not in expected_sigs:
                        logger.warning(
                            'twilio validation failure: %s not in possible sigs: %s',
                            sig, expected_sigs)
                        raise falcon.HTTPUnauthorized('Access denied',
                                                      'Twilio auth failure',
                                                      [])
                    return
                elif segments[2] == 'gmail' or segments[
                        2] == 'gmail-oneclick' or segments[2] == 'slack':
                    return
        elif len(segments) == 1:
            if segments[0] == 'health' or segments[0] == 'healthcheck':
                return
            elif segments[0] == self.config['gmail'].get('verification_code'):
                return

        raise falcon.HTTPUnauthorized('Access denied', 'Authentication failed',
                                      [])
Ejemplo n.º 2
0
    def process_request(self, req, resp):
        if self.debug:
            return
        # CORS Pre-flight
        if req.method == 'OPTIONS':
            resp.status = falcon.HTTP_204
            return
        # http basic auth
        if self.config['server'].get('enable_basic_auth'):
            hdr_auth = req.get_header('AUTHORIZATION')
            if not hdr_auth:
                raise falcon.HTTPUnauthorized('Access denied',
                                              'No auth header', [])

            auth = re.sub('^Basic ', '', hdr_auth)
            usr, pwd = decodestring(auth).split(':')
            if not equals(self.basic_auth.get(usr, ''), pwd):
                logger.warning('basic auth failure: %s', usr)
                raise falcon.HTTPUnauthorized('Access denied',
                                              'Basic auth failure', [])

        segments = req.path.strip('/').split('/')
        if segments[0] == 'api':
            if len(segments) >= 3:
                # twilio validation
                if segments[2] == 'twilio':
                    sig = req.get_header('X_TWILIO_SIGNATURE')
                    if sig is None:
                        logger.warning("no twilio signature found!")
                        raise falcon.HTTPUnauthorized('Access denied',
                                                      'No Twilio signature',
                                                      [])
                    uri = [
                        req.protocol, '://',
                        req.get_header('HOST'),
                        self.config['server'].get('lb_routing_path',
                                                  ''), req.path
                    ]
                    if req.query_string:
                        uri.append('?')
                        uri.append(req.query_string)
                    post_body = req.context['body']
                    expected_sigs = [
                        compute_signature(t, ''.join(uri), post_body)
                        for t in self.twilio_auth_token
                    ]
                    sig = sig.encode('utf8')
                    if sig not in expected_sigs:
                        logger.warning(
                            'twilio validation failure: %s not in possible sigs: %s',
                            sig, expected_sigs)
                        raise falcon.HTTPUnauthorized('Access denied',
                                                      'Twilio auth failure',
                                                      [])
                    return
                elif self.mobile and (segments[2] == 'mobile'
                                      or segments[2] == 'oncall'):
                    # Only allow refresh tokens for /refresh, only access for all else
                    table = 'refresh_token' if segments[
                        3] == 'refresh' else 'access_token'
                    key_query = '''SELECT `key`, `target`.`name`
                                   FROM `%s` JOIN `target` ON `user_id` = `target`.`id`
                                   WHERE `%s`.`id` = %%s
                                   AND `expiration` > %%s''' % (table, table)
                    method = req.method
                    auth = req.get_header('Authorization', required=True)

                    items = urllib2.parse_http_list(auth)
                    parts = urllib2.parse_keqv_list(items)

                    if 'signature' not in parts or 'keyId' not in parts or 'timestamp' not in parts:
                        raise falcon.HTTPUnauthorized(
                            'Authentication failure: invalid header')

                    try:
                        window = int(parts['timestamp'])
                        time_diff = abs(time.time() - window)
                    except ValueError:
                        raise falcon.HTTPUnauthorized(
                            'Authentication failure: invalid header')
                    client_digest = parts['signature']
                    key_id = parts['keyId']
                    body = req.context['body'].decode('utf8')
                    path = req.env['PATH_INFO']
                    qs = req.env['QUERY_STRING']
                    if qs:
                        path = path + '?' + qs
                    text = '%s %s %s %s' % (window, method, path, body)
                    text = text.encode('utf8')

                    conn = db.connect()
                    cursor = conn.cursor()
                    cursor.execute(key_query, (key_id, time.time()))
                    row = cursor.fetchone()
                    conn.close()
                    # make sure that there exists a row for the corresponding username
                    if row is None:
                        raise falcon.HTTPUnauthorized(
                            'Authentication failure: server')
                    key = self.fernet.decrypt(str(row[0]).encode('utf8'))
                    key = key
                    req.context['user'] = row[1]

                    HMAC = hmac.new(key, text, hashlib.sha512)
                    digest = urlsafe_b64encode(HMAC.digest())

                    if hmac.compare_digest(
                            client_digest.encode('utf8'),
                            digest) and time_diff < self.time_window:
                        return
                    else:
                        raise falcon.HTTPUnauthorized(
                            'Authentication failure: server')
                elif segments[2] == 'gmail' or segments[
                        2] == 'gmail-oneclick' or segments[
                            2] == 'slack' or segments[2] == 'ical':
                    return
        elif len(segments) == 1:
            if segments[0] == 'health' or segments[0] == 'healthcheck':
                return
            elif segments[0] == self.config.get('gmail',
                                                {}).get('verification_code'):
                return

        elif segments[0] == 'saml':
            return
        raise falcon.HTTPUnauthorized('Access denied', 'Authentication failed',
                                      [])