Ejemplo n.º 1
0
def authenticate(user=None, password=None):
    def _format_key(key):
        try:
            if isinstance(key, list):
                kk = key
            else:
                kk = key.split(',')
            if len(kk) == 1:
                return kk[0]
            else:
                return apikey.create_combined_key(kk)
        except Exception as e:
            logging.error(e)
            raise

    if user is None or password is None:
        raise AccessDenied('No login/password provided')
    dbconn = userdb()
    try:
        r = dbconn.execute(sql('select k from users where u = :u and p = :p'),
                           u=user,
                           p=crypt_password(password)).fetchone()
    except:
        eva.core.report_userdb_error()
    if r:
        return _format_key(r.k), None
    else:
        k = msad_authenticate(user, password)
        if k is None:
            raise AccessDenied('Authentication failure')
        else:
            logging.debug(
                f'user {user} authenticated via active directory, key id: {k}')
            return _format_key(k), 'msad'
Ejemplo n.º 2
0
def create_user(user=None, password=None, key=None):
    if user is None or password is None or key is None:
        return False
    kk = key if isinstance(key, list) else key.split(',')
    for k in kk:
        if k not in apikey.keys_by_id:
            raise ResourceNotFound(f'API key {k}')
    try:
        dbconn = userdb()
        row = dbconn.execute(sql('select k from users where u = :u'),
                             u=user).fetchone()
    except:
        eva.core.report_userdb_error()
    if row:
        raise ResourceAlreadyExists
    try:
        dbconn.execute(sql('insert into users(u, p, k) values (:u, :p, :k)'),
                       u=user,
                       p=crypt_password(password),
                       k=','.join(kk))
        logging.info('User {} created, key: {}'.format(user, ','.join(kk)))
    except:
        eva.core.report_userdb_error()
        return None
    run_hook('create', user, password)
    return {'user': user, 'key_id': key}
Ejemplo n.º 3
0
def api_log_insert(call_id,
                   gw=None,
                   ip=None,
                   auth=None,
                   u=None,
                   utp=None,
                   ki=None,
                   func=None,
                   params=None):
    dbconn = userdb()
    dbt = dbconn.begin()
    try:
        dbconn.execute(sql(
            'insert into api_log(id, t, gw, ip, auth, u, utp, ki, func, params)'
            ' values (:i, :t, :gw, :ip, :auth, :u, :utp, :ki, :func, :params)'
        ),
                       i=call_id,
                       t=time.time(),
                       gw=gw,
                       ip=ip,
                       auth=auth,
                       u=u,
                       utp=utp,
                       ki=ki,
                       func=func,
                       params=rapidjson.dumps(params)[:512])
        dbt.commit()
    except:
        dbt.rollback()
        logging.error('Unable to insert API call info into DB')
        eva.core.log_traceback()
Ejemplo n.º 4
0
def init():
    dbconn = userdb()
    meta = sa.MetaData()
    t_users = sa.Table('users', meta,
                       sa.Column('u', sa.String(64), primary_key=True),
                       sa.Column('p', sa.String(64)),
                       sa.Column('k', sa.String(2048)))
    t_api_log = sa.Table('api_log', meta,
                         sa.Column('id', sa.String(36), primary_key=True),
                         sa.Column('t', sa.Numeric(20, 8), nullable=False),
                         sa.Column('tf', sa.Numeric(20, 8)),
                         sa.Column('gw', sa.String(128)),
                         sa.Column('ip', sa.String(45)),
                         sa.Column('auth', sa.String(128)),
                         sa.Column('u', sa.String(128)),
                         sa.Column('utp', sa.String(32)),
                         sa.Column('ki', sa.String(2048)),
                         sa.Column('func', sa.String(128)),
                         sa.Column('params', sa.String(512)),
                         sa.Column('status', sa.String(32)))
    try:
        meta.create_all(dbconn)
    except:
        eva.core.log_traceback()
        logging.critical('unable to create users table in db')
    try:
        dbconn.close()
    except:
        pass
Ejemplo n.º 5
0
def load_keys_from_db():
    _keys = {}
    _keys_by_id = {}
    dbconn = userdb()
    meta = sa.MetaData()
    t_apikeys = sa.Table('apikeys', meta,
                         sa.Column('k_id', sa.String(64), primary_key=True),
                         sa.Column('k', sa.String(64)),
                         sa.Column('m', sa.Integer),
                         sa.Column('s', sa.Integer),
                         sa.Column('i', sa.String(1024)),
                         sa.Column('g', sa.String(1024)),
                         sa.Column('i_ro', sa.String(1024)),
                         sa.Column('g_ro', sa.String(1024)),
                         sa.Column('a', sa.String(256)),
                         sa.Column('hal', sa.String(1024)),
                         sa.Column('has', sa.String(1024)),
                         sa.Column('pvt', sa.String(1024)),
                         sa.Column('rpvt', sa.String(1024)))
    try:
        meta.create_all(dbconn)
    except:
        logging.critical('unable to create apikeys table in db')
        return _keys, _keys_by_id
    try:
        result = dbconn.execute(sql('select * from apikeys'))
        while True:
            r = result.fetchone()
            if not r: break
            key = APIKey(r.k, r.k_id)
            key.sysfunc = True if val_to_boolean(r.s) else False
            for i, v in {
                    'item_ids': 'i',
                    'groups': 'g',
                    'item_ids_ro': 'i_ro',
                    'groups_ro': 'g_ro',
                    'allow': 'a',
                    'pvt_files': 'pvt',
                    'rpvt_uris': 'rpvt'
            }.items():
                setattr(
                    key, i,
                    list(filter(None, [j.strip() for j in r[v].split(',')])))
            _hosts_allow = list(
                filter(None, [j.strip() for j in r.hal.split(',')]))
            key.hosts_allow = [IPNetwork(h) for h in _hosts_allow]
            _hosts_assign = list(
                filter(None, [x.strip() for x in r.has.split(',')]))
            key.hosts_assign = \
                    [ IPNetwork(h) for h in _hosts_assign ]
            key.dynamic = True
            key.in_db = True
            _keys[key.key] = key
            _keys_by_id[key.key_id] = key
    except:
        eva.core.report_userdb_error(raise_exeption=False)
    return _keys, _keys_by_id
Ejemplo n.º 6
0
 def save(self):
     if not self.dynamic:
         return False
     data = self.serialize()
     for d in [
             'items', 'groups', 'items_ro', 'groups_ro', 'allow',
             'hosts_allow', 'hosts_assign', 'pvt', 'rpvt'
     ]:
         data[d] = ','.join(data[d])
     dbconn = userdb()
     try:
         if not self.in_db:
             # if save on exit is set, deleted key with the same name could
             # still be present in the database
             dbconn.execute(sql('delete from apikeys where k_id=:k_id'),
                            k_id=data['id'])
             dbconn.execute(
                 sql('insert into apikeys(k_id, k, m, s, i,' +
                     ' g, i_ro, g_ro, a,hal, has, pvt, rpvt) values ' +
                     '(:k_id, :k, :m, :s, :i, :g, :i_ro, :g_ro, :a, ' +
                     ':hal, :has, :pvt, :rpvt)'),
                 k_id=data['id'],
                 k=data['key'],
                 m=1 if data['master'] else 0,
                 s=1 if data['sysfunc'] else 0,
                 i=data['items'],
                 g=data['groups'],
                 i_ro=data['items_ro'],
                 g_ro=data['groups_ro'],
                 a=data['allow'],
                 hal=data['hosts_allow'],
                 has=data['hosts_assign'],
                 pvt=data['pvt'],
                 rpvt=data['rpvt'])
         else:
             dbconn.execute(
                 sql('update apikeys set k=:k, s=:s, i=:i, g=:g, ' +
                     'i_ro=:i_ro, g_ro=:g_ro, a=:a, ' +
                     'hal=:hal, has=:has, pvt=:pvt, rpvt=:rpvt where ' +
                     'k_id=:k_id'),
                 k=self.key,
                 s=1 if data['sysfunc'] else 0,
                 i=data['items'],
                 g=data['groups'],
                 i_ro=data['items_ro'],
                 g_ro=data['groups_ro'],
                 a=data['allow'],
                 hal=data['hosts_allow'],
                 has=data['hosts_assign'],
                 pvt=data['pvt'],
                 rpvt=data['rpvt'],
                 k_id=data['id'])
     except:
         eva.core.report_userdb_error()
     self.in_db = True
     return True
Ejemplo n.º 7
0
def msad_get_cached_credentials(username, password):
    if _d.msad_cache_time <= 0:
        return
    logging.debug(f'getting cached credentials for {username}')
    r = userdb().execute(
        sql('select cn from msad_cache where u=:u and p=:p and t>=:t'),
        u=username,
        p=crypt_password(password),
        t=time.time() - _d.msad_cache_time).fetchone()
    return r.cn if r else None
Ejemplo n.º 8
0
def msad_cache_cleaner(**kwargs):
    logging.debug('cleaning MSAD cache')
    dbconn = userdb()
    dbt = dbconn.begin()
    try:
        dbconn.execute(sql('delete from msad_cache where t < :t'),
                       t=time.time() - _d.msad_cache_time)
        dbt.commit()
    except:
        dbt.rollback()
        raise
Ejemplo n.º 9
0
def get_user(user=None):
    if not user: return None
    try:
        dbconn = userdb()
        result = []
        row = dbconn.execute(sql('select u, k from users where u=:u'),
                             u=user).fetchone()
    except:
        eva.core.report_userdb_error()
    if not row: raise ResourceNotFound
    return {'user': row.u, 'key_id': row.k}
Ejemplo n.º 10
0
def save():
    for i, k in keys_by_id.copy().items():
        if k.config_changed and not k.save():
            return False
    dbconn = userdb()
    try:
        for k in keys_to_delete:
            dbconn.execute(sql('delete from apikeys where k_id=:k_id'), k_id=k)
        return True
    except:
        eva.core.report_db_error(raise_exeption=False)
Ejemplo n.º 11
0
def init():
    dbconn = userdb()
    meta = sa.MetaData()
    t_users = sa.Table('users', meta,
                       sa.Column('u', sa.String(64), primary_key=True),
                       sa.Column('p', sa.String(64)),
                       sa.Column('k', sa.String(64)))
    try:
        meta.create_all(dbconn)
    except:
        eva.core.log_traceback()
        logging.critical('unable to create apikeys table in db')
Ejemplo n.º 12
0
def authenticate(user=None, password=None):
    if user is None or password is None:
        raise AccessDenied('No login/password provided')
    dbconn = userdb()
    try:
        r = dbconn.execute(sql('select k from users where u = :u and p = :p'),
                           u=user,
                           p=crypt_password(password)).fetchone()
    except:
        eva.core.report_userdb_error()
    if not r:
        raise AccessDenied('Authentication failure')
    return r.k
Ejemplo n.º 13
0
def set_user_key(user=None, key=None):
    if user is None or key is None or key not in apikey.keys_by_id:
        return None
    try:
        dbconn = userdb()
        if dbconn.execute(sql('update users set k = :k where u = :u'),
                          k=key,
                          u=user).rowcount:
            logging.info('user {} key {} is set'.format(user, key))
            return True
    except:
        eva.core.report_userdb_error()
    raise ResourceNotFound
Ejemplo n.º 14
0
def api_log_set_status(call_id, status=None):
    dbconn = userdb()
    dbt = dbconn.begin()
    try:
        dbconn.execute(
            sql('update api_log set tf=:tf, status=:status where id=:i'),
            i=call_id,
            tf=time.time(),
            status=status)
        dbt.commit()
    except:
        dbt.rollback()
        logging.error('Unable to update API call info in DB')
        eva.core.log_traceback()
Ejemplo n.º 15
0
def list_users():
    try:
        dbconn = userdb()
        result = []
        r = dbconn.execute(sql('select u, k from users order by u'))
        while 1:
            row = r.fetchone()
            if not row: break
            u = {}
            u['user'] = row.u
            u['key_id'] = row.k
            result.append(u)
        return sorted(result, key=lambda k: k['user'])
    except:
        eva.core.report_userdb_error()
Ejemplo n.º 16
0
def api_log_cleaner(**kwargs):
    logging.debug('cleaning API log')
    dbconn = userdb()
    dbt = dbconn.begin()
    try:
        dbconn.execute(sql('delete from api_log where t < :t'),
                       t=time.time() - eva.core.config.keep_api_log)
        dbt.commit()
    except:
        dbt.rollback()
        raise
    try:
        dbconn.close()
    except:
        pass
Ejemplo n.º 17
0
def destroy_user(user=None):
    if user is None:
        raise FunctionFailed
    try:
        dbconn = userdb()
        if dbconn.execute(sql('delete from users where u = :u'),
                          u=user).rowcount:
            logging.info('User {} deleted'.format(user))
        else:
            raise ResourceNotFound
    except ResourceNotFound:
        raise
    except:
        eva.core.report_userdb_error()
        return False
    run_hook('destroy', user)
    return True
Ejemplo n.º 18
0
def delete_api_key(key_id):
    if key_id is None or key_id not in keys_by_id:
        raise ResourceNotFound
    if keys_by_id[key_id].master or not keys_by_id[key_id].dynamic:
        raise FunctionFailed('Master and static keys can not be deleted')
    del keys[keys_by_id[key_id].key]
    del keys_by_id[key_id]
    if eva.core.config.db_update == 1:
        dbconn = userdb()
        try:
            dbconn.execute(sql('delete from apikeys where k_id=:key_id'),
                           key_id=key_id)
        except:
            eva.core.report_userdb_error()
    else:
        keys_to_delete.add(key_id)
    return True
Ejemplo n.º 19
0
def set_user_key(user=None, key=None):
    if user is None or key is None:
        return None
    kk = key if isinstance(key, list) else key.split(',')
    for k in kk:
        if k not in apikey.keys_by_id:
            raise ResourceNotFound(f'API key {k}')
    try:
        dbconn = userdb()
        if dbconn.execute(sql('update users set k = :k where u = :u'),
                          k=','.join(kk),
                          u=user).rowcount:
            logging.info('user {} key {} is set'.format(user, ','.join(kk)))
            return True
    except:
        eva.core.report_userdb_error()
    raise ResourceNotFound
Ejemplo n.º 20
0
def set_user_password(user=None, password=None):
    if user is None or password is None:
        return None
    try:
        dbconn = userdb()
        if dbconn.execute(sql('update users set p = :p where u = :u'),
                          p=crypt_password(password),
                          u=user).rowcount:
            logging.info('user {} new password is set'.format(user))
        else:
            raise ResourceNotFound
    except ResourceNotFound:
        raise
    except:
        eva.core.report_userdb_error()
        return False
    run_hook('set_password', user, password)
    return True
Ejemplo n.º 21
0
def api_log_update(call_id, **kwargs):
    # unsafe, make sure kwargs keys are not coming from outside
    cond = ''
    qkw = {'i': call_id}
    for k, v in kwargs.items():
        if cond:
            cond += ','
        cond += f'{k}=:{k}'
        qkw[k] = v
    if cond:
        dbconn = userdb()
        dbt = dbconn.begin()
        try:
            dbconn.execute(sql(f'update api_log set {cond} where id=:i'),
                           **qkw)
            dbt.commit()
        except:
            dbt.rollback()
            logging.error('Unable to update API call info in DB')
            eva.core.log_traceback()
Ejemplo n.º 22
0
def msad_init(host,
              domain,
              ca=None,
              key_prefix=None,
              ou=None,
              cache_time=86400,
              cache_first=False):
    try:
        from easyad import EasyAD
    except:
        logging.error('unable to import easyad module')
        return
    dbconn = userdb()
    meta = sa.MetaData()
    t_users = sa.Table(
        'msad_cache',
        meta,
        sa.Column('u', sa.String(64), primary_key=True),
        sa.Column('p', sa.String(64)),
        sa.Column('cn', sa.String(2048)),
        sa.Column('t', sa.Numeric(20, 8)),
    )
    try:
        meta.create_all(dbconn)
    except:
        eva.core.log_traceback()
        logging.critical('unable to create msad_cache table in db')
    _d.msad_host = dict_from_str(host) if '=' in host else host
    _d.msad_default_domain = domain
    _d.msad_ca = ca
    _d.msad_key_prefix = key_prefix if key_prefix else ''
    _d.msad_cache_time = cache_time
    _d.msad_cache_first = cache_first
    if ou is not None:
        _d.msad_ou = ou
    try:
        dbconn.close()
    except:
        pass
Ejemplo n.º 23
0
def delete_api_key(key_id):
    with key_lock:
        if key_id is None or key_id not in keys_by_id:
            raise ResourceNotFound
        if keys_by_id[key_id].master or not keys_by_id[key_id].dynamic:
            raise FunctionFailed('Master and static keys can not be deleted')
        del keys[keys_by_id[key_id].key]
        del keys_by_id[key_id]
        if eva.core.config.auto_save:
            dbconn = userdb()
            try:
                dbconn.execute(sql('delete from apikeys where k_id=:key_id'),
                               key_id=key_id)
            except:
                eva.core.report_userdb_error()
        else:
            keys_to_delete.add(key_id)
        for k, v in combined_keys_cache.items():
            ckey = keys_by_id[v]
            if key_id in ckey.combined_from:
                ckey.need_recombine = True
        return True
Ejemplo n.º 24
0
def msad_cache_credentials(username, password, cn):
    if _d.msad_cache_time <= 0:
        return
    dbconn = userdb()
    dbt = dbconn.begin()
    params = {
        'u': username,
        'p': crypt_password(password),
        'cn': cn,
        't': time.time()
    }
    try:
        if dbconn.execute(
                sql('update msad_cache set p=:p, cn=:cn, t=:t where u=:u'), **
                params).rowcount < 1:
            dbconn.execute(
                sql('insert into msad_cache(u, p, cn, t) '
                    'values (:u, :p, :cn, :t)'), **params)
        dbt.commit()
        logging.debug(f'MSAD credentials for {username} cached')
    except:
        dbt.rollback()
        raise
Ejemplo n.º 25
0
def api_log_get(t_start=None,
                t_end=None,
                limit=None,
                time_format=None,
                f=None):
    t_start = fmt_time(t_start)
    t_end = fmt_time(t_end)
    qkw = {}
    if t_start or t_end:
        cond = 'where ('
        if t_start is not None:
            try:
                t_start = float(t_start)
            except:
                try:
                    t_start = dateutil.parser.parse(t_start).timestamp()
                except:
                    raise ValueError('start time format is uknown')
            cond += 't >= :t_start'
            qkw['t_start'] = t_start
        if t_end is not None:
            try:
                t_end = float(t_end)
            except:
                try:
                    t_end = dateutil.parser.parse(t_end).timestamp()
                except:
                    raise ValueError('end time format is uknown')
            if t_start is not None:
                cond += ' and '
            cond += 't <= :t_end'
            qkw['t_end'] = t_end
        cond += ')'
    else:
        cond = ''
    if f:
        # make sure some empty fields are null
        for z in ('u', 'utp', 'status'):
            if z in f and f[z] == '':
                f[z] = None
    if 'params' in f:
        condp = 'params like :params'
        qkw['params'] = f'%{f["params"]}%'
        del f['params']
    else:
        condp = None
    try:
        cond, qkw = format_sql_condition(f,
                                         qkw,
                                         fields=('gw', 'ip', 'auth', 'u',
                                                 'utp', 'ki', 'func',
                                                 'status'),
                                         cond=cond)
    except ValueError as e:
        raise ValueError(f'Invalid filter: {e}')
    if condp:
        if cond:
            cond += ' and '
        else:
            cond = 'where '
        cond += condp
    if limit is None:
        cond += ' order by t asc'
    else:
        cond += f' order by t desc limit {limit}'
    result = [
        dict(r) for r in userdb().execute(
            sql('select id, t, tf, gw, ip, auth, u, utp, ki,'
                f' func, params, status from api_log {cond}'), **
            qkw).fetchall()
    ]
    if limit is not None:
        result = sorted(result, key=lambda k: k['t'])
    if time_format == 'iso':
        import pytz
        tz = pytz.timezone(time.tzname[0])
        for r in result:
            r['t'] = datetime.fromtimestamp(r['t'], tz).isoformat()
            r['tf'] = datetime.fromtimestamp(r['tf'], tz).isoformat()
    return result