Example #1
0
def sso_request_get():
    state = utils.rand_str(64)
    secret = utils.rand_str(64)
    callback = flask.request.url_root + 'sso/callback'

    if not settings.local.sub_active:
        return flask.abort(405)

    resp = utils.request.post(AUTH_SERVER + '/request/google',
        json_data={
            'license': settings.app.license,
            'callback': callback,
            'state': state,
            'secret': secret,
        }, headers={
            'Content-Type': 'application/json',
        })

    if resp.status_code != 200:
        if resp.status_code == 401:
            return flask.abort(405)
        return flask.abort(500)

    tokens_collection = mongo.get_collection('sso_tokens')
    tokens_collection.insert({
        '_id': state,
        'secret': secret,
        'timestamp': utils.now(),
    })

    data = resp.json()

    return flask.redirect(data['url'])
Example #2
0
def sso_request_get():
    state = utils.rand_str(64)
    secret = utils.rand_str(64)
    callback = flask.request.url_root + 'sso/callback'

    if not settings.local.sub_active:
        return flask.abort(405)

    resp = utils.request.post(AUTH_SERVER + '/request/google',
                              json_data={
                                  'license': settings.app.license,
                                  'callback': callback,
                                  'state': state,
                                  'secret': secret,
                              },
                              headers={
                                  'Content-Type': 'application/json',
                              })

    if resp.status_code != 200:
        if resp.status_code == 401:
            return flask.abort(405)
        return flask.abort(500)

    tokens_collection = mongo.get_collection('sso_tokens')
    tokens_collection.insert({
        '_id': state,
        'secret': secret,
        'timestamp': utils.now(),
    })

    data = resp.json()

    return flask.redirect(data['url'])
Example #3
0
    def _stress_thread(self):
        try:
            i = 0

            for org in self.server.iter_orgs():
                for user in org.iter_users():
                    if user.type != CERT_CLIENT:
                        continue

                    i += 1

                    client = {
                        "client_id": i,
                        "key_id": 1,
                        "org_id": org.id,
                        "user_id": user.id,
                        "mac_addr": utils.rand_str(16),
                        "remote_ip": str(ipaddress.IPAddress(100000000 + random.randint(0, 1000000000))),
                        "platform": "linux",
                        "device_id": str(bson.ObjectId()),
                        "device_name": utils.random_name(),
                    }

                    self.clients.connect(client)
        except:
            logger.exception(
                "Error in stress thread",
                "server",
                server_id=self.server.id,
                instance_id=self.instance.id,
                socket_path=self.socket_path,
            )
Example #4
0
def _find_doc(query, one_time=None, one_time_new=False):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one(query)

    if one_time and doc and doc.get('one_time'):
        short_id = utils.rand_str(settings.app.long_url_length)
        collection = mongo.get_collection('users_key_link')

        if one_time_new:
            set_doc = {
                'short_id': short_id,
            }
        else:
            set_doc = {
                'one_time': 'used',
            }

        response = collection.update({
            '_id': doc['_id'],
            'short_id': doc['short_id'],
            'one_time': True,
        }, {'$set': set_doc})
        if not response['updatedExisting']:
            return None

        if one_time_new:
            doc['short_id'] = short_id

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)

    return doc
Example #5
0
def _find_doc(query, one_time=None, one_time_new=False):
    utils.rand_sleep()

    collection = mongo.get_collection('users_key_link')
    doc = collection.find_one(query)

    if one_time and doc and doc.get('one_time'):
        short_id = utils.rand_str(settings.app.long_url_length)
        collection = mongo.get_collection('users_key_link')

        if one_time_new:
            set_doc = {
                'short_id': short_id,
            }
        else:
            set_doc = {
                'one_time': 'used',
            }

        response = collection.update({
            '_id': doc['_id'],
            'short_id': doc['short_id'],
            'one_time': True,
        }, {'$set': set_doc})
        if not response['updatedExisting']:
            return None

        if one_time_new:
            doc['short_id'] = short_id

    if not doc:
        time.sleep(settings.app.rate_limit_sleep)

    return doc
Example #6
0
    def _stress_thread(self):
        try:
            i = 0

            for org in self.server.iter_orgs():
                for user in org.iter_users():
                    if user.type != CERT_CLIENT:
                        continue

                    i += 1

                    client = {
                        'client_id': i,
                        'key_id': 1,
                        'org_id': org.id,
                        'user_id': user.id,
                        'mac_addr': utils.rand_str(16),
                        'remote_ip': str(
                            ipaddress.IPAddress(100000000 + random.randint(
                                0, 1000000000))),
                        'platform': 'linux',
                        'device_id': str(bson.ObjectId()),
                        'device_name': utils.random_name(),
                    }

                    self.clients.connect(client)
        except:
            logger.exception('Error in stress thread', 'server',
                server_id=self.server.id,
                instance_id=self.instance.id,
                socket_path=self.socket_path,
            )
Example #7
0
    def _stress_thread(self):
        try:
            i = 0

            for org in self.server.iter_orgs():
                for user in org.iter_users():
                    if user.type != CERT_CLIENT:
                        continue

                    i += 1

                    client = {
                        'client_id': i,
                        'key_id': 1,
                        'org_id': org.id,
                        'user_id': user.id,
                        'mac_addr': utils.rand_str(16),
                        'remote_ip': str(
                            ipaddress.IPAddress(100000000 + random.randint(
                                0, 1000000000))),
                        'platform': 'linux',
                        'device_id': str(bson.ObjectId()),
                        'device_name': utils.random_name(),
                    }

                    self.clients.connect(client)
        except:
            logger.exception('Error in stress thread', 'server',
                server_id=self.server.id,
                instance_id=self.instance.id,
                socket_path=self.socket_path,
            )
Example #8
0
    def create_user_key_link(self, user_id, one_time=False):
        success = False
        for _ in range(256):
            key_id = utils.rand_str(32)

            if one_time:
                short_id = utils.rand_str(settings.app.long_url_length)
            else:
                short_id = utils.rand_str_ne(settings.app.short_url_length)

            try:
                self.key_link_collection.update(
                    {
                        'org_id': self.id,
                        'user_id': user_id,
                    }, {
                        '$set': {
                            'key_id': key_id,
                            'short_id': short_id,
                            'one_time': one_time,
                            'timestamp': utils.now(),
                        }
                    },
                    upsert=True)
            except pymongo.errors.DuplicateKeyError:
                continue

            success = True
            break

        if not success:
            raise KeyLinkError('Failed to generate random key short id')

        return {
            'id': key_id,
            'key_url': '/key/%s.tar' % key_id,
            'key_zip_url': '/key/%s.zip' % key_id,
            'key_onc_url': '/key_onc/%s.onc' % key_id,
            'view_url': '/k/%s' % short_id,
            'uri_url': '/ku/%s' % short_id,
        }
Example #9
0
    def create_user_key_link(self, user_id, one_time=False):
        success = False
        for _ in xrange(256):
            key_id = utils.rand_str(32)

            if one_time:
                short_id = utils.rand_str(settings.app.long_url_length)
            else:
                short_id = utils.rand_str_ne(settings.app.short_url_length)

            try:
                self.key_link_collection.update({
                    'org_id': self.id,
                    'user_id': user_id,
                }, {'$set': {
                    'key_id': key_id,
                    'short_id': short_id,
                    'one_time': one_time,
                    'timestamp': utils.now(),
                }}, upsert=True)
            except pymongo.errors.DuplicateKeyError:
                continue

            success = True
            break

        if not success:
            raise KeyLinkError('Failed to generate random key short id')

        return {
            'id': key_id,
            'key_url': '/key/%s.tar' % key_id,
            'key_zip_url': '/key/%s.zip' % key_id,
            'key_onc_url': '/key_onc/%s.onc' % key_id,
            'view_url': '/k/%s' % short_id,
            'uri_url': '/ku/%s' % short_id,
        }
Example #10
0
 def generate_key(self):
     self.key = utils.rand_str(64)
Example #11
0
 def generate_secret(self):
     self.secret = utils.rand_str(32)
Example #12
0
def setup_mongo():
    prefix = settings.conf.mongodb_collection_prefix or ''
    last_error = time.time() - 24

    while True:
        try:
            read_pref = _get_read_pref(settings.conf.mongodb_read_preference)

            if read_pref:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                    read_preference=read_pref
                )
            else:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                )

            break
        except pymongo.errors.ConnectionFailure:
            time.sleep(0.5)
            if time.time() - last_error > 30:
                last_error = time.time()
                logger.exception('Error connecting to mongodb server')

    database = client.get_default_database()
    cur_collections = database.collection_names()

    if prefix + 'messages' not in cur_collections:
        database.create_collection(prefix + 'messages', capped=True,
            size=100000, max=1024)

    mongo.collections.update({
        'time_sync': getattr(database, prefix + 'time_sync'),
        'transaction': getattr(database, prefix + 'transaction'),
        'queue': getattr(database, prefix + 'queue'),
        'task': getattr(database, prefix + 'task'),
        'settings': getattr(database, prefix + 'settings'),
        'messages': getattr(database, prefix + 'messages'),
        'administrators': getattr(database, prefix + 'administrators'),
        'users': getattr(database, prefix + 'users'),
        'users_audit': getattr(database, prefix + 'users_audit'),
        'users_key_link': getattr(database, prefix + 'users_key_link'),
        'users_net_link': getattr(database, prefix + 'users_net_link'),
        'clients': getattr(database, prefix + 'clients'),
        'organizations': getattr(database, prefix + 'organizations'),
        'hosts': getattr(database, prefix + 'hosts'),
        'hosts_usage': getattr(database, prefix + 'hosts_usage'),
        'servers': getattr(database, prefix + 'servers'),
        'servers_output': getattr(database, prefix + 'servers_output'),
        'servers_output_link': getattr(database,
            prefix + 'servers_output_link'),
        'servers_bandwidth': getattr(database, prefix + 'servers_bandwidth'),
        'servers_ip_pool': getattr(database, prefix + 'servers_ip_pool'),
        'routes_reserve': getattr(database, prefix + 'routes_reserve'),
        'dh_params': getattr(database, prefix + 'dh_params'),
        'auth_sessions': getattr(database, prefix + 'auth_sessions'),
        'auth_nonces': getattr(database, prefix + 'auth_nonces'),
        'auth_limiter': getattr(database, prefix + 'auth_limiter'),
        'otp': getattr(database, prefix + 'otp'),
        'otp_cache': getattr(database, prefix + 'otp_cache'),
        'sso_tokens': getattr(database, prefix + 'sso_tokens'),
    })

    for collection_name, collection in mongo.collections.items():
        collection.name_str = collection_name

    settings.local.mongo_time = None

    while True:
        try:
            utils.sync_time()
            break
        except:
            logger.exception('Failed to sync time', 'setup')
            time.sleep(30)

    settings.init()

    if prefix + 'logs' not in cur_collections:
        log_limit = settings.app.log_limit
        database.create_collection(prefix + 'logs', capped=True,
            size=log_limit * 1024, max=log_limit)

    if prefix + 'log_entries' not in cur_collections:
        log_entry_limit = settings.app.log_entry_limit
        database.create_collection(prefix + 'log_entries', capped=True,
            size=log_entry_limit * 512, max=log_entry_limit)

    mongo.collections.update({
        'logs': getattr(database, prefix + 'logs'),
        'log_entries': getattr(database, prefix + 'log_entries'),
    })
    mongo.collections['logs'].name_str = 'logs'
    mongo.collections['log_entries'].name_str = 'log_entries'

    upsert_index(mongo.collections['logs'], 'timestamp', background=True)
    upsert_index(mongo.collections['transaction'], 'lock_id',
        background=True, unique=True)
    upsert_index(mongo.collections['transaction'], [
        ('ttl_timestamp', pymongo.ASCENDING),
        ('state', pymongo.ASCENDING),
        ('priority', pymongo.DESCENDING),
    ], background=True)
    upsert_index(mongo.collections['queue'], 'runner_id', background=True)
    upsert_index(mongo.collections['queue'], 'ttl_timestamp', background=True)
    upsert_index(mongo.collections['task'], 'type', background=True,
        unique=True)
    upsert_index(mongo.collections['task'], 'ttl_timestamp', background=True)
    upsert_index(mongo.collections['log_entries'], [
        ('timestamp', pymongo.DESCENDING),
    ], background=True)
    upsert_index(mongo.collections['messages'], 'channel', background=True)
    upsert_index(mongo.collections['administrators'], 'username',
        background=True, unique=True)
    upsert_index(mongo.collections['users'], 'resource_id', background=True)
    upsert_index(mongo.collections['users'], [
        ('type', pymongo.ASCENDING),
        ('org_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['users'], [
        ('org_id', pymongo.ASCENDING),
        ('name', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['users_audit'], [
        ('org_id', pymongo.ASCENDING),
        ('user_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['users_audit'], [
        ('timestamp', pymongo.DESCENDING),
    ], background=True)
    upsert_index(mongo.collections['users_key_link'], 'key_id', background=True)
    upsert_index(mongo.collections['users_key_link'], 'short_id',
        background=True, unique=True)
    upsert_index(mongo.collections['users_net_link'], 'user_id',
        background=True)
    upsert_index(mongo.collections['users_net_link'], 'org_id',
        background=True)
    upsert_index(mongo.collections['users_net_link'], 'network',
        background=True)
    upsert_index(mongo.collections['clients'], 'user_id', background=True)
    upsert_index(mongo.collections['clients'], 'domain', background=True)
    upsert_index(mongo.collections['clients'], [
        ('server_id', pymongo.ASCENDING),
        ('type', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['clients'], [
        ('host_id', pymongo.ASCENDING),
        ('type', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['organizations'], 'type', background=True)
    upsert_index(mongo.collections['organizations'],
        'auth_token', background=True)
    upsert_index(mongo.collections['hosts'], 'name', background=True)
    upsert_index(mongo.collections['hosts_usage'], [
        ('host_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['servers'], 'name', background=True)
    upsert_index(mongo.collections['servers'], 'ping_timestamp',
        background=True)
    upsert_index(mongo.collections['servers_output'], [
        ('server_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['servers_output_link'], [
        ('server_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['servers_bandwidth'], [
        ('server_id', pymongo.ASCENDING),
        ('period', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['servers_ip_pool'], [
        ('server_id', pymongo.ASCENDING),
        ('user_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index(mongo.collections['servers_ip_pool'], 'user_id',
        background=True)
    upsert_index(mongo.collections['routes_reserve'], 'timestamp',
        background=True)
    upsert_index(mongo.collections['dh_params'], 'dh_param_bits',
        background=True)
    upsert_index(mongo.collections['auth_nonces'], [
        ('token', pymongo.ASCENDING),
        ('nonce', pymongo.ASCENDING),
    ], background=True, unique=True)

    upsert_index(mongo.collections['clients'], 'timestamp',
        background=True, expireAfterSeconds=settings.vpn.client_ttl)
    upsert_index(mongo.collections['users_key_link'], 'timestamp',
        background=True, expireAfterSeconds=settings.app.key_link_timeout)
    upsert_index(mongo.collections['auth_sessions'], 'timestamp',
        background=True, expireAfterSeconds=settings.app.session_timeout)
    upsert_index(mongo.collections['auth_nonces'], 'timestamp', background=True,
        expireAfterSeconds=settings.app.auth_time_window * 2.1)
    upsert_index(mongo.collections['auth_limiter'], 'timestamp',
        background=True, expireAfterSeconds=settings.app.auth_limiter_ttl)
    upsert_index(mongo.collections['otp'], 'timestamp', background=True,
        expireAfterSeconds=120)
    upsert_index(mongo.collections['otp_cache'], 'timestamp', background=True,
        expireAfterSeconds=settings.user.otp_cache_ttl)
    upsert_index(mongo.collections['sso_tokens'], 'timestamp', background=True,
        expireAfterSeconds=600)

    if not auth.Administrator.collection.find_one():
        auth.Administrator(
            username=DEFAULT_USERNAME,
            password=DEFAULT_PASSWORD,
            default=True,
        ).commit()

    secret_key = settings.app.cookie_secret
    if not secret_key:
        secret_key = utils.rand_str(64)
        settings.app.cookie_secret = secret_key
        settings.commit()
    app.app.secret_key = secret_key.encode()
Example #13
0
def setup_mongo():
    prefix = settings.conf.mongodb_collection_prefix or ''
    read_pref = _get_read_pref(settings.conf.mongodb_read_preference)
    max_pool = settings.conf.mongodb_max_pool_size or None
    last_error = time.time() - 24

    while True:
        try:

            if read_pref:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                    socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    maxPoolSize=max_pool,
                    read_preference=read_pref,
                )
            else:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                    socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    maxPoolSize=max_pool,
                )

            break
        except pymongo.errors.ConnectionFailure:
            time.sleep(0.5)
            if time.time() - last_error > 30:
                last_error = time.time()
                logger.exception('Error connecting to mongodb server')

    database = client.get_default_database()

    settings_col = getattr(database, prefix + 'settings')
    app_settings = settings_col.find_one({'_id': 'app'})
    if app_settings:
        secondary_mongodb_uri = app_settings.get('secondary_mongodb_uri')
    else:
        secondary_mongodb_uri = None

    if secondary_mongodb_uri:
        while True:
            try:
                read_pref = _get_read_pref(
                    settings.conf.mongodb_read_preference)

                if read_pref:
                    secondary_client = pymongo.MongoClient(
                        secondary_mongodb_uri,
                        connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                        socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        maxPoolSize=max_pool,
                        read_preference=read_pref,
                    )
                else:
                    secondary_client = pymongo.MongoClient(
                        secondary_mongodb_uri,
                        connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                        socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        maxPoolSize=max_pool,
                    )

                break
            except pymongo.errors.ConnectionFailure:
                time.sleep(0.5)
                if time.time() - last_error > 30:
                    last_error = time.time()
                    logger.exception(
                        'Error connecting to secondary mongodb server')

        secondary_database = secondary_client.get_default_database()
    else:
        secondary_database = database

    mongo.database = database
    mongo.secondary_database = secondary_database

    cur_collections = database.collection_names()
    cur_sec_collections = secondary_database.collection_names()
    if 'authorities' in cur_collections or \
            'authorities' in cur_sec_collections:
        raise TypeError('Cannot connect to a Pritunl Zero database')

    mongo.collection_types = {
        'transaction': 1,
        'queue': 1,
        'tasks': 1,
        'settings': 1,
        'messages': 2,
        'administrators': 1,
        'users': 1,
        'users_audit': 1,
        'users_key_link': 2,
        'users_net_link': 1,
        'clients': 1,
        'clients_pool': 1,
        'organizations': 1,
        'hosts': 1,
        'hosts_usage': 1,
        'servers': 1,
        'servers_output': 1,
        'servers_output_link': 1,
        'servers_bandwidth': 1,
        'servers_ip_pool': 1,
        'links': 1,
        'links_locations': 1,
        'links_hosts': 1,
        'routes_reserve': 1,
        'dh_params': 1,
        'acme_challenges': 1,
        'auth_sessions': 2,
        'auth_csrf_tokens': 2,
        'auth_nonces': 2,
        'auth_limiter': 2,
        'otp': 2,
        'otp_cache': 2,
        'yubikey': 2,
        'sso_tokens': 2,
        'sso_push_cache': 2,
        'sso_client_cache': 2,
        'sso_passcode_cache': 2,
        'vxlans': 1,
        'logs': 1,
        'log_entries': 1,
    }

    cur_collections = mongo.secondary_database.collection_names()
    if prefix + 'messages' not in cur_collections:
        mongo.secondary_database.create_collection(
            prefix + 'messages', capped=True,
            size=5000192, max=1000)
    elif not mongo.get_collection('messages').options().get('capped'):
        mongo.get_collection('messages').drop()
        mongo.secondary_database.create_collection(
            prefix + 'messages', capped=True,
            size=5000192, max=1000)

    settings.local.mongo_time = None

    while True:
        try:
            utils.sync_time()
            break
        except:
            logger.exception('Failed to sync time', 'setup')
            time.sleep(30)

    settings.init()

    upsert_indexes()

    if not auth.Administrator.collection.find_one():
        default_admin = auth.Administrator(
            username=DEFAULT_USERNAME,
        )
        default_admin.generate_default_password()
        default_admin.commit()

    secret_key = settings.app.cookie_secret
    secret_key2 = settings.app.cookie_secret2
    settings_commit = False

    if not secret_key:
        settings_commit = True
        secret_key = utils.rand_str(64)
        settings.app.cookie_secret = secret_key

    if not secret_key2:
        settings_commit = True
        settings.app.cookie_secret2 = utils.rand_str(64)

    if settings_commit:
        settings.commit()

    app.app.secret_key = secret_key.encode()
Example #14
0
def sso_request_get():
    sso_mode = settings.app.sso

    if sso_mode not in (GOOGLE_AUTH, GOOGLE_DUO_AUTH, SLACK_AUTH,
            SLACK_DUO_AUTH, SAML_AUTH, SAML_DUO_AUTH, SAML_OKTA_AUTH,
            SAML_OKTA_DUO_AUTH, SAML_ONELOGIN_AUTH, SAML_ONELOGIN_DUO_AUTH):
        return flask.abort(405)

    state = utils.rand_str(64)
    secret = utils.rand_str(64)
    callback = utils.get_url_root() + 'sso/callback'

    if not settings.local.sub_active:
        logger.error('Subscription must be active for sso', 'sso')
        return flask.abort(405)

    if GOOGLE_AUTH in sso_mode:
        resp = requests.post(AUTH_SERVER + '/v1/request/google',
            headers={
                'Content-Type': 'application/json',
            },
            json={
                'license': settings.app.license,
                'callback': callback,
                'state': state,
                'secret': secret,
            }
        )

        if resp.status_code != 200:
            logger.error('Google auth server error', 'sso',
                status_code=resp.status_code,
                content=resp.content,
            )

            if resp.status_code == 401:
                return flask.abort(405)

            return flask.abort(500)

        tokens_collection = mongo.get_collection('sso_tokens')
        tokens_collection.insert({
            '_id': state,
            'type': GOOGLE_AUTH,
            'secret': secret,
            'timestamp': utils.now(),
        })

        data = resp.json()

        return utils.redirect(data['url'])

    elif SLACK_AUTH in sso_mode:
        resp = requests.post(AUTH_SERVER + '/v1/request/slack',
            headers={
                'Content-Type': 'application/json',
            },
            json={
                'license': settings.app.license,
                'callback': callback,
                'state': state,
                'secret': secret,
            }
        )

        if resp.status_code != 200:
            logger.error('Slack auth server error', 'sso',
                status_code=resp.status_code,
                content=resp.content,
            )

            if resp.status_code == 401:
                return flask.abort(405)

            return flask.abort(500)

        tokens_collection = mongo.get_collection('sso_tokens')
        tokens_collection.insert({
            '_id': state,
            'type': SLACK_AUTH,
            'secret': secret,
            'timestamp': utils.now(),
        })

        data = resp.json()

        return utils.redirect(data['url'])

    elif SAML_AUTH in sso_mode:
        resp = requests.post(AUTH_SERVER + '/v1/request/saml',
            headers={
                'Content-Type': 'application/json',
            },
            json={
                'license': settings.app.license,
                'callback': callback,
                'state': state,
                'secret': secret,
                'sso_url': settings.app.sso_saml_url,
                'issuer_url': settings.app.sso_saml_issuer_url,
                'cert': settings.app.sso_saml_cert,
            },
        )

        if resp.status_code != 200:
            logger.error('Saml auth server error', 'sso',
                status_code=resp.status_code,
                content=resp.content,
            )

            if resp.status_code == 401:
                return flask.abort(405)

            return flask.abort(500)

        tokens_collection = mongo.get_collection('sso_tokens')
        tokens_collection.insert({
            '_id': state,
            'type': SAML_AUTH,
            'secret': secret,
            'timestamp': utils.now(),
        })

        return flask.Response(
            status=200,
            response=resp.content,
            content_type="text/html;charset=utf-8",
        )
Example #15
0
def setup_mongo():
    prefix = settings.conf.mongodb_collection_prefix or ''
    last_error = time.time() - 24

    while True:
        try:
            read_pref = _get_read_pref(settings.conf.mongodb_read_preference)

            if read_pref:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                    socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    read_preference=read_pref,
                )
            else:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                    socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                )

            break
        except pymongo.errors.ConnectionFailure:
            time.sleep(0.5)
            if time.time() - last_error > 30:
                last_error = time.time()
                logger.exception('Error connecting to mongodb server')

    database = client.get_default_database()

    settings_col = getattr(database, prefix + 'settings')
    app_settings = settings_col.find_one({'_id': 'app'})
    if app_settings:
        secondary_mongodb_uri = app_settings.get('secondary_mongodb_uri')
    else:
        secondary_mongodb_uri = None

    if secondary_mongodb_uri:
        while True:
            try:
                read_pref = _get_read_pref(
                    settings.conf.mongodb_read_preference)

                if read_pref:
                    secondary_client = pymongo.MongoClient(
                        settings.conf.mongodb_uri,
                        connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                        socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        read_preference=read_pref,
                    )
                else:
                    secondary_client = pymongo.MongoClient(
                        settings.conf.mongodb_uri,
                        connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                        socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    )

                break
            except pymongo.errors.ConnectionFailure:
                time.sleep(0.5)
                if time.time() - last_error > 30:
                    last_error = time.time()
                    logger.exception(
                        'Error connecting to secondary mongodb server')

        secondary_database = secondary_client.get_default_database()
    else:
        secondary_database = database

    cur_collections = secondary_database.collection_names()
    if prefix + 'messages' not in cur_collections:
        secondary_database.create_collection(prefix + 'messages',
                                             capped=True,
                                             size=5000192,
                                             max=1500)

    mongo.collections.update({
        'transaction':
        getattr(database, prefix + 'transaction'),
        'queue':
        getattr(database, prefix + 'queue'),
        'tasks':
        getattr(database, prefix + 'tasks'),
        'settings':
        getattr(database, prefix + 'settings'),
        'messages':
        getattr(secondary_database, prefix + 'messages'),
        'administrators':
        getattr(database, prefix + 'administrators'),
        'users':
        getattr(database, prefix + 'users'),
        'users_audit':
        getattr(database, prefix + 'users_audit'),
        'users_key_link':
        getattr(secondary_database, prefix + 'users_key_link'),
        'users_net_link':
        getattr(database, prefix + 'users_net_link'),
        'clients':
        getattr(database, prefix + 'clients'),
        'clients_pool':
        getattr(database, prefix + 'clients_pool'),
        'organizations':
        getattr(database, prefix + 'organizations'),
        'hosts':
        getattr(database, prefix + 'hosts'),
        'hosts_usage':
        getattr(database, prefix + 'hosts_usage'),
        'servers':
        getattr(database, prefix + 'servers'),
        'servers_output':
        getattr(database, prefix + 'servers_output'),
        'servers_output_link':
        getattr(database, prefix + 'servers_output_link'),
        'servers_bandwidth':
        getattr(database, prefix + 'servers_bandwidth'),
        'servers_ip_pool':
        getattr(database, prefix + 'servers_ip_pool'),
        'routes_reserve':
        getattr(database, prefix + 'routes_reserve'),
        'dh_params':
        getattr(database, prefix + 'dh_params'),
        'auth_sessions':
        getattr(secondary_database, prefix + 'auth_sessions'),
        'auth_csrf_tokens':
        getattr(secondary_database, prefix + 'auth_csrf_tokens'),
        'auth_nonces':
        getattr(secondary_database, prefix + 'auth_nonces'),
        'auth_limiter':
        getattr(secondary_database, prefix + 'auth_limiter'),
        'otp':
        getattr(secondary_database, prefix + 'otp'),
        'otp_cache':
        getattr(secondary_database, prefix + 'otp_cache'),
        'sso_tokens':
        getattr(secondary_database, prefix + 'sso_tokens'),
        'sso_cache':
        getattr(secondary_database, prefix + 'sso_cache'),
        'vxlans':
        getattr(database, prefix + 'vxlans'),
    })

    for collection_name, collection in mongo.collections.items():
        collection.name_str = collection_name

    settings.local.mongo_time = None

    while True:
        try:
            utils.sync_time()
            break
        except:
            logger.exception('Failed to sync time', 'setup')
            time.sleep(30)

    settings.init()

    cur_collections = database.collection_names()
    if prefix + 'logs' not in cur_collections:
        log_limit = settings.app.log_limit
        database.create_collection(prefix + 'logs',
                                   capped=True,
                                   size=log_limit * 1024,
                                   max=log_limit)

    if prefix + 'log_entries' not in cur_collections:
        log_entry_limit = settings.app.log_entry_limit
        database.create_collection(prefix + 'log_entries',
                                   capped=True,
                                   size=log_entry_limit * 512,
                                   max=log_entry_limit)

    mongo.collections.update({
        'logs':
        getattr(database, prefix + 'logs'),
        'log_entries':
        getattr(database, prefix + 'log_entries'),
    })
    mongo.collections['logs'].name_str = 'logs'
    mongo.collections['log_entries'].name_str = 'log_entries'

    upsert_index(mongo.collections['logs'], 'timestamp', background=True)
    upsert_index(mongo.collections['transaction'],
                 'lock_id',
                 background=True,
                 unique=True)
    upsert_index(mongo.collections['transaction'], [
        ('ttl_timestamp', pymongo.ASCENDING),
        ('state', pymongo.ASCENDING),
        ('priority', pymongo.DESCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['queue'], 'runner_id', background=True)
    upsert_index(mongo.collections['queue'], 'ttl_timestamp', background=True)
    upsert_index(mongo.collections['tasks'], [
        ('ttl_timestamp', pymongo.ASCENDING),
        ('state', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['log_entries'], [
        ('timestamp', pymongo.DESCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['messages'], 'channel', background=True)
    upsert_index(mongo.collections['administrators'],
                 'username',
                 background=True,
                 unique=True)
    upsert_index(mongo.collections['users'], 'resource_id', background=True)
    upsert_index(mongo.collections['users'], [
        ('type', pymongo.ASCENDING),
        ('org_id', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['users'], [
        ('org_id', pymongo.ASCENDING),
        ('name', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['users_audit'], [
        ('org_id', pymongo.ASCENDING),
        ('user_id', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['users_audit'], [
        ('timestamp', pymongo.DESCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['users_key_link'],
                 'key_id',
                 background=True)
    upsert_index(mongo.collections['users_key_link'],
                 'short_id',
                 background=True,
                 unique=True)
    upsert_index(mongo.collections['users_net_link'],
                 'user_id',
                 background=True)
    upsert_index(mongo.collections['users_net_link'],
                 'org_id',
                 background=True)
    upsert_index(mongo.collections['users_net_link'],
                 'network',
                 background=True)
    upsert_index(mongo.collections['clients'], 'user_id', background=True)
    upsert_index(mongo.collections['clients'], 'domain', background=True)
    upsert_index(mongo.collections['clients'],
                 'virt_address_num',
                 background=True)
    upsert_index(mongo.collections['clients'], [
        ('server_id', pymongo.ASCENDING),
        ('type', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['clients'], [
        ('host_id', pymongo.ASCENDING),
        ('type', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['clients_pool'],
                 'client_id',
                 background=True)
    upsert_index(mongo.collections['clients_pool'],
                 'timestamp',
                 background=True)
    upsert_index(mongo.collections['clients_pool'], [
        ('server_id', pymongo.ASCENDING),
        ('user_id', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['organizations'], 'type', background=True)
    upsert_index(mongo.collections['organizations'],
                 'auth_token',
                 background=True)
    upsert_index(mongo.collections['hosts'], 'name', background=True)
    upsert_index(mongo.collections['hosts_usage'], [
        ('host_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['servers'], 'name', background=True)
    upsert_index(mongo.collections['servers'],
                 'ping_timestamp',
                 background=True)
    upsert_index(mongo.collections['servers_output'], [
        ('server_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['servers_output_link'], [
        ('server_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['servers_bandwidth'], [
        ('server_id', pymongo.ASCENDING),
        ('period', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['servers_ip_pool'], [
        ('server_id', pymongo.ASCENDING),
        ('user_id', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['servers_ip_pool'], [
        ('server_id', pymongo.ASCENDING),
        ('_id', pymongo.DESCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['servers_ip_pool'],
                 'user_id',
                 background=True)
    upsert_index(mongo.collections['routes_reserve'],
                 'timestamp',
                 background=True)
    upsert_index(mongo.collections['dh_params'],
                 'dh_param_bits',
                 background=True)
    upsert_index(mongo.collections['auth_nonces'], [
        ('token', pymongo.ASCENDING),
        ('nonce', pymongo.ASCENDING),
    ],
                 background=True,
                 unique=True)
    upsert_index(mongo.collections['sso_cache'], [
        ('user_id', pymongo.ASCENDING),
        ('server_id', pymongo.ASCENDING),
        ('remote_ip', pymongo.ASCENDING),
        ('mac_addr', pymongo.ASCENDING),
        ('platform', pymongo.ASCENDING),
        ('device_name', pymongo.ASCENDING),
    ],
                 background=True)
    upsert_index(mongo.collections['vxlans'],
                 'server_id',
                 background=True,
                 unique=True)

    upsert_index(mongo.collections['tasks'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=300)
    upsert_index(mongo.collections['clients'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=settings.vpn.client_ttl)
    upsert_index(mongo.collections['users_key_link'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=settings.app.key_link_timeout)
    upsert_index(mongo.collections['auth_sessions'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=settings.app.session_timeout)
    upsert_index(mongo.collections['auth_nonces'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=settings.app.auth_time_window * 2.1)
    upsert_index(mongo.collections['auth_limiter'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=settings.app.auth_limiter_ttl)
    upsert_index(mongo.collections['otp'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=120)
    upsert_index(mongo.collections['otp_cache'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=settings.user.otp_cache_ttl)
    upsert_index(mongo.collections['sso_tokens'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=600)
    upsert_index(mongo.collections['sso_cache'],
                 'timestamp',
                 background=True,
                 expireAfterSeconds=settings.app.sso_cache_timeout)

    if not auth.Administrator.collection.find_one():
        auth.Administrator(
            username=DEFAULT_USERNAME,
            password=DEFAULT_PASSWORD,
            default=True,
        ).commit()

    secret_key = settings.app.cookie_secret
    secret_key2 = settings.app.cookie_secret2
    settings_commit = False

    if not secret_key:
        settings_commit = True
        secret_key = utils.rand_str(64)
        settings.app.cookie_secret = secret_key

    if not secret_key2:
        settings_commit = True
        settings.app.cookie_secret2 = utils.rand_str(64)

    if settings_commit:
        settings.commit()

    app.app.secret_key = secret_key.encode()
Example #16
0
    def thread():
        platforms = list(DESKTOP_PLATFORMS)
        start_timestamp = datetime.datetime(2015, 12, 28, 4, 1, 0)
        hosts_collection = mongo.get_collection('hosts')
        servers_collection  = mongo.get_collection('servers')
        clients_collection = mongo.get_collection('clients')

        clients_collection.remove({})

        for hst in host.iter_hosts():
            hosts_collection.update({
                '_id': hst.id,
            }, {'$set': {
                'server_count': 0,
                'device_count': 0,
                'cpu_usage': 0,
                'mem_usage': 0,
                'thread_count': 0,
                'open_file_count': 0,
                'status': ONLINE,
                'start_timestamp': start_timestamp,
                'ping_timestamp': start_timestamp,
                'auto_public_address': None,
                'auto_public_address6': None,
                'auto_public_host': hst.name + '.pritunl.com',
                'auto_public_host6': hst.name + '.pritunl.com',
            }})

        for svr in server.iter_servers():
            prefered_hosts = host.get_prefered_hosts(
                svr.hosts, svr.replica_count)

            instances = []
            for hst in prefered_hosts:
                instances.append({
                    'instance_id': utils.ObjectId(),
                    'host_id': hst,
                    'ping_timestamp': utils.now(),
                })

            servers_collection.update({
                '_id': svr.id,
            }, {'$set': {
                'status': ONLINE,
                'pool_cursor': None,
                'start_timestamp': start_timestamp,
                'availability_group': DEFAULT,
                'instances': instances,
                'instances_count': len(instances),
            }})

            for org in svr.iter_orgs():
                for usr in org.iter_users():
                    if usr.type != CERT_CLIENT:
                        continue

                    virt_address = svr.get_ip_addr(org.id, usr.id)
                    virt_address6 = svr.ip4to6(virt_address)

                    doc = {
                        '_id': utils.ObjectId(),
                        'user_id': usr.id,
                        'server_id': svr.id,
                        'host_id': settings.local.host_id,
                        'timestamp': start_timestamp,
                        'platform': random.choice(platforms),
                        'type': CERT_CLIENT,
                        'device_name': utils.random_name(),
                        'mac_addr': utils.rand_str(16),
                        'network': svr.network,
                        'real_address': str(
                            ipaddress.IPAddress(100000000 + random.randint(
                                0, 1000000000))),
                        'virt_address': virt_address,
                        'virt_address6': virt_address6,
                        'host_address': settings.local.host.local_addr,
                        'host_address6': settings.local.host.local_addr6,
                        'dns_servers': [],
                        'dns_suffix': None,
                        'connected_since': int(start_timestamp.strftime('%s')),
                    }

                    clients_collection.insert(doc)

        for lnk in link.iter_links():
            lnk.status = ONLINE
            lnk.commit()

            for location in lnk.iter_locations():
                active = False
                for hst in location.iter_hosts():
                    if not active:
                        hst.active = True
                        active = True
                    hst.status = AVAILABLE
                    hst.commit(('active', 'status'))

        logger.info('Demo initiated', 'demo')
Example #17
0
 def generate_secret(self):
     self.secret = utils.rand_str(32)
Example #18
0
 def generate_key(self):
     self.key = utils.rand_str(64)
Example #19
0
def setup_mongo():
    prefix = settings.conf.mongodb_collection_prefix or ''
    last_error = time.time() - 24
    while True:
        try:
            client = pymongo.MongoClient(
                settings.conf.mongodb_uri,
                connectTimeoutMS=MONGO_CONNECT_TIMEOUT)
            break
        except pymongo.errors.ConnectionFailure:
            time.sleep(0.5)
            if time.time() - last_error > 30:
                last_error = time.time()
                logger.exception('Error connecting to mongodb server')

    database = client.get_default_database()
    cur_collections = database.collection_names()

    if prefix + 'messages' not in cur_collections:
        database.create_collection(prefix + 'messages',
                                   capped=True,
                                   size=100000,
                                   max=1024)

    mongo.collections.update({
        'time_sync':
        getattr(database, prefix + 'time_sync'),
        'transaction':
        getattr(database, prefix + 'transaction'),
        'queue':
        getattr(database, prefix + 'queue'),
        'task':
        getattr(database, prefix + 'task'),
        'settings':
        getattr(database, prefix + 'settings'),
        'messages':
        getattr(database, prefix + 'messages'),
        'administrators':
        getattr(database, prefix + 'administrators'),
        'users':
        getattr(database, prefix + 'users'),
        'users_key_link':
        getattr(database, prefix + 'users_key_link'),
        'clients':
        getattr(database, prefix + 'clients'),
        'organizations':
        getattr(database, prefix + 'organizations'),
        'hosts':
        getattr(database, prefix + 'hosts'),
        'hosts_usage':
        getattr(database, prefix + 'hosts_usage'),
        'servers':
        getattr(database, prefix + 'servers'),
        'servers_output':
        getattr(database, prefix + 'servers_output'),
        'servers_output_link':
        getattr(database, prefix + 'servers_output_link'),
        'servers_bandwidth':
        getattr(database, prefix + 'servers_bandwidth'),
        'servers_ip_pool':
        getattr(database, prefix + 'servers_ip_pool'),
        'dh_params':
        getattr(database, prefix + 'dh_params'),
        'auth_sessions':
        getattr(database, prefix + 'auth_sessions'),
        'auth_nonces':
        getattr(database, prefix + 'auth_nonces'),
        'auth_limiter':
        getattr(database, prefix + 'auth_limiter'),
        'otp':
        getattr(database, prefix + 'otp'),
        'otp_cache':
        getattr(database, prefix + 'otp_cache'),
        'sso_tokens':
        getattr(database, prefix + 'sso_tokens'),
    })

    for collection_name, collection in mongo.collections.items():
        collection.name_str = collection_name

    utils.sync_time()

    settings.init()

    if prefix + 'logs' not in cur_collections:
        log_limit = settings.app.log_limit
        database.create_collection(prefix + 'logs',
                                   capped=True,
                                   size=log_limit * 1024,
                                   max=log_limit)

    if prefix + 'log_entries' not in cur_collections:
        log_entry_limit = settings.app.log_entry_limit
        database.create_collection(prefix + 'log_entries',
                                   capped=True,
                                   size=log_entry_limit * 512,
                                   max=log_entry_limit)

    mongo.collections.update({
        'logs':
        getattr(database, prefix + 'logs'),
        'log_entries':
        getattr(database, prefix + 'log_entries'),
    })
    mongo.collections['logs'].name_str = 'logs'
    mongo.collections['log_entries'].name_str = 'log_entries'

    mongo.collections['logs'].ensure_index('timestamp', background=True)
    mongo.collections['transaction'].ensure_index('lock_id',
                                                  background=True,
                                                  unique=True)
    mongo.collections['transaction'].ensure_index([
        ('ttl_timestamp', pymongo.ASCENDING),
        ('state', pymongo.ASCENDING),
        ('priority', pymongo.DESCENDING),
    ],
                                                  background=True)
    mongo.collections['queue'].ensure_index('runner_id', background=True)
    mongo.collections['queue'].ensure_index('ttl_timestamp', background=True)
    mongo.collections['task'].ensure_index('type',
                                           background=True,
                                           unique=True)
    mongo.collections['task'].ensure_index('ttl_timestamp', background=True)
    mongo.collections['log_entries'].ensure_index([
        ('timestamp', pymongo.DESCENDING),
    ],
                                                  background=True)
    mongo.collections['messages'].ensure_index('channel', background=True)
    mongo.collections['administrators'].ensure_index('username',
                                                     background=True,
                                                     unique=True)
    mongo.collections['users'].ensure_index('resource_id', background=True)
    mongo.collections['users'].ensure_index([
        ('type', pymongo.ASCENDING),
        ('org_id', pymongo.ASCENDING),
    ],
                                            background=True)
    mongo.collections['users'].ensure_index([
        ('org_id', pymongo.ASCENDING),
        ('name', pymongo.ASCENDING),
    ],
                                            background=True)
    mongo.collections['users_key_link'].ensure_index('key_id', background=True)
    mongo.collections['users_key_link'].ensure_index('short_id',
                                                     background=True,
                                                     unique=True)
    mongo.collections['clients'].ensure_index('user_id', background=True)
    mongo.collections['clients'].ensure_index('domain', background=True)
    mongo.collections['clients'].ensure_index([
        ('server_id', pymongo.ASCENDING),
        ('type', pymongo.ASCENDING),
    ],
                                              background=True)
    mongo.collections['organizations'].ensure_index('type', background=True)
    mongo.collections['hosts'].ensure_index('name', background=True)
    mongo.collections['hosts_usage'].ensure_index([
        ('host_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ],
                                                  background=True)
    mongo.collections['servers'].ensure_index('name', background=True)
    mongo.collections['servers'].ensure_index('ping_timestamp',
                                              background=True)
    mongo.collections['servers_output'].ensure_index([
        ('server_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ],
                                                     background=True)
    mongo.collections['servers_output_link'].ensure_index([
        ('server_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ],
                                                          background=True)
    mongo.collections['servers_bandwidth'].ensure_index([
        ('server_id', pymongo.ASCENDING),
        ('period', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ],
                                                        background=True)
    mongo.collections['servers_ip_pool'].ensure_index([
        ('server_id', pymongo.ASCENDING),
        ('user_id', pymongo.ASCENDING),
    ],
                                                      background=True)
    mongo.collections['servers_ip_pool'].ensure_index('user_id',
                                                      background=True)
    mongo.collections['dh_params'].ensure_index('dh_param_bits',
                                                background=True)
    mongo.collections['auth_nonces'].ensure_index([
        ('token', pymongo.ASCENDING),
        ('nonce', pymongo.ASCENDING),
    ],
                                                  background=True,
                                                  unique=True)

    mongo.collections['clients'].ensure_index(
        'timestamp',
        background=True,
        expireAfterSeconds=settings.vpn.client_ttl)
    mongo.collections['users_key_link'].ensure_index(
        'timestamp',
        background=True,
        expireAfterSeconds=settings.app.key_link_timeout)
    mongo.collections['auth_sessions'].ensure_index(
        'timestamp',
        background=True,
        expireAfterSeconds=settings.app.session_timeout)
    mongo.collections['auth_nonces'].ensure_index(
        'timestamp',
        background=True,
        expireAfterSeconds=settings.app.auth_time_window * 2.1)
    mongo.collections['auth_limiter'].ensure_index(
        'timestamp',
        background=True,
        expireAfterSeconds=settings.app.auth_limiter_ttl)
    mongo.collections['otp'].ensure_index('timestamp',
                                          background=True,
                                          expireAfterSeconds=120)
    mongo.collections['otp_cache'].ensure_index(
        'timestamp',
        background=True,
        expireAfterSeconds=settings.user.otp_cache_ttl)
    mongo.collections['sso_tokens'].ensure_index('timestamp',
                                                 background=True,
                                                 expireAfterSeconds=600)

    if not auth.Administrator.collection.find_one():
        auth.Administrator(
            username=DEFAULT_USERNAME,
            password=DEFAULT_PASSWORD,
            default=True,
        ).commit()

    secret_key = settings.app.cookie_secret
    if not secret_key:
        secret_key = utils.rand_str(64)
        settings.app.cookie_secret = secret_key
        settings.commit()
    app.app.secret_key = secret_key.encode()
Example #20
0
    def thread():
        platforms = list(DESKTOP_PLATFORMS)
        start_timestamp = datetime.datetime(2015, 12, 28, 4, 1, 0)
        hosts_collection = mongo.get_collection('hosts')
        servers_collection = mongo.get_collection('servers')
        clients_collection = mongo.get_collection('clients')

        clients_collection.remove({})

        for hst in host.iter_hosts():
            hosts_collection.update({
                '_id': hst.id,
            }, {
                '$set': {
                    'server_count': 0,
                    'device_count': 0,
                    'cpu_usage': 0,
                    'mem_usage': 0,
                    'thread_count': 0,
                    'open_file_count': 0,
                    'status': ONLINE,
                    'start_timestamp': start_timestamp,
                    'ping_timestamp': start_timestamp,
                    'auto_public_address': None,
                    'auto_public_address6': None,
                    'auto_public_host': hst.name + '.pritunl.com',
                    'auto_public_host6': hst.name + '.pritunl.com',
                }
            })

        for svr in server.iter_servers():
            prefered_hosts = host.get_prefered_hosts(svr.hosts,
                                                     svr.replica_count)

            instances = []
            for hst in prefered_hosts:
                instances.append({
                    'instance_id': utils.ObjectId(),
                    'host_id': hst,
                    'ping_timestamp': utils.now(),
                })

            servers_collection.update({
                '_id': svr.id,
            }, {
                '$set': {
                    'status': ONLINE,
                    'pool_cursor': None,
                    'start_timestamp': start_timestamp,
                    'availability_group': DEFAULT,
                    'instances': instances,
                    'instances_count': len(instances),
                }
            })

            for org in svr.iter_orgs():
                for usr in org.iter_users():
                    if usr.type != CERT_CLIENT:
                        continue

                    virt_address = svr.get_ip_addr(org.id, usr.id)
                    virt_address6 = svr.ip4to6(virt_address)

                    doc = {
                        '_id':
                        utils.ObjectId(),
                        'user_id':
                        usr.id,
                        'server_id':
                        svr.id,
                        'host_id':
                        settings.local.host_id,
                        'timestamp':
                        start_timestamp,
                        'platform':
                        random.choice(platforms),
                        'type':
                        CERT_CLIENT,
                        'device_name':
                        utils.random_name(),
                        'mac_addr':
                        utils.rand_str(16),
                        'network':
                        svr.network,
                        'real_address':
                        str(
                            ipaddress.IPAddress(
                                100000000 + random.randint(0, 1000000000))),
                        'virt_address':
                        virt_address,
                        'virt_address6':
                        virt_address6,
                        'host_address':
                        settings.local.host.local_addr,
                        'host_address6':
                        settings.local.host.local_addr6,
                        'dns_servers': [],
                        'dns_suffix':
                        None,
                        'connected_since':
                        int(start_timestamp.strftime('%s')),
                    }

                    clients_collection.insert(doc)

        for lnk in link.iter_links():
            lnk.status = ONLINE
            lnk.commit()

            for location in lnk.iter_locations():
                active = False
                for hst in location.iter_hosts():
                    if not active:
                        hst.active = True
                        active = True
                    hst.status = AVAILABLE
                    hst.commit(('active', 'status'))

        logger.info('Demo initiated', 'demo')
Example #21
0
def setup_mongo():
    prefix = settings.conf.mongodb_collection_prefix or ''
    last_error = time.time() - 24

    while True:
        try:
            read_pref = _get_read_pref(settings.conf.mongodb_read_preference)

            if read_pref:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                    socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    read_preference=read_pref,
                )
            else:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                    socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                )

            break
        except pymongo.errors.ConnectionFailure:
            time.sleep(0.5)
            if time.time() - last_error > 30:
                last_error = time.time()
                logger.exception('Error connecting to mongodb server')

    database = client.get_default_database()

    settings_col = getattr(database, prefix + 'settings')
    app_settings = settings_col.find_one({'_id': 'app'})
    if app_settings:
        secondary_mongodb_uri = app_settings.get('secondary_mongodb_uri')
    else:
        secondary_mongodb_uri = None

    if secondary_mongodb_uri:
        while True:
            try:
                read_pref = _get_read_pref(
                    settings.conf.mongodb_read_preference)

                if read_pref:
                    secondary_client = pymongo.MongoClient(
                        settings.conf.mongodb_uri,
                        connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                        socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        read_preference=read_pref,
                    )
                else:
                    secondary_client = pymongo.MongoClient(
                        settings.conf.mongodb_uri,
                        connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                        socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    )

                break
            except pymongo.errors.ConnectionFailure:
                time.sleep(0.5)
                if time.time() - last_error > 30:
                    last_error = time.time()
                    logger.exception(
                        'Error connecting to secondary mongodb server')

        secondary_database = secondary_client.get_default_database()
    else:
        secondary_database = database

    mongo.database = database
    mongo.secondary_database = secondary_database

    cur_collections = secondary_database.collection_names()
    if prefix + 'messages' not in cur_collections:
        secondary_database.create_collection(prefix + 'messages', capped=True,
            size=5000192, max=1000)

    mongo.collections.update({
        'transaction': getattr(database, prefix + 'transaction'),
        'queue': getattr(database, prefix + 'queue'),
        'tasks': getattr(database, prefix + 'tasks'),
        'settings': getattr(database, prefix + 'settings'),
        'messages': getattr(secondary_database, prefix + 'messages'),
        'administrators': getattr(database, prefix + 'administrators'),
        'users': getattr(database, prefix + 'users'),
        'users_audit': getattr(database, prefix + 'users_audit'),
        'users_key_link': getattr(secondary_database,
            prefix + 'users_key_link'),
        'users_net_link': getattr(database, prefix + 'users_net_link'),
        'clients': getattr(database, prefix + 'clients'),
        'clients_pool': getattr(database, prefix + 'clients_pool'),
        'organizations': getattr(database, prefix + 'organizations'),
        'hosts': getattr(database, prefix + 'hosts'),
        'hosts_usage': getattr(database, prefix + 'hosts_usage'),
        'servers': getattr(database, prefix + 'servers'),
        'servers_output': getattr(database, prefix + 'servers_output'),
        'servers_output_link': getattr(database,
            prefix + 'servers_output_link'),
        'servers_bandwidth': getattr(database, prefix + 'servers_bandwidth'),
        'servers_ip_pool': getattr(database, prefix + 'servers_ip_pool'),
        'links': getattr(database, prefix + 'links'),
        'links_locations': getattr(database, prefix + 'links_locations'),
        'links_hosts': getattr(database, prefix + 'links_hosts'),
        'routes_reserve': getattr(database, prefix + 'routes_reserve'),
        'dh_params': getattr(database, prefix + 'dh_params'),
        'auth_sessions': getattr(secondary_database,
            prefix + 'auth_sessions'),
        'auth_csrf_tokens': getattr(secondary_database,
            prefix + 'auth_csrf_tokens'),
        'auth_nonces': getattr(secondary_database, prefix + 'auth_nonces'),
        'auth_limiter': getattr(secondary_database, prefix + 'auth_limiter'),
        'otp': getattr(secondary_database, prefix + 'otp'),
        'otp_cache': getattr(secondary_database, prefix + 'otp_cache'),
        'yubikey': getattr(secondary_database, prefix + 'yubikey'),
        'sso_tokens': getattr(secondary_database, prefix + 'sso_tokens'),
        'sso_push_cache': getattr(secondary_database,
            prefix + 'sso_push_cache'),
        'sso_client_cache': getattr(secondary_database,
            prefix + 'sso_client_cache'),
        'sso_passcode_cache': getattr(secondary_database,
            prefix + 'sso_passcode_cache'),
        'vxlans': getattr(database, prefix + 'vxlans'),
    })

    for collection_name, collection in mongo.collections.items():
        collection.name_str = collection_name

    settings.local.mongo_time = None

    while True:
        try:
            utils.sync_time()
            break
        except:
            logger.exception('Failed to sync time', 'setup')
            time.sleep(30)

    settings.init()

    cur_collections = database.collection_names()
    if prefix + 'logs' not in cur_collections:
        log_limit = settings.app.log_limit
        database.create_collection(prefix + 'logs', capped=True,
            size=log_limit * 1024, max=log_limit)

    if prefix + 'log_entries' not in cur_collections:
        log_entry_limit = settings.app.log_entry_limit
        database.create_collection(prefix + 'log_entries', capped=True,
            size=log_entry_limit * 512, max=log_entry_limit)

    mongo.collections.update({
        'logs': getattr(database, prefix + 'logs'),
        'log_entries': getattr(database, prefix + 'log_entries'),
    })
    mongo.collections['logs'].name_str = 'logs'
    mongo.collections['log_entries'].name_str = 'log_entries'

    upsert_index('logs', 'timestamp', background=True)
    upsert_index('transaction', 'lock_id',
        background=True, unique=True)
    upsert_index('transaction', [
        ('ttl_timestamp', pymongo.ASCENDING),
        ('state', pymongo.ASCENDING),
        ('priority', pymongo.DESCENDING),
    ], background=True)
    upsert_index('queue', 'runner_id', background=True)
    upsert_index('queue', 'ttl_timestamp', background=True)
    upsert_index('queue', [
        ('priority', pymongo.ASCENDING),
        ('ttl_timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index('tasks', [
        ('ttl_timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index('log_entries', [
        ('timestamp', pymongo.DESCENDING),
    ], background=True)
    upsert_index('messages', 'channel', background=True)
    upsert_index('administrators', 'username',
        background=True, unique=True)
    upsert_index('users', 'resource_id', background=True)
    upsert_index('users', [
        ('type', pymongo.ASCENDING),
        ('org_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index('users', [
        ('org_id', pymongo.ASCENDING),
        ('name', pymongo.ASCENDING),
    ], background=True)
    upsert_index('users_audit', [
        ('org_id', pymongo.ASCENDING),
        ('user_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index('users_audit', [
        ('timestamp', pymongo.DESCENDING),
    ], background=True)
    upsert_index('users_key_link', 'key_id',
        background=True)
    upsert_index('users_key_link', 'short_id',
        background=True, unique=True)
    upsert_index('users_net_link', 'user_id',
        background=True)
    upsert_index('users_net_link', 'org_id',
        background=True)
    upsert_index('users_net_link', 'network',
        background=True)
    upsert_index('clients', 'user_id', background=True)
    upsert_index('clients', 'domain', background=True)
    upsert_index('clients', 'virt_address_num',
        background=True)
    upsert_index('clients', [
        ('server_id', pymongo.ASCENDING),
        ('type', pymongo.ASCENDING),
    ], background=True)
    upsert_index('clients', [
        ('host_id', pymongo.ASCENDING),
        ('type', pymongo.ASCENDING),
    ], background=True)
    upsert_index('clients_pool',
        'client_id', background=True)
    upsert_index('clients_pool',
        'timestamp', background=True)
    upsert_index('clients_pool', [
        ('server_id', pymongo.ASCENDING),
        ('user_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index('organizations', 'type', background=True)
    upsert_index('organizations',
        'auth_token', background=True)
    upsert_index('hosts', 'name', background=True)
    upsert_index('hosts_usage', [
        ('host_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index('servers', 'name', background=True)
    upsert_index('servers', 'ping_timestamp',
        background=True)
    upsert_index('servers_output', [
        ('server_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index('servers_output_link', [
        ('server_id', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index('servers_bandwidth', [
        ('server_id', pymongo.ASCENDING),
        ('period', pymongo.ASCENDING),
        ('timestamp', pymongo.ASCENDING),
    ], background=True)
    upsert_index('servers_ip_pool', [
        ('server_id', pymongo.ASCENDING),
        ('user_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index('servers_ip_pool', [
        ('server_id', pymongo.ASCENDING),
        ('_id', pymongo.DESCENDING),
    ], background=True)
    upsert_index('servers_ip_pool', 'user_id',
        background=True)
    upsert_index('links_hosts', 'link_id',
        background=True)
    upsert_index('links_hosts', [
        ('location_id', pymongo.ASCENDING),
        ('status', pymongo.ASCENDING),
        ('active', pymongo.ASCENDING),
        ('priority', pymongo.DESCENDING),
    ], background=True)
    upsert_index('links_hosts', [
        ('location_id', pymongo.ASCENDING),
        ('name', pymongo.ASCENDING),
    ], background=True)
    upsert_index('links_hosts', 'ping_timestamp_ttl',
        background=True)
    upsert_index('links_locations', 'link_id',
        background=True)
    upsert_index('routes_reserve', 'timestamp',
        background=True)
    upsert_index('dh_params', 'dh_param_bits',
        background=True)
    upsert_index('auth_nonces', [
        ('token', pymongo.ASCENDING),
        ('nonce', pymongo.ASCENDING),
    ], background=True, unique=True)
    upsert_index('otp_cache', [
        ('user_id', pymongo.ASCENDING),
        ('server_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index('sso_push_cache', [
        ('user_id', pymongo.ASCENDING),
        ('server_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index('sso_client_cache', [
        ('user_id', pymongo.ASCENDING),
        ('server_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index('sso_passcode_cache', [
        ('user_id', pymongo.ASCENDING),
        ('server_id', pymongo.ASCENDING),
    ], background=True)
    upsert_index('vxlans', 'server_id',
        background=True, unique=True)

    upsert_index('tasks', 'timestamp',
        background=True, expireAfterSeconds=300)
    if settings.app.demo_mode:
        drop_index(mongo.collections['clients'], 'timestamp', background=True)
    else:
        upsert_index('clients', 'timestamp',
            background=True, expireAfterSeconds=settings.vpn.client_ttl)
    upsert_index('users_key_link', 'timestamp',
        background=True, expireAfterSeconds=settings.app.key_link_timeout)
    upsert_index('auth_sessions', 'timestamp',
        background=True, expireAfterSeconds=settings.app.session_timeout)
    upsert_index('auth_nonces', 'timestamp',
        background=True,
        expireAfterSeconds=settings.app.auth_time_window * 2.1)
    upsert_index('auth_csrf_tokens', 'timestamp',
        background=True, expireAfterSeconds=604800)
    upsert_index('auth_limiter', 'timestamp',
        background=True, expireAfterSeconds=settings.app.auth_limiter_ttl)
    upsert_index('otp', 'timestamp', background=True,
        expireAfterSeconds=120)
    upsert_index('otp_cache', 'timestamp',
        background=True, expireAfterSeconds=settings.vpn.otp_cache_timeout)
    upsert_index('yubikey', 'timestamp',
        background=True, expireAfterSeconds=86400)
    upsert_index('sso_tokens', 'timestamp',
        background=True, expireAfterSeconds=600)
    upsert_index('sso_push_cache', 'timestamp',
        background=True, expireAfterSeconds=settings.app.sso_cache_timeout)
    upsert_index('sso_client_cache', 'timestamp',
        background=True,
        expireAfterSeconds=settings.app.sso_client_cache_timeout +
            settings.app.sso_client_cache_window)
    upsert_index('sso_passcode_cache', 'timestamp',
        background=True, expireAfterSeconds=settings.app.sso_cache_timeout)

    try:
        clean_indexes()
    except:
        logger.exception('Failed to clean indexes', 'setup')

    if not auth.Administrator.collection.find_one():
        auth.Administrator(
            username=DEFAULT_USERNAME,
            password=DEFAULT_PASSWORD,
            default=True,
        ).commit()

    secret_key = settings.app.cookie_secret
    secret_key2 = settings.app.cookie_secret2
    settings_commit = False

    if not secret_key:
        settings_commit = True
        secret_key = utils.rand_str(64)
        settings.app.cookie_secret = secret_key

    if not secret_key2:
        settings_commit = True
        settings.app.cookie_secret2 = utils.rand_str(64)

    if settings_commit:
        settings.commit()

    app.app.secret_key = secret_key.encode()
Example #22
0
def setup_mongo():
    prefix = settings.conf.mongodb_collection_prefix or ''
    last_error = time.time() - 24

    while True:
        try:
            read_pref = _get_read_pref(settings.conf.mongodb_read_preference)

            if read_pref:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                    socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    read_preference=read_pref,
                )
            else:
                client = pymongo.MongoClient(
                    settings.conf.mongodb_uri,
                    connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                    socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                )

            break
        except pymongo.errors.ConnectionFailure:
            time.sleep(0.5)
            if time.time() - last_error > 30:
                last_error = time.time()
                logger.exception('Error connecting to mongodb server')

    database = client.get_default_database()

    settings_col = getattr(database, prefix + 'settings')
    app_settings = settings_col.find_one({'_id': 'app'})
    if app_settings:
        secondary_mongodb_uri = app_settings.get('secondary_mongodb_uri')
    else:
        secondary_mongodb_uri = None

    if secondary_mongodb_uri:
        while True:
            try:
                read_pref = _get_read_pref(
                    settings.conf.mongodb_read_preference)

                if read_pref:
                    secondary_client = pymongo.MongoClient(
                        secondary_mongodb_uri,
                        connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                        socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        read_preference=read_pref,
                    )
                else:
                    secondary_client = pymongo.MongoClient(
                        secondary_mongodb_uri,
                        connectTimeoutMS=MONGO_CONNECT_TIMEOUT,
                        socketTimeoutMS=MONGO_SOCKET_TIMEOUT,
                        serverSelectionTimeoutMS=MONGO_SOCKET_TIMEOUT,
                    )

                break
            except pymongo.errors.ConnectionFailure:
                time.sleep(0.5)
                if time.time() - last_error > 30:
                    last_error = time.time()
                    logger.exception(
                        'Error connecting to secondary mongodb server')

        secondary_database = secondary_client.get_default_database()
    else:
        secondary_database = database

    mongo.database = database
    mongo.secondary_database = secondary_database

    cur_collections = database.collection_names()
    cur_sec_collections = secondary_database.collection_names()
    if 'authorities' in cur_collections or \
            'authorities' in cur_sec_collections:
        raise TypeError('Cannot connect to a Pritunl Zero database')

    mongo.collection_types = {
        'transaction': 1,
        'queue': 1,
        'tasks': 1,
        'settings': 1,
        'messages': 2,
        'administrators': 1,
        'users': 1,
        'users_audit': 1,
        'users_key_link': 2,
        'users_net_link': 1,
        'clients': 1,
        'clients_pool': 1,
        'organizations': 1,
        'hosts': 1,
        'hosts_usage': 1,
        'servers': 1,
        'servers_output': 1,
        'servers_output_link': 1,
        'servers_bandwidth': 1,
        'servers_ip_pool': 1,
        'links': 1,
        'links_locations': 1,
        'links_hosts': 1,
        'routes_reserve': 1,
        'dh_params': 1,
        'acme_challenges': 1,
        'auth_sessions': 2,
        'auth_csrf_tokens': 2,
        'auth_nonces': 2,
        'auth_limiter': 2,
        'otp': 2,
        'otp_cache': 2,
        'yubikey': 2,
        'sso_tokens': 2,
        'sso_push_cache': 2,
        'sso_client_cache': 2,
        'sso_passcode_cache': 2,
        'vxlans': 1,
        'logs': 1,
        'log_entries': 1,
    }

    cur_collections = mongo.secondary_database.collection_names()
    if prefix + 'messages' not in cur_collections:
        mongo.secondary_database.create_collection(
            prefix + 'messages', capped=True,
            size=5000192, max=1000)
    elif not mongo.get_collection('messages').options().get('capped'):
        mongo.get_collection('messages').drop()
        mongo.secondary_database.create_collection(
            prefix + 'messages', capped=True,
            size=5000192, max=1000)

    settings.local.mongo_time = None

    while True:
        try:
            utils.sync_time()
            break
        except:
            logger.exception('Failed to sync time', 'setup')
            time.sleep(30)

    settings.init()

    upsert_indexes()

    if not auth.Administrator.collection.find_one():
        default_admin = auth.Administrator(
            username=DEFAULT_USERNAME,
        )
        default_admin.generate_default_password()
        default_admin.commit()

    secret_key = settings.app.cookie_secret
    secret_key2 = settings.app.cookie_secret2
    settings_commit = False

    if not secret_key:
        settings_commit = True
        secret_key = utils.rand_str(64)
        settings.app.cookie_secret = secret_key

    if not secret_key2:
        settings_commit = True
        settings.app.cookie_secret2 = utils.rand_str(64)

    if settings_commit:
        settings.commit()

    app.app.secret_key = secret_key.encode()
Example #23
0
def sso_request_get():
    sso_mode = settings.app.sso

    if sso_mode not in (
        GOOGLE_AUTH,
        GOOGLE_DUO_AUTH,
        SLACK_AUTH,
        SLACK_DUO_AUTH,
        SAML_AUTH,
        SAML_DUO_AUTH,
        SAML_OKTA_AUTH,
        SAML_OKTA_DUO_AUTH,
        SAML_ONELOGIN_AUTH,
        SAML_ONELOGIN_DUO_AUTH,
    ):
        return flask.abort(404)

    state = utils.rand_str(64)
    secret = utils.rand_str(64)
    callback = utils.get_url_root() + "/sso/callback"

    if not settings.local.sub_active:
        logger.error("Subscription must be active for sso", "sso")
        return flask.abort(405)

    if GOOGLE_AUTH in sso_mode:
        resp = requests.post(
            AUTH_SERVER + "/v1/request/google",
            headers={"Content-Type": "application/json"},
            json={"license": settings.app.license, "callback": callback, "state": state, "secret": secret},
        )

        if resp.status_code != 200:
            logger.error("Google auth server error", "sso", status_code=resp.status_code, content=resp.content)

            if resp.status_code == 401:
                return flask.abort(405)

            return flask.abort(500)

        tokens_collection = mongo.get_collection("sso_tokens")
        tokens_collection.insert({"_id": state, "type": GOOGLE_AUTH, "secret": secret, "timestamp": utils.now()})

        data = resp.json()

        return utils.redirect(data["url"])

    elif SLACK_AUTH in sso_mode:
        resp = requests.post(
            AUTH_SERVER + "/v1/request/slack",
            headers={"Content-Type": "application/json"},
            json={"license": settings.app.license, "callback": callback, "state": state, "secret": secret},
        )

        if resp.status_code != 200:
            logger.error("Slack auth server error", "sso", status_code=resp.status_code, content=resp.content)

            if resp.status_code == 401:
                return flask.abort(405)

            return flask.abort(500)

        tokens_collection = mongo.get_collection("sso_tokens")
        tokens_collection.insert({"_id": state, "type": SLACK_AUTH, "secret": secret, "timestamp": utils.now()})

        data = resp.json()

        return utils.redirect(data["url"])

    elif SAML_AUTH in sso_mode:
        resp = requests.post(
            AUTH_SERVER + "/v1/request/saml",
            headers={"Content-Type": "application/json"},
            json={
                "license": settings.app.license,
                "callback": callback,
                "state": state,
                "secret": secret,
                "sso_url": settings.app.sso_saml_url,
                "issuer_url": settings.app.sso_saml_issuer_url,
                "cert": settings.app.sso_saml_cert,
            },
        )

        if resp.status_code != 200:
            logger.error("Saml auth server error", "sso", status_code=resp.status_code, content=resp.content)

            if resp.status_code == 401:
                return flask.abort(405)

            return flask.abort(500)

        tokens_collection = mongo.get_collection("sso_tokens")
        tokens_collection.insert({"_id": state, "type": SAML_AUTH, "secret": secret, "timestamp": utils.now()})

        return flask.Response(status=200, response=resp.content, content_type="text/html;charset=utf-8")

    else:
        return flask.abort(404)
Example #24
0
def sso_request_get():
    sso_mode = settings.app.sso

    if sso_mode not in (GOOGLE_AUTH, GOOGLE_DUO_AUTH, SLACK_AUTH,
            SLACK_DUO_AUTH, SAML_AUTH, SAML_DUO_AUTH, SAML_OKTA_AUTH,
            SAML_OKTA_DUO_AUTH, SAML_ONELOGIN_AUTH, SAML_ONELOGIN_DUO_AUTH):
        return flask.abort(405)

    state = utils.rand_str(64)
    secret = utils.rand_str(64)
    callback = flask.request.url_root + 'sso/callback'

    if not settings.local.sub_active:
        logger.error('Subscription must be active for sso', 'sso')
        return flask.abort(405)

    if GOOGLE_AUTH in sso_mode:
        resp = requests.post(AUTH_SERVER + '/v1/request/google',
            headers={
                'Content-Type': 'application/json',
            },
            json={
                'license': settings.app.license,
                'callback': callback,
                'state': state,
                'secret': secret,
            }
        )

        if resp.status_code != 200:
            logger.error('Google auth server error', 'sso',
                status_code=resp.status_code,
                content=resp.content,
            )

            if resp.status_code == 401:
                return flask.abort(405)

            return flask.abort(500)

        tokens_collection = mongo.get_collection('sso_tokens')
        tokens_collection.insert({
            '_id': state,
            'type': GOOGLE_AUTH,
            'secret': secret,
            'timestamp': utils.now(),
        })

        data = resp.json()

        return flask.redirect(data['url'])

    elif SLACK_AUTH in sso_mode:
        resp = requests.post(AUTH_SERVER + '/v1/request/slack',
            headers={
                'Content-Type': 'application/json',
            },
            json={
                'license': settings.app.license,
                'callback': callback,
                'state': state,
                'secret': secret,
            }
        )

        if resp.status_code != 200:
            logger.error('Slack auth server error', 'sso',
                status_code=resp.status_code,
                content=resp.content,
            )

            if resp.status_code == 401:
                return flask.abort(405)

            return flask.abort(500)

        tokens_collection = mongo.get_collection('sso_tokens')
        tokens_collection.insert({
            '_id': state,
            'type': SLACK_AUTH,
            'secret': secret,
            'timestamp': utils.now(),
        })

        data = resp.json()

        return flask.redirect(data['url'])

    elif SAML_AUTH in sso_mode:
        resp = requests.post(AUTH_SERVER + '/v1/request/saml',
            headers={
                'Content-Type': 'application/json',
            },
            json={
                'license': settings.app.license,
                'callback': callback,
                'state': state,
                'secret': secret,
                'sso_url': settings.app.sso_saml_url,
                'issuer_url': settings.app.sso_saml_issuer_url,
                'cert': settings.app.sso_saml_cert,
            },
        )

        if resp.status_code != 200:
            logger.error('Saml auth server error', 'sso',
                status_code=resp.status_code,
                content=resp.content,
            )

            if resp.status_code == 401:
                return flask.abort(405)

            return flask.abort(500)

        tokens_collection = mongo.get_collection('sso_tokens')
        tokens_collection.insert({
            '_id': state,
            'type': SAML_AUTH,
            'secret': secret,
            'timestamp': utils.now(),
        })

        return flask.Response(
            status=200,
            response=resp.content,
            content_type="text/html;charset=utf-8",
        )
Example #25
0
def setup_mongo():
    prefix = settings.conf.mongodb_collection_prefix or ""
    last_error = time.time() - 24
    while True:
        try:
            client = pymongo.MongoClient(settings.conf.mongodb_uri, connectTimeoutMS=MONGO_CONNECT_TIMEOUT)
            break
        except pymongo.errors.ConnectionFailure:
            time.sleep(0.5)
            if time.time() - last_error > 30:
                last_error = time.time()
                logger.exception("Error connecting to mongodb server")

    database = client.get_default_database()
    cur_collections = database.collection_names()

    if prefix + "messages" not in cur_collections:
        database.create_collection(prefix + "messages", capped=True, size=100000, max=1024)

    mongo.collections.update(
        {
            "time_sync": getattr(database, prefix + "time_sync"),
            "transaction": getattr(database, prefix + "transaction"),
            "queue": getattr(database, prefix + "queue"),
            "task": getattr(database, prefix + "task"),
            "settings": getattr(database, prefix + "settings"),
            "messages": getattr(database, prefix + "messages"),
            "administrators": getattr(database, prefix + "administrators"),
            "users": getattr(database, prefix + "users"),
            "users_key_link": getattr(database, prefix + "users_key_link"),
            "clients": getattr(database, prefix + "clients"),
            "organizations": getattr(database, prefix + "organizations"),
            "hosts": getattr(database, prefix + "hosts"),
            "hosts_usage": getattr(database, prefix + "hosts_usage"),
            "servers": getattr(database, prefix + "servers"),
            "servers_output": getattr(database, prefix + "servers_output"),
            "servers_output_link": getattr(database, prefix + "servers_output_link"),
            "servers_bandwidth": getattr(database, prefix + "servers_bandwidth"),
            "servers_ip_pool": getattr(database, prefix + "servers_ip_pool"),
            "dh_params": getattr(database, prefix + "dh_params"),
            "auth_sessions": getattr(database, prefix + "auth_sessions"),
            "auth_nonces": getattr(database, prefix + "auth_nonces"),
            "auth_limiter": getattr(database, prefix + "auth_limiter"),
            "otp": getattr(database, prefix + "otp"),
            "otp_cache": getattr(database, prefix + "otp_cache"),
            "sso_tokens": getattr(database, prefix + "sso_tokens"),
        }
    )

    for collection_name, collection in mongo.collections.items():
        collection.name_str = collection_name

    utils.sync_time()

    settings.init()

    if prefix + "logs" not in cur_collections:
        log_limit = settings.app.log_limit
        database.create_collection(prefix + "logs", capped=True, size=log_limit * 1024, max=log_limit)

    if prefix + "log_entries" not in cur_collections:
        log_entry_limit = settings.app.log_entry_limit
        database.create_collection(prefix + "log_entries", capped=True, size=log_entry_limit * 512, max=log_entry_limit)

    mongo.collections.update(
        {"logs": getattr(database, prefix + "logs"), "log_entries": getattr(database, prefix + "log_entries")}
    )
    mongo.collections["logs"].name_str = "logs"
    mongo.collections["log_entries"].name_str = "log_entries"

    mongo.collections["logs"].ensure_index("timestamp", background=True)
    mongo.collections["transaction"].ensure_index("lock_id", background=True, unique=True)
    mongo.collections["transaction"].ensure_index(
        [("ttl_timestamp", pymongo.ASCENDING), ("state", pymongo.ASCENDING), ("priority", pymongo.DESCENDING)],
        background=True,
    )
    mongo.collections["queue"].ensure_index("runner_id", background=True)
    mongo.collections["queue"].ensure_index("ttl_timestamp", background=True)
    mongo.collections["task"].ensure_index("type", background=True, unique=True)
    mongo.collections["task"].ensure_index("ttl_timestamp", background=True)
    mongo.collections["log_entries"].ensure_index([("timestamp", pymongo.DESCENDING)], background=True)
    mongo.collections["messages"].ensure_index("channel", background=True)
    mongo.collections["administrators"].ensure_index("username", background=True, unique=True)
    mongo.collections["users"].ensure_index("resource_id", background=True)
    mongo.collections["users"].ensure_index(
        [("type", pymongo.ASCENDING), ("org_id", pymongo.ASCENDING)], background=True
    )
    mongo.collections["users"].ensure_index(
        [("org_id", pymongo.ASCENDING), ("name", pymongo.ASCENDING)], background=True
    )
    mongo.collections["users_key_link"].ensure_index("key_id", background=True)
    mongo.collections["users_key_link"].ensure_index("short_id", background=True, unique=True)
    mongo.collections["clients"].ensure_index("user_id", background=True)
    mongo.collections["clients"].ensure_index("domain", background=True)
    mongo.collections["clients"].ensure_index(
        [("server_id", pymongo.ASCENDING), ("type", pymongo.ASCENDING)], background=True
    )
    mongo.collections["organizations"].ensure_index("type", background=True)
    mongo.collections["hosts"].ensure_index("name", background=True)
    mongo.collections["hosts_usage"].ensure_index(
        [("host_id", pymongo.ASCENDING), ("timestamp", pymongo.ASCENDING)], background=True
    )
    mongo.collections["servers"].ensure_index("name", background=True)
    mongo.collections["servers"].ensure_index("ping_timestamp", background=True)
    mongo.collections["servers_output"].ensure_index(
        [("server_id", pymongo.ASCENDING), ("timestamp", pymongo.ASCENDING)], background=True
    )
    mongo.collections["servers_output_link"].ensure_index(
        [("server_id", pymongo.ASCENDING), ("timestamp", pymongo.ASCENDING)], background=True
    )
    mongo.collections["servers_bandwidth"].ensure_index(
        [("server_id", pymongo.ASCENDING), ("period", pymongo.ASCENDING), ("timestamp", pymongo.ASCENDING)],
        background=True,
    )
    mongo.collections["servers_ip_pool"].ensure_index(
        [("server_id", pymongo.ASCENDING), ("user_id", pymongo.ASCENDING)], background=True
    )
    mongo.collections["servers_ip_pool"].ensure_index("user_id", background=True)
    mongo.collections["dh_params"].ensure_index("dh_param_bits", background=True)
    mongo.collections["auth_nonces"].ensure_index(
        [("token", pymongo.ASCENDING), ("nonce", pymongo.ASCENDING)], background=True, unique=True
    )

    mongo.collections["clients"].ensure_index("timestamp", background=True, expireAfterSeconds=settings.vpn.client_ttl)
    mongo.collections["users_key_link"].ensure_index(
        "timestamp", background=True, expireAfterSeconds=settings.app.key_link_timeout
    )
    mongo.collections["auth_sessions"].ensure_index(
        "timestamp", background=True, expireAfterSeconds=settings.app.session_timeout
    )
    mongo.collections["auth_nonces"].ensure_index(
        "timestamp", background=True, expireAfterSeconds=settings.app.auth_time_window * 2.1
    )
    mongo.collections["auth_limiter"].ensure_index(
        "timestamp", background=True, expireAfterSeconds=settings.app.auth_limiter_ttl
    )
    mongo.collections["otp"].ensure_index("timestamp", background=True, expireAfterSeconds=120)
    mongo.collections["otp_cache"].ensure_index(
        "timestamp", background=True, expireAfterSeconds=settings.user.otp_cache_ttl
    )
    mongo.collections["sso_tokens"].ensure_index("timestamp", background=True, expireAfterSeconds=600)

    if not auth.Administrator.collection.find_one():
        auth.Administrator(username=DEFAULT_USERNAME, password=DEFAULT_PASSWORD, default=True).commit()

    secret_key = settings.app.cookie_secret
    if not secret_key:
        secret_key = utils.rand_str(64)
        settings.app.cookie_secret = secret_key
        settings.commit()
    app.app.secret_key = secret_key.encode()