Beispiel #1
0
def index_static_get():
    if not auth.check_session():
        return utils.redirect('login')

    if settings.local.dart_url:
        return utils.redirect('/s/')

    static_file = static.StaticFile(settings.conf.www_path,
        'index.html', cache=False)

    return static_file.get_response()
Beispiel #2
0
def index_static_get():
    if not auth.check_session():
        return utils.redirect('login')

    if settings.local.dart_url:
        return utils.redirect('/s/')

    static_file = static.StaticFile(settings.conf.www_path,
                                    'index.html',
                                    cache=False)

    return static_file.get_response()
Beispiel #3
0
def login_static_get():
    if auth.check_session():
        return utils.redirect('')
    static_file = static.StaticFile(settings.conf.www_path,
        'login.html', cache=False, gzip=False)

    bodyClass = ''

    if settings.local.sub_active:
        if settings.app.theme == 'dark':
            bodyClass += 'dark '

        if settings.local.sub_plan == 'enterprise':
            if not settings.app.sso:
                pass
            elif settings.app.sso in (SAML_AUTH, SAML_DUO_AUTH):
                bodyClass += 'sso-saml '
            elif SAML_OKTA_AUTH in settings.app.sso:
                bodyClass += 'sso-okta '
            elif SAML_ONELOGIN_AUTH in settings.app.sso:
                bodyClass += 'sso-onelogin '
            elif GOOGLE_AUTH in settings.app.sso:
                bodyClass += 'sso-google '
            elif SLACK_AUTH in settings.app.sso:
                bodyClass += 'sso-slack '
            elif settings.app.sso == DUO_AUTH:
                bodyClass += 'sso-duo '

    if settings.app.demo_mode:
        bodyClass += 'demo '

    static_file.data = static_file.data.replace(
        '<body>', '<body class="' + bodyClass + '">')

    return static_file.get_response()
Beispiel #4
0
def login_static_get():
    if auth.check_session(False):
        return utils.redirect('')

    static_file = static.StaticFile(settings.conf.www_path,
                                    'login.html',
                                    cache=False,
                                    gzip=False)

    body_class = ''

    if auth.has_default_password():
        body_class += 'default-pass '

    if settings.local.sub_active:
        if settings.app.theme == 'dark':
            body_class += 'dark '

        if settings.local.sub_plan and \
                'enterprise' in settings.local.sub_plan:
            if not settings.app.sso:
                pass
            elif settings.app.sso in (SAML_AUTH, SAML_DUO_AUTH):
                body_class += 'sso-saml '
            elif SAML_OKTA_AUTH in settings.app.sso:
                body_class += 'sso-okta '
            elif SAML_ONELOGIN_AUTH in settings.app.sso:
                body_class += 'sso-onelogin '
            elif SAML_JUMPCLOUD_AUTH in settings.app.sso:
                body_class += 'sso-jumpcloud '
            elif AZURE_AUTH in settings.app.sso:
                body_class += 'sso-azure '
            elif GOOGLE_AUTH in settings.app.sso:
                body_class += 'sso-google '
            elif AUTHZERO_AUTH in settings.app.sso:
                body_class += 'sso-authzero '
            elif SLACK_AUTH in settings.app.sso:
                body_class += 'sso-slack '
            elif settings.app.sso == DUO_AUTH:
                body_class += 'sso-duo '

            if settings.app.sso and DUO_AUTH in settings.app.sso and \
                    settings.app.sso != DUO_AUTH and \
                    settings.app.sso_duo_mode != 'passcode':
                body_class += 'sso-duo-auth '

    if settings.app.demo_mode:
        body_class += 'demo '

    static_file.data = static_file.data.replace(
        '<body>', '<body class="' + body_class + '">')

    return static_file.get_response()
Beispiel #5
0
def login_static_get():
    if auth.check_session(False):
        return utils.redirect('')

    static_file = static.StaticFile(settings.conf.www_path,
        'login.html', cache=False, gzip=False)

    body_class = ''

    if auth.has_default_password():
        body_class += 'default-pass '

    if settings.local.sub_active:
        if settings.app.theme == 'dark':
            body_class += 'dark '

        if settings.local.sub_plan and \
                'enterprise' in settings.local.sub_plan:
            if not settings.app.sso:
                pass
            elif settings.app.sso in (SAML_AUTH, SAML_DUO_AUTH):
                body_class += 'sso-saml '
            elif SAML_OKTA_AUTH in settings.app.sso:
                body_class += 'sso-okta '
            elif SAML_ONELOGIN_AUTH in settings.app.sso:
                body_class += 'sso-onelogin '
            elif AZURE_AUTH in settings.app.sso:
                body_class += 'sso-azure '
            elif GOOGLE_AUTH in settings.app.sso:
                body_class += 'sso-google '
            elif AUTHZERO_AUTH in settings.app.sso:
                body_class += 'sso-authzero '
            elif SLACK_AUTH in settings.app.sso:
                body_class += 'sso-slack '
            elif settings.app.sso == DUO_AUTH:
                body_class += 'sso-duo '

            if settings.app.sso and DUO_AUTH in settings.app.sso and \
                    settings.app.sso != DUO_AUTH and \
                    settings.app.sso_duo_mode != 'passcode':
                body_class += 'sso-duo-auth '

    if settings.app.demo_mode:
        body_class += 'demo '

    static_file.data = static_file.data.replace(
        '<body>', '<body class="' + body_class + '">')

    return static_file.get_response()
Beispiel #6
0
def login_static_get():
    if auth.check_session(False):
        return utils.redirect('')

    static_file = static.StaticFile(settings.conf.www_path,
                                    'login.html',
                                    cache=False,
                                    gzip=False)

    bodyClass = ''

    if settings.local.sub_active:
        if settings.app.theme == 'dark':
            bodyClass += 'dark '

        if settings.local.sub_plan == 'enterprise':
            if not settings.app.sso:
                pass
            elif settings.app.sso in (SAML_AUTH, SAML_DUO_AUTH):
                bodyClass += 'sso-saml '
            elif SAML_OKTA_AUTH in settings.app.sso:
                bodyClass += 'sso-okta '
            elif SAML_ONELOGIN_AUTH in settings.app.sso:
                bodyClass += 'sso-onelogin '
            elif GOOGLE_AUTH in settings.app.sso:
                bodyClass += 'sso-google '
            elif SLACK_AUTH in settings.app.sso:
                bodyClass += 'sso-slack '
            elif settings.app.sso == DUO_AUTH:
                bodyClass += 'sso-duo '

            if settings.app.sso and DUO_AUTH in settings.app.sso:
                bodyClass += 'sso-duo-auth '

    if settings.app.demo_mode:
        bodyClass += 'demo '

    static_file.data = static_file.data.replace(
        '<body>', '<body class="' + bodyClass + '">')

    return static_file.get_response()
Beispiel #7
0
def sso_callback_get():
    sso_mode = settings.app.sso

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

    state = flask.request.args.get('state')
    sig = flask.request.args.get('sig')

    tokens_collection = mongo.get_collection('sso_tokens')
    doc = tokens_collection.find_and_modify(query={
        '_id': state,
    },
                                            remove=True)

    if not doc:
        return flask.abort(404)

    query = flask.request.query_string.split('&sig=')[0]
    test_sig = base64.urlsafe_b64encode(
        hmac.new(str(doc['secret']), query, hashlib.sha512).digest())

    if sig != test_sig:
        return flask.abort(401)

    params = urlparse.parse_qs(query)

    if doc.get('type') == SAML_AUTH:
        username = params.get('username')[0]
        email = params.get('email', [None])[0]
        org_name = params.get('org', [None])[0]

        if not username:
            return flask.abort(406)

        valid, org_name = sso.verify_saml(username, email, org_name)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org
        if org_name:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id

        valid, org_id_new, groups = sso.plugin_sso_authenticate(
            sso_type='saml',
            user_name=username,
            user_email=email,
            remote_ip=utils.get_remote_addr(),
            sso_org_names=[org_name],
        )
        if valid:
            org_id = org_id_new or org_id
        else:
            logger.error(
                'Saml plugin authentication not valid',
                'sso',
                username=username,
            )
            return flask.abort(401)
    elif doc.get('type') == SLACK_AUTH:
        username = params.get('username')[0]
        email = None
        user_team = params.get('team')[0]
        org_names = params.get('orgs', [''])[0]
        org_names = org_names.split(',')

        valid, org_name = sso.verify_slack(username, user_team, org_names)
        if not valid:
            return flask.abort(401)

        if org_name:
            org_names = [org_name]

        org_id = settings.app.sso_org
        for org_name in org_names:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id
                break

        valid, org_id_new, groups = sso.plugin_sso_authenticate(
            sso_type='slack',
            user_name=username,
            user_email=email,
            remote_ip=utils.get_remote_addr(),
            sso_org_names=org_names,
        )
        if valid:
            org_id = org_id_new or org_id
        else:
            logger.error(
                'Slack plugin authentication not valid',
                'sso',
                username=username,
            )
            return flask.abort(401)
    else:
        username = params.get('username')[0]
        email = username

        valid, org_name = sso.verify_google(username)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org
        if org_name:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id

        valid, org_id_new, groups = sso.plugin_sso_authenticate(
            sso_type='google',
            user_name=username,
            user_email=email,
            remote_ip=utils.get_remote_addr(),
        )
        if valid:
            org_id = org_id_new or org_id
        else:
            logger.error(
                'Google plugin authentication not valid',
                'sso',
                username=username,
            )
            return flask.abort(401)

    if DUO_AUTH in sso_mode:
        if settings.app.sso_duo_mode == 'passcode':
            token = utils.generate_secret()

            tokens_collection = mongo.get_collection('sso_tokens')
            tokens_collection.insert({
                '_id': token,
                'type': DUO_AUTH,
                'username': username,
                'email': email,
                'org_id': org_id,
                'groups': groups,
                'timestamp': utils.now(),
            })

            duo_page = static.StaticFile(settings.conf.www_path,
                                         'duo.html',
                                         cache=False,
                                         gzip=False)

            if settings.app.theme == 'dark':
                duo_page.data = duo_page.data.replace('<body>',
                                                      '<body class="dark">')
            duo_page.data = duo_page.data.replace('<%= token %>', token)

            return duo_page.get_response()
        else:
            duo_auth = sso.Duo(
                username=username,
                factor=settings.app.sso_duo_mode,
                remote_ip=utils.get_remote_addr(),
                auth_type='Key',
            )
            valid = duo_auth.authenticate()
            if valid:
                valid, org_id_new, groups2 = sso.plugin_sso_authenticate(
                    sso_type='duo',
                    user_name=username,
                    user_email=email,
                    remote_ip=utils.get_remote_addr(),
                )
                if valid:
                    org_id = org_id_new or org_id
                else:
                    logger.error(
                        'Duo plugin authentication not valid',
                        'sso',
                        username=username,
                    )
                    return flask.abort(401)

                groups = ((groups or set()) | (groups2 or set())) or None
            else:
                logger.error(
                    'Duo authentication not valid',
                    'sso',
                    username=username,
                )
                return flask.abort(401)

    if YUBICO_AUTH in sso_mode:
        token = utils.generate_secret()

        tokens_collection = mongo.get_collection('sso_tokens')
        tokens_collection.insert({
            '_id': token,
            'type': YUBICO_AUTH,
            'username': username,
            'email': email,
            'org_id': org_id,
            'groups': groups,
            'timestamp': utils.now(),
        })

        yubico_page = static.StaticFile(settings.conf.www_path,
                                        'yubico.html',
                                        cache=False,
                                        gzip=False)

        if settings.app.theme == 'dark':
            yubico_page.data = yubico_page.data.replace(
                '<body>', '<body class="dark">')
        yubico_page.data = yubico_page.data.replace('<%= token %>', token)

        return yubico_page.get_response()

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(405)

    usr = org.find_user(name=username)
    if not usr:
        usr = org.new_user(name=username,
                           email=email,
                           type=CERT_CLIENT,
                           auth_type=sso_mode,
                           groups=list(groups) if groups else None)
        usr.audit_event('user_created',
                        'User created with single sign-on',
                        remote_addr=utils.get_remote_addr())

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if usr.disabled:
            return flask.abort(403)

        if groups and groups - set(usr.groups or []):
            usr.groups = list(set(usr.groups or []) | groups)
            usr.commit('groups')

        if usr.auth_type != sso_mode:
            usr.auth_type = sso_mode
            usr.commit('auth_type')

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event(
        'user_profile',
        'User profile viewed from single sign-on',
        remote_addr=utils.get_remote_addr(),
    )

    return utils.redirect(utils.get_url_root() + key_link['view_url'])
Beispiel #8
0
def sso_callback_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 = flask.request.args.get("state")
    sig = flask.request.args.get("sig")

    tokens_collection = mongo.get_collection("sso_tokens")
    doc = tokens_collection.find_and_modify(query={"_id": state}, remove=True)

    if not doc:
        return flask.abort(404)

    query = flask.request.query_string.split("&sig=")[0]
    test_sig = base64.urlsafe_b64encode(hmac.new(str(doc["secret"]), query, hashlib.sha512).digest())

    if sig != test_sig:
        return flask.abort(401)

    params = urlparse.parse_qs(query)

    if doc.get("type") == SAML_AUTH:
        username = params.get("username")[0]
        email = params.get("email", [None])[0]
        org_name = params.get("org", [None])[0]

        if not username:
            return flask.abort(406)

        valid, org_name = sso.verify_saml(username, email, org_name)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org
        if org_name:
            org = organization.get_by_name(org_name, fields=("_id"))
            if org:
                org_id = org.id

        valid, org_id_new, groups = sso.plugin_sso_authenticate(
            sso_type="saml",
            user_name=username,
            user_email=email,
            remote_ip=utils.get_remote_addr(),
            sso_org_names=[org_name],
        )
        if valid:
            org_id = org_id_new or org_id
        else:
            logger.error("Saml plugin authentication not valid", "sso", username=username)
            return flask.abort(401)
    elif doc.get("type") == SLACK_AUTH:
        username = params.get("username")[0]
        email = None
        user_team = params.get("team")[0]
        org_names = params.get("orgs", [""])[0]
        org_names = org_names.split(",")

        valid, org_name = sso.verify_slack(username, user_team, org_names)
        if not valid:
            return flask.abort(401)

        if org_name:
            org_names = [org_name]

        org_id = settings.app.sso_org
        for org_name in org_names:
            org = organization.get_by_name(org_name, fields=("_id"))
            if org:
                org_id = org.id
                break

        valid, org_id_new, groups = sso.plugin_sso_authenticate(
            sso_type="slack",
            user_name=username,
            user_email=email,
            remote_ip=utils.get_remote_addr(),
            sso_org_names=org_names,
        )
        if valid:
            org_id = org_id_new or org_id
        else:
            logger.error("Slack plugin authentication not valid", "sso", username=username)
            return flask.abort(401)
    else:
        username = params.get("username")[0]
        email = username

        valid, org_name = sso.verify_google(username)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org
        if org_name:
            org = organization.get_by_name(org_name, fields=("_id"))
            if org:
                org_id = org.id

        valid, org_id_new, groups = sso.plugin_sso_authenticate(
            sso_type="google", user_name=username, user_email=email, remote_ip=utils.get_remote_addr()
        )
        if valid:
            org_id = org_id_new or org_id
        else:
            logger.error("Google plugin authentication not valid", "sso", username=username)
            return flask.abort(401)

    if DUO_AUTH in sso_mode:
        if settings.app.sso_duo_mode == "passcode":
            token = utils.generate_secret()

            tokens_collection = mongo.get_collection("sso_tokens")
            tokens_collection.insert(
                {
                    "_id": token,
                    "type": DUO_AUTH,
                    "username": username,
                    "email": email,
                    "org_id": org_id,
                    "groups": groups,
                    "timestamp": utils.now(),
                }
            )

            duo_page = static.StaticFile(settings.conf.www_path, "duo.html", cache=False, gzip=False)

            if settings.app.theme == "dark":
                duo_page.data = duo_page.data.replace("<body>", '<body class="dark">')
            duo_page.data = duo_page.data.replace("<%= token %>", token)

            return duo_page.get_response()
        else:
            duo_auth = sso.Duo(
                username=username, factor=settings.app.sso_duo_mode, remote_ip=utils.get_remote_addr(), auth_type="Key"
            )
            valid = duo_auth.authenticate()
            if valid:
                valid, org_id_new, groups2 = sso.plugin_sso_authenticate(
                    sso_type="duo", user_name=username, user_email=email, remote_ip=utils.get_remote_addr()
                )
                if valid:
                    org_id = org_id_new or org_id
                else:
                    logger.error("Duo plugin authentication not valid", "sso", username=username)
                    return flask.abort(401)

                groups = ((groups or set()) | (groups2 or set())) or None
            else:
                logger.error("Duo authentication not valid", "sso", username=username)
                return flask.abort(401)

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(405)

    usr = org.find_user(name=username)
    if not usr:
        usr = org.new_user(
            name=username, email=email, type=CERT_CLIENT, auth_type=sso_mode, groups=list(groups) if groups else None
        )
        usr.audit_event("user_created", "User created with single sign-on", remote_addr=utils.get_remote_addr())

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if usr.disabled:
            return flask.abort(403)

        if groups and groups - set(usr.groups or []):
            usr.groups = list(set(usr.groups or []) | groups)
            usr.commit("groups")

        if usr.auth_type != sso_mode:
            usr.auth_type = sso_mode
            usr.commit("auth_type")

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event("user_profile", "User profile viewed from single sign-on", remote_addr=utils.get_remote_addr())

    return utils.redirect(utils.get_url_root() + key_link["view_url"])
Beispiel #9
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)
Beispiel #10
0
def upgrade_get():
    return utils.redirect('')
Beispiel #11
0
def setup_get():
    return utils.redirect('')
Beispiel #12
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",
        )
Beispiel #13
0
def upgrade_get():
    return utils.redirect('')
Beispiel #14
0
def setup_get():
    return utils.redirect('')
Beispiel #15
0
def sso_callback_get():
    sso_mode = settings.app.sso

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

    state = flask.request.args.get('state')
    sig = flask.request.args.get('sig')

    tokens_collection = mongo.get_collection('sso_tokens')
    doc = tokens_collection.find_and_modify(query={
        '_id': state,
    }, remove=True)

    if not doc:
        return flask.abort(404)

    query = flask.request.query_string.split('&sig=')[0]
    test_sig = base64.urlsafe_b64encode(hmac.new(str(doc['secret']),
        query, hashlib.sha512).digest())
    if not utils.const_compare(sig, test_sig):
        return flask.abort(401)

    params = urlparse.parse_qs(query)

    if doc.get('type') == SAML_AUTH:
        username = params.get('username')[0]
        email = params.get('email', [None])[0]
        org_name = params.get('org', [None])[0]

        if not username:
            return flask.abort(406)

        org_id = settings.app.sso_org
        if org_name:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id

        valid, org_id_new, groups = sso.plugin_sso_authenticate(
            sso_type='saml',
            user_name=username,
            user_email=email,
            remote_ip=utils.get_remote_addr(),
            sso_org_names=[org_name],
        )
        if valid:
            org_id = org_id_new or org_id
        else:
            logger.error('Saml plugin authentication not valid', 'sso',
                username=username,
            )
            return flask.abort(401)
    elif doc.get('type') == SLACK_AUTH:
        username = params.get('username')[0]
        email = None
        user_team = params.get('team')[0]
        org_names = params.get('orgs', [''])[0]
        org_names = org_names.split(',')

        valid = sso.verify_slack(username, user_team)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org
        for org_name in org_names:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id
                break

        valid, org_id_new, groups = sso.plugin_sso_authenticate(
            sso_type='slack',
            user_name=username,
            user_email=email,
            remote_ip=utils.get_remote_addr(),
            sso_org_names=org_names,
        )
        if valid:
            org_id = org_id_new or org_id
        else:
            logger.error('Slack plugin authentication not valid', 'sso',
                username=username,
            )
            return flask.abort(401)
    else:
        username = params.get('username')[0]
        email = username

        valid = sso.verify_google(username)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org

        valid, org_id_new, groups = sso.plugin_sso_authenticate(
            sso_type='google',
            user_name=username,
            user_email=email,
            remote_ip=utils.get_remote_addr(),
        )
        if valid:
            org_id = org_id_new or org_id
        else:
            logger.error('Google plugin authentication not valid', 'sso',
                username=username,
            )
            return flask.abort(401)

    if DUO_AUTH in sso_mode:
        token = utils.generate_secret()

        tokens_collection = mongo.get_collection('sso_tokens')
        tokens_collection.insert({
            '_id': token,
            'type': DUO_AUTH,
            'username': username,
            'email': email,
            'org_id': org_id,
            'groups': groups,
            'timestamp': utils.now(),
        })

        duo_page = static.StaticFile(settings.conf.www_path,
            'duo.html', cache=False, gzip=False)

        sso_duo_mode = settings.app.sso_duo_mode
        if sso_duo_mode == 'passcode':
            duo_mode = 'passcode'
        elif sso_duo_mode == 'phone':
            duo_mode = 'phone'
        else:
            duo_mode = 'push'

        body_class = duo_mode
        if settings.app.theme == 'dark':
            body_class += ' dark'

        duo_page.data = duo_page.data.replace('<%= body_class %>', body_class)
        duo_page.data = duo_page.data.replace('<%= token %>', token)
        duo_page.data = duo_page.data.replace('<%= duo_mode %>', duo_mode)

        return duo_page.get_response()

    if YUBICO_AUTH in sso_mode:
        token = utils.generate_secret()

        tokens_collection = mongo.get_collection('sso_tokens')
        tokens_collection.insert({
            '_id': token,
            'type': YUBICO_AUTH,
            'username': username,
            'email': email,
            'org_id': org_id,
            'groups': groups,
            'timestamp': utils.now(),
        })

        yubico_page = static.StaticFile(settings.conf.www_path,
            'yubico.html', cache=False, gzip=False)

        if settings.app.theme == 'dark':
            yubico_page.data = yubico_page.data.replace(
                '<body>', '<body class="dark">')
        yubico_page.data = yubico_page.data.replace('<%= token %>', token)

        return yubico_page.get_response()

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(405)

    usr = org.find_user(name=username)
    if not usr:
        usr = org.new_user(name=username, email=email, type=CERT_CLIENT,
            auth_type=sso_mode, groups=list(groups) if groups else None)
        usr.audit_event('user_created', 'User created with single sign-on',
            remote_addr=utils.get_remote_addr())

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if usr.disabled:
            return flask.abort(403)

        if groups and groups - set(usr.groups or []):
            usr.groups = list(set(usr.groups or []) | groups)
            usr.commit('groups')

        if usr.auth_type != sso_mode:
            usr.auth_type = sso_mode
            usr.commit('auth_type')

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event('user_profile',
        'User profile viewed from single sign-on',
        remote_addr=utils.get_remote_addr(),
    )

    return utils.redirect(utils.get_url_root() + key_link['view_url'])
Beispiel #16
0
def _validate_user(username,
                   email,
                   sso_mode,
                   org_id,
                   groups,
                   http_redirect=False,
                   yubico_id=None):
    usr = user.find_user_auth(name=username, auth_type=sso_mode)
    if not usr:
        org = organization.get_by_id(org_id)
        if not org:
            logger.error(
                'Organization for sso does not exist',
                'sso',
                org_id=org_id,
            )
            return flask.abort(405)

        usr = org.find_user(name=username)
    else:
        if usr.org_id != org_id:
            logger.info(
                'User organization changed, moving user',
                'sso',
                user_name=username,
                user_email=email,
                remote_ip=utils.get_remote_addr(),
                cur_org_id=usr.org_id,
                new_org_id=org_id,
            )

            org = organization.get_by_id(org_id)
            if not org:
                logger.error(
                    'Organization for sso does not exist',
                    'sso',
                    org_id=org_id,
                )
                return flask.abort(405)

            usr.remove()
            old_org_id = usr.org_id

            usr = org.new_user(
                name=usr.name,
                email=usr.email,
                type=usr.type,
                groups=usr.groups,
                auth_type=usr.auth_type,
                yubico_id=usr.yubico_id,
                disabled=usr.disabled,
                bypass_secondary=usr.bypass_secondary,
                client_to_client=usr.client_to_client,
                dns_servers=usr.dns_servers,
                dns_suffix=usr.dns_suffix,
                port_forwarding=usr.port_forwarding,
            )

            event.Event(type=ORGS_UPDATED)
            event.Event(type=USERS_UPDATED, resource_id=old_org_id)
            event.Event(type=USERS_UPDATED, resource_id=org.id)
            event.Event(type=SERVERS_UPDATED)

        org = usr.org

    if not usr:
        usr = org.new_user(name=username,
                           email=email,
                           type=CERT_CLIENT,
                           auth_type=sso_mode,
                           yubico_id=yubico_id,
                           groups=list(groups) if groups else None)
        usr.audit_event('user_created',
                        'User created with single sign-on',
                        remote_addr=utils.get_remote_addr())

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if yubico_id and usr.yubico_id and yubico_id != usr.yubico_id:
            return utils.jsonify(
                {
                    'error': YUBIKEY_INVALID,
                    'error_msg': YUBIKEY_INVALID_MSG,
                }, 401)

        if usr.disabled:
            return flask.abort(403)

        changed = False

        if yubico_id and not usr.yubico_id:
            changed = True
            usr.yubico_id = yubico_id
            usr.commit('yubico_id')

        if groups and groups - set(usr.groups or []):
            changed = True
            usr.groups = list(set(usr.groups or []) | groups)
            usr.commit('groups')

        if usr.auth_type != sso_mode:
            changed = True
            usr.auth_type = sso_mode
            usr.commit('auth_type')

        if changed:
            event.Event(type=USERS_UPDATED, resource_id=org.id)

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event(
        'user_profile',
        'User profile viewed from single sign-on',
        remote_addr=utils.get_remote_addr(),
    )

    if http_redirect:
        return utils.redirect(utils.get_url_root() + key_link['view_url'])
    else:
        return utils.jsonify(
            {
                'redirect': utils.get_url_root() + key_link['view_url'],
            }, 200)
Beispiel #17
0
def _validate_user(username, email, sso_mode, org_id, groups, remote_addr,
        http_redirect=False, yubico_id=None):
    usr = user.find_user_auth(name=username, auth_type=sso_mode)
    if not usr:
        org = organization.get_by_id(org_id)
        if not org:
            logger.error('Organization for sso does not exist', 'sso',
                org_id=org_id,
            )
            return flask.abort(405)

        usr = org.find_user(name=username)
    else:
        if usr.org_id != org_id:
            logger.info('User organization changed, moving user', 'sso',
                user_name=username,
                user_email=email,
                remote_ip=remote_addr,
                cur_org_id=usr.org_id,
                new_org_id=org_id,
            )

            org = organization.get_by_id(org_id)
            if not org:
                logger.error('Organization for sso does not exist', 'sso',
                    org_id=org_id,
                )
                return flask.abort(405)

            usr.remove()
            old_org_id = usr.org_id

            usr = org.new_user(
                name=usr.name,
                email=usr.email,
                type=usr.type,
                groups=usr.groups,
                auth_type=usr.auth_type,
                yubico_id=usr.yubico_id,
                disabled=usr.disabled,
                bypass_secondary=usr.bypass_secondary,
                client_to_client=usr.client_to_client,
                dns_servers=usr.dns_servers,
                dns_suffix=usr.dns_suffix,
                port_forwarding=usr.port_forwarding,
            )

            event.Event(type=ORGS_UPDATED)
            event.Event(type=USERS_UPDATED, resource_id=old_org_id)
            event.Event(type=USERS_UPDATED, resource_id=org.id)
            event.Event(type=SERVERS_UPDATED)

        org = usr.org

    if not usr:
        usr = org.new_user(name=username, email=email, type=CERT_CLIENT,
            auth_type=sso_mode, yubico_id=yubico_id,
            groups=list(groups) if groups else None)
        usr.audit_event('user_created', 'User created with single sign-on',
            remote_addr=remote_addr)

        journal.entry(
            journal.USER_CREATE,
            usr.journal_data,
            event_long='User created with single sign-on',
            remote_address=remote_addr,
        )

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if yubico_id and usr.yubico_id and yubico_id != usr.yubico_id:
            journal.entry(
                journal.SSO_AUTH_FAILURE,
                user_name=username,
                remote_address=remote_addr,
                reason=journal.SSO_AUTH_REASON_INVALID_YUBIKEY,
                reason_long='Invalid username',
            )

            return utils.jsonify({
                'error': YUBIKEY_INVALID,
                'error_msg': YUBIKEY_INVALID_MSG,
            }, 401)

        if usr.disabled:
            return flask.abort(403)

        changed = False

        if yubico_id and not usr.yubico_id:
            changed = True
            usr.yubico_id = yubico_id
            usr.commit('yubico_id')

        if groups and groups - set(usr.groups or []):
            changed = True
            usr.groups = list(set(usr.groups or []) | groups)
            usr.commit('groups')

        if usr.auth_type != sso_mode:
            changed = True
            usr.auth_type = sso_mode
            usr.commit('auth_type')

        if changed:
            event.Event(type=USERS_UPDATED, resource_id=org.id)

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event('user_profile',
        'User profile viewed from single sign-on',
        remote_addr=remote_addr,
    )

    journal.entry(
        journal.SSO_AUTH_SUCCESS,
        usr.journal_data,
        key_id_hash=hashlib.md5(key_link['id']).hexdigest(),
        remote_address=remote_addr,
    )

    journal.entry(
        journal.USER_PROFILE_SUCCESS,
        usr.journal_data,
        remote_address=remote_addr,
        event_long='User profile viewed from single sign-on',
    )

    if http_redirect:
        return utils.redirect(utils.get_url_root() + key_link['view_url'])
    else:
        return utils.jsonify({
            'redirect': utils.get_url_root() + key_link['view_url'],
        }, 200)
Beispiel #18
0
def sso_callback_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 = flask.request.args.get('state')
    sig = flask.request.args.get('sig')

    tokens_collection = mongo.get_collection('sso_tokens')
    doc = tokens_collection.find_and_modify(query={
        '_id': state,
    }, remove=True)

    if not doc:
        return flask.abort(404)

    query = flask.request.query_string.split('&sig=')[0]
    test_sig = base64.urlsafe_b64encode(hmac.new(str(doc['secret']),
        query, hashlib.sha512).digest())

    if sig != test_sig:
        return flask.abort(401)

    params = urlparse.parse_qs(query)

    if doc.get('type') == SAML_AUTH:
        username = params.get('username')[0]
        email = params.get('email', [None])[0]
        org_name = params.get('org', [None])[0]

        if not username:
            return flask.abort(406)

        valid, org_name = sso.verify_saml(username, email, org_name)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org
        if org_name:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id
    elif doc.get('type') == SLACK_AUTH:
        username = params.get('username')[0]
        email = None
        user_team = params.get('team')[0]
        org_names = params.get('orgs', [''])[0]
        org_names = org_names.split(',')

        valid, org_name = sso.verify_slack(username, user_team, org_names)
        if not valid:
            return flask.abort(401)

        if org_name:
            org_names = [org_name]

        org_id = settings.app.sso_org
        for org_name in org_names:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id
                break
    else:
        username = params.get('username')[0]
        email = username

        valid, org_name = sso.verify_google(username)
        if not valid:
            return flask.abort(401)

        org_id = settings.app.sso_org
        if org_name:
            org = organization.get_by_name(org_name, fields=('_id'))
            if org:
                org_id = org.id
    if DUO_AUTH in sso_mode:
        valid, _ = sso.auth_duo(
            username,
            ipaddr=flask.request.remote_addr,
            type='Key',
        )
        if not valid:
            return flask.abort(401)

    org = organization.get_by_id(org_id)
    if not org:
        return flask.abort(405)

    usr = org.find_user(name=username)
    if not usr:
        usr = org.new_user(name=username, email=email, type=CERT_CLIENT,
            auth_type=sso_mode)
        usr.audit_event('user_created', 'User created with single sign-on',
            remote_addr=utils.get_remote_addr())

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if usr.disabled:
            return flask.abort(403)

        if usr.auth_type != sso_mode:
            usr.auth_type = sso_mode
            usr.commit('auth_type')

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event('user_profile',
        'User profile viewed from single sign-on',
        remote_addr=utils.get_remote_addr(),
    )

    return utils.redirect(utils.get_url_root()[:-1] + key_link['view_url'])
Beispiel #19
0
def _validate_user(username,
                   email,
                   sso_mode,
                   org_id,
                   groups,
                   remote_addr,
                   http_redirect=False,
                   yubico_id=None):
    usr = user.find_user_auth(name=username, auth_type=sso_mode)
    if not usr:
        org = organization.get_by_id(org_id)
        if not org:
            logger.error(
                'Organization for sso does not exist',
                'sso',
                org_id=org_id,
            )
            return flask.abort(405)

        usr = org.find_user(name=username)
    else:
        if usr.org_id != org_id:
            logger.info(
                'User organization changed, moving user',
                'sso',
                user_name=username,
                user_email=email,
                remote_ip=remote_addr,
                cur_org_id=usr.org_id,
                new_org_id=org_id,
            )

            org = organization.get_by_id(org_id)
            if not org:
                logger.error(
                    'Organization for sso does not exist',
                    'sso',
                    org_id=org_id,
                )
                return flask.abort(405)

            usr.remove()
            old_org_id = usr.org_id

            new_usr = org.new_user(
                name=usr.name,
                email=usr.email,
                pin=usr.pin,
                type=usr.type,
                groups=usr.groups,
                auth_type=usr.auth_type,
                yubico_id=usr.yubico_id,
                disabled=usr.disabled,
                resource_id=usr.resource_id,
                bypass_secondary=usr.bypass_secondary,
                client_to_client=usr.client_to_client,
                mac_addresses=usr.mac_addresses,
                dns_servers=usr.dns_servers,
                dns_suffix=usr.dns_suffix,
                port_forwarding=usr.port_forwarding,
            )
            new_usr.otp_secret = usr.otp_secret

            usr = new_usr
            usr.commit()

            event.Event(type=ORGS_UPDATED)
            event.Event(type=USERS_UPDATED, resource_id=old_org_id)
            event.Event(type=USERS_UPDATED, resource_id=org.id)
            event.Event(type=SERVERS_UPDATED)

        org = usr.org

    if not usr:
        usr = org.new_user(name=username,
                           email=email,
                           type=CERT_CLIENT,
                           auth_type=sso_mode,
                           yubico_id=yubico_id,
                           groups=list(groups) if groups else None)
        usr.audit_event('user_created',
                        'User created with single sign-on',
                        remote_addr=remote_addr)

        journal.entry(
            journal.USER_CREATE,
            usr.journal_data,
            event_long='User created with single sign-on',
            remote_address=remote_addr,
        )

        event.Event(type=ORGS_UPDATED)
        event.Event(type=USERS_UPDATED, resource_id=org.id)
        event.Event(type=SERVERS_UPDATED)
    else:
        if yubico_id and usr.yubico_id and yubico_id != usr.yubico_id:
            journal.entry(
                journal.SSO_AUTH_FAILURE,
                user_name=username,
                remote_address=remote_addr,
                reason=journal.SSO_AUTH_REASON_INVALID_YUBIKEY,
                reason_long='Invalid username',
            )

            return utils.jsonify(
                {
                    'error': YUBIKEY_INVALID,
                    'error_msg': YUBIKEY_INVALID_MSG,
                }, 401)

        if usr.disabled:
            return flask.abort(403)

        changed = False

        if yubico_id and not usr.yubico_id:
            changed = True
            usr.yubico_id = yubico_id
            usr.commit('yubico_id')

        if groups and groups - set(usr.groups or []):
            changed = True
            usr.groups = list(set(usr.groups or []) | groups)
            usr.commit('groups')

        if usr.auth_type != sso_mode:
            changed = True
            usr.auth_type = sso_mode
            usr.commit('auth_type')

        usr.clear_auth_cache()
        usr.disconnect()

        if changed:
            event.Event(type=USERS_UPDATED, resource_id=org.id)

    key_link = org.create_user_key_link(usr.id, one_time=True)

    usr.audit_event(
        'user_profile',
        'User profile viewed from single sign-on',
        remote_addr=remote_addr,
    )

    journal.entry(
        journal.SSO_AUTH_SUCCESS,
        usr.journal_data,
        key_id_hash=hashlib.md5(key_link['id'].encode()).hexdigest(),
        remote_address=remote_addr,
    )

    journal.entry(
        journal.USER_PROFILE_SUCCESS,
        usr.journal_data,
        remote_address=remote_addr,
        event_long='User profile viewed from single sign-on',
    )

    if http_redirect:
        return utils.redirect(utils.get_url_root() + key_link['view_url'])
    else:
        return utils.jsonify(
            {
                'redirect': utils.get_url_root() + key_link['view_url'],
            }, 200)