Пример #1
0
 def test_create_and_check_for_user(self):
     """ ACCOUNT (CORE): Test the creation, query, and deletion of an account """
     usr = account_name_generator()
     invalid_usr = account_name_generator()
     add_account(usr, 'USER', 'root')
     assert_equal(account_exists(usr), True)
     assert_equal(account_exists(invalid_usr), False)
     del_account(usr, 'root')
Пример #2
0
 def test_create_and_check_for_user(self):
     """ ACCOUNT (CORE): Test the creation, query, and deletion of an account """
     usr = account_name_generator()
     invalid_usr = account_name_generator()
     add_account(usr, 'USER', '*****@*****.**', 'root')
     assert_equal(account_exists(usr), True)
     assert_equal(account_exists(invalid_usr), False)
     del_account(usr, 'root')
Пример #3
0
def oidc_auth(account, issuer, ui_vo=None):
    """
    # TODO: Validate for Flask
    Open ID Connect Login
    :param account: Rucio account string
    :param issuer: issuer key (e.g. xdc, wlcg) as in the idpsecrets.json file
    :param ui_vo: 3 character string to identify the VO, if None will attempt to deduce it from `account`
    :returns: rendered final page or a page with error message
    """
    if not account:
        account = 'webui'
    if ui_vo is None:
        all_vos = [vo['vo'] for vo in vo_core.list_vos()]
        valid_vos = []
        for vo in all_vos:
            if account_exists(account, vo):
                valid_vos.append(vo)
        if len(valid_vos) == 0:
            return render_template(
                "problem.html",
                msg=('Cannot find any Rucio account %s at any VO.' %
                     html_escape(account)))
        elif len(valid_vos) == 1:
            ui_vo = valid_vos[0]
        else:
            vos_with_desc = get_vo_descriptions(valid_vos)
            return add_cookies(
                make_response(
                    render_template("select_login_method.html",
                                    oidc_issuers=AUTH_ISSUERS,
                                    saml_support=SAML_SUPPORT,
                                    possible_vos=vos_with_desc)))

    if not issuer:
        return render_template("problem.html",
                               msg="Please provide IdP issuer.")
    realhome = request.environ.get(
        'REQUEST_SCHEME') + '://' + request.environ.get(
            'HTTP_HOST') + request.environ.get('SCRIPT_NAME')
    kwargs = {
        'audience': None,
        'auth_scope': None,
        'issuer': issuer.lower(),
        'auto': True,
        'polling': False,
        'refresh_lifetime': None,
        'ip': None,
        'webhome': realhome + '/oidc_final'
    }
    auth_url = auth.get_auth_oidc(account, vo=ui_vo, **kwargs)
    if not auth_url:
        return render_template(
            "problem.html",
            msg=
            "It was not possible to get the OIDC authentication url from the Rucio auth server. "
            +
            "In case you provided your account name, make sure it is known to Rucio."
        )  # NOQA: W503
    return redirect(auth_url, code=303)
Пример #4
0
def oidc_auth(account, issuer, ui_vo=None):
    """
    Open ID Connect Login
    :param account: Rucio account string
    :param issuer: issuer key (e.g. xdc, wlcg) as in the idpsecrets.json file
    :param ui_vo: 3 character string to identify the VO, if None will attempt to deduce it from `account`
    :returns: rendered final page or a page with error message
    """
    if not account:
        account = 'webui'
    if ui_vo is None:
        all_vos = [vo['vo'] for vo in vo_core.list_vos()]
        valid_vos = []
        for vo in all_vos:
            if account_exists(account, vo):
                valid_vos.append(vo)
        if len(valid_vos) == 0:
            return RENDERER.problem(
                ('Cannot find any Rucio account %s at any VO.' %
                 html_escape(account)))
        elif len(valid_vos) == 1:
            ui_vo = valid_vos[0]
        else:
            vos_with_desc = get_vo_descriptions(valid_vos)
            return RENDERER.select_login_method(AUTH_ISSUERS, SAML_SUPPORT,
                                                vos_with_desc)

    if not issuer:
        return RENDERER.problem("Please provide IdP issuer.")
    kwargs = {
        'audience': None,
        'auth_scope': None,
        'issuer': issuer.lower(),
        'auto': True,
        'polling': False,
        'refresh_lifetime': None,
        'ip': None,
        'webhome': ctx.realhome + '/oidc_final'
    }
    auth_url = auth.get_auth_oidc(account, vo=ui_vo, **kwargs)
    if not auth_url:
        return RENDERER.problem(
            "It was not possible to get the OIDC authentication url from the Rucio auth server. "
            +
            "In case you provided your account name, make sure it is known to Rucio."
        )  # NOQA: W503
    return seeother(auth_url)
Пример #5
0
def saml_auth(method, data=None):
    """
    # TODO: Validate for Flask
    Login with SAML
    :param method: method type, GET or POST
    :param data: data object containing account string can be provided
    :param rendered_tpl: page to be rendered
    :returns: rendered final page or a page with error message
    """
    SAML_PATH = join(dirname(__file__), 'saml/')
    req = prepare_saml_request()
    samlauth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH)
    saml_user_data = request.cookies.get('saml-user-data')
    if not MULTI_VO:
        ui_vo = 'def'
    elif hasattr(data, 'vo') and data.vo:
        ui_vo = data.vo
    else:
        ui_vo = None
    if hasattr(data, 'account') and data.account:
        ui_account = data.account
    else:
        ui_account = None

    if method == "GET":
        # If user data is not present, redirect to IdP for authentication
        if not saml_user_data:
            return redirect(samlauth.login(), code=303)
        # If user data is present but token is not valid, create a new one
        saml_nameid = request.cookies.get('saml-nameid')
        if ui_account is None and ui_vo is None:
            ui_account, ui_vo = select_account_name(saml_nameid, 'saml', ui_vo)
        elif ui_account is None:
            ui_account, _ = select_account_name(saml_nameid, 'saml', ui_vo)
        elif ui_vo is None:
            _, ui_vo = select_account_name(saml_nameid, 'saml', ui_vo)

        # Try to eliminate VOs based on the account name (if we have one), if we still have multiple options let the user select one
        if type(ui_vo) is list:
            if ui_account:
                valid_vos = []
                for vo in ui_vo:
                    if account_exists(ui_account, vo):
                        valid_vos.append(vo)
                if len(valid_vos) == 0:
                    return render_template(
                        "problem.html",
                        msg=
                        ('Cannot find any Rucio account %s associated with identity %s at any VO.'
                         %
                         (html_escape(ui_account), html_escape(saml_nameid))))
                elif len(valid_vos) == 1:
                    ui_vo = valid_vos[0]
                else:
                    vos_with_desc = get_vo_descriptions(valid_vos)
                    return add_cookies(
                        make_response(
                            render_template("select_login_method.html",
                                            oidc_issuers=AUTH_ISSUERS,
                                            saml_support=SAML_SUPPORT,
                                            possible_vos=vos_with_desc)))
            else:
                vos_with_desc = get_vo_descriptions(ui_vo)
                return add_cookies(
                    make_response(
                        render_template("select_login_method.html",
                                        oidc_issuers=AUTH_ISSUERS,
                                        saml_support=SAML_SUPPORT,
                                        possible_vos=vos_with_desc)))

        if not ui_account:
            if MULTI_VO:
                return render_template(
                    "problem.html",
                    msg=
                    'Cannot get find any account associated with %s identity at VO %s.'
                    % (html_escape(saml_nameid), html_escape(ui_vo)))
            else:
                return render_template(
                    "problem.html",
                    msg=
                    'Cannot get find any account associated with %s identity.'
                    % (html_escape(saml_nameid)))
        token = get_token(auth.get_auth_token_saml,
                          acc=ui_account,
                          vo=ui_vo,
                          idt=saml_nameid)
        if not token:
            if MULTI_VO:
                return render_template(
                    "problem.html",
                    msg=
                    ('Cannot get auth token. It is possible that the presented identity %s is not mapped to any Rucio account %s at VO %s.'
                     ) % (html_escape(saml_nameid), html_escape(ui_account),
                          html_escape(ui_vo)))
            else:
                return render_template(
                    "problem.html",
                    msg=
                    ('Cannot get auth token. It is possible that the presented identity %s is not mapped to any Rucio account %s.'
                     ) % (html_escape(saml_nameid), html_escape(ui_account)))
        return finalize_auth(token, 'saml')

    # If method is POST, check the received SAML response and redirect to home if valid
    samlauth.process_response()
    errors = samlauth.get_errors()
    if not errors:
        if samlauth.is_authenticated():
            saml_nameid = samlauth.get_nameid()
            cookie_extra = {'saml-nameid': saml_nameid}
            cookie_extra['saml-user-data'] = samlauth.get_attributes()
            cookie_extra['saml-session-index'] = samlauth.get_session_index()
            # WHY THIS ATTEMPTS TO GET A NEW TOKEN ?
            # WE SHOULD HAVE IT/GET IT FROM COOKIE OR DB AND JUST REDIRECT, NO ?
            if ui_account is None and ui_vo is None:
                ui_account, ui_vo = select_account_name(
                    saml_nameid, 'saml', ui_vo)
            elif ui_account is None:
                ui_account, _ = select_account_name(saml_nameid, 'saml', ui_vo)
            elif ui_vo is None:
                _, ui_vo = select_account_name(saml_nameid, 'saml', ui_vo)

            # Try to eliminate VOs based on the account name (if we have one), if we still have multiple options let the user select one
            if type(ui_vo) is list:
                if ui_account:
                    valid_vos = []
                    for vo in ui_vo:
                        if account_exists(ui_account, vo):
                            valid_vos.append(vo)
                    if len(valid_vos) == 0:
                        return render_template(
                            "problem.html",
                            msg=
                            ('Cannot find any Rucio account %s associated with identity %s at any VO.'
                             % (html_escape(ui_account),
                                html_escape(saml_nameid))))
                    elif len(valid_vos) == 1:
                        ui_vo = valid_vos[0]
                    else:
                        vos_with_desc = get_vo_descriptions(valid_vos)
                        return add_cookies(
                            make_response(
                                render_template("select_login_method.html",
                                                oidc_issuers=AUTH_ISSUERS,
                                                saml_support=SAML_SUPPORT,
                                                possible_vos=vos_with_desc)))
                else:
                    vos_with_desc = get_vo_descriptions(ui_vo)
                    return add_cookies(
                        make_response(
                            render_template("select_login_method.html",
                                            oidc_issuers=AUTH_ISSUERS,
                                            saml_support=SAML_SUPPORT,
                                            possible_vos=vos_with_desc)))

            if not ui_account:
                if MULTI_VO:
                    return render_template(
                        "problem.html",
                        msg=
                        'Cannot get find any account associated with %s identity at VO %s.'
                        % (html_escape(saml_nameid), html_escape(ui_vo)))
                else:
                    return render_template(
                        "problem.html",
                        msg=
                        'Cannot get find any account associated with %s identity.'
                        % (html_escape(saml_nameid)))
            token = get_token(auth.get_auth_token_saml,
                              acc=ui_account,
                              vo=ui_vo,
                              idt=saml_nameid)
            if not token:
                if MULTI_VO:
                    return render_template(
                        "problem.html",
                        msg=
                        ('Cannot get auth token. It is possible that the presented identity %s is not mapped to any Rucio account %s at VO %s.'
                         ) % (html_escape(saml_nameid),
                              html_escape(ui_account), html_escape(ui_vo)))
                else:
                    return render_template(
                        "problem.html",
                        msg=
                        ('Cannot get auth token. It is possible that the presented identity %s is not mapped to any Rucio account %s.'
                         ) %
                        (html_escape(saml_nameid), html_escape(ui_account)))
            return finalize_auth(token, 'saml', cookie_extra)

        return render_template("problem.html", msg="Not authenticated")

    return render_template("problem.html", msg="Error while processing SAML")
Пример #6
0
def userpass_auth():
    """
    Manages login via Rucio USERPASS method.
    :returns: final page or a page with an error message
    """

    ui_account = request.args.get('account')
    ui_vo = request.args.get('vo')
    username = request.form.get('username')
    password = request.form.get('password')

    if not username and not password:
        return render_template('problem.html',
                               msg="No input credentials were provided.")

    if not MULTI_VO:
        ui_vo = 'def'
    if ui_account is None and ui_vo is None:
        ui_account, ui_vo = select_account_name(username, 'userpass', ui_vo)
    elif ui_account is None:
        ui_account, _ = select_account_name(username, 'userpass', ui_vo)
    elif ui_vo is None:
        _, ui_vo = select_account_name(username, 'userpass', ui_vo)

    if type(ui_vo) is list:
        if ui_account:
            valid_vos = []
            for vo in ui_vo:
                if account_exists(ui_account, vo):
                    valid_vos.append(vo)

            if len(valid_vos) == 0:
                return render_template(
                    'problem.html',
                    msg=
                    'Cannot find any Rucio account %s associated with identity %s at any VO.'
                    % (html_escape(ui_account), html_escape(username)))
            elif len(valid_vos) == 1:
                ui_vo = valid_vos[0]
            else:
                vos_with_desc = get_vo_descriptions(valid_vos)
                return render_template('login.html',
                                       account=ui_account,
                                       vo=None,
                                       possible_vos=vos_with_desc)
        else:
            vos_with_desc = get_vo_descriptions(ui_vo)
            return render_template('login.html',
                                   account=None,
                                   vo=None,
                                   possible_vos=vos_with_desc)

    if not ui_account:
        if MULTI_VO:
            return render_template(
                'problem.html',
                msg=
                'Cannot get find any account associated with %s identity at VO %s.'
                % (html_escape(username), html_escape(ui_vo)))
        else:
            return render_template(
                'problem.html',
                msg='Cannot get find any account associated with %s identity.'
                % (html_escape(username)))
    token = get_token(auth.get_auth_token_user_pass,
                      acc=ui_account,
                      vo=ui_vo,
                      idt=username,
                      pwd=password)
    if not token:
        if MULTI_VO:
            return render_template(
                'problem.html',
                msg=
                'Cannot get auth token. It is possible that the presented identity %s is not mapped to any Rucio account %s at VO %s.'
            ) % (html_escape(username), html_escape(ui_account),
                 html_escape(ui_vo))
        else:
            return render_template(
                'problem.html',
                msg=
                'Cannot get auth token. It is possible that the presented identity %s is not mapped to any Rucio account %s.'
            ) % (html_escape(username), html_escape(ui_account))

    return finalize_auth(token, 'userpass')
Пример #7
0
def x509token_auth(data=None):
    """
    Manages login via X509 certificate.
    :param data: data object containing account string can be provided
    :returns: final page or a page with an error message
    """
    # checking if Rucio auth server succeeded to verify the certificate
    if request.environ.get('SSL_CLIENT_VERIFY') != 'SUCCESS':
        return render_template(
            "problem.html",
            msg=
            "No certificate provided. Please authenticate with a certificate registered in Rucio."
        )
    dn = request.environ.get('SSL_CLIENT_S_DN')
    if not dn.startswith('/'):
        dn = '/%s' % '/'.join(dn.split(',')[::-1])
    if not MULTI_VO:
        ui_vo = 'def'
    elif hasattr(data, 'vo') and data.vo:
        ui_vo = data.vo
    else:
        ui_vo = None
    if hasattr(data, 'account') and data.account:
        ui_account = data.account
    else:
        ui_account = None

    if ui_account is None and ui_vo is None:
        ui_account, ui_vo = select_account_name(dn, 'x509', ui_vo)
    elif ui_account is None:
        ui_account, _ = select_account_name(dn, 'x509', ui_vo)
    elif ui_vo is None:
        _, ui_vo = select_account_name(dn, 'x509', ui_vo)

    # Try to eliminate VOs based on the account name (if we have one), if we still have multiple options let the user select one
    if type(ui_vo) is list:
        if ui_account:
            valid_vos = []
            for vo in ui_vo:
                if account_exists(ui_account, vo):
                    valid_vos.append(vo)
            if len(valid_vos) == 0:
                return render_template(
                    'problem.html',
                    msg=
                    ('<br><br>Your certificate (%s) is not mapped to (possibly any) rucio account: %s at any VO.'
                     % (html_escape(dn), html_escape(ui_account))))
            elif len(valid_vos) == 1:
                ui_vo = valid_vos[0]
            else:
                vos_with_desc = get_vo_descriptions(valid_vos)
                return add_cookies(
                    make_response(
                        render_template("select_login_method.html",
                                        oidc_issuers=AUTH_ISSUERS,
                                        saml_support=SAML_SUPPORT,
                                        possible_vos=vos_with_desc)))
        else:
            vos_with_desc = get_vo_descriptions(ui_vo)
            return add_cookies(
                make_response(
                    render_template("select_login_method.html",
                                    oidc_issuers=AUTH_ISSUERS,
                                    saml_support=SAML_SUPPORT,
                                    possible_vos=vos_with_desc)))

    if MULTI_VO:
        msg = "<br><br>Your certificate (%s) is not mapped to (possibly any) rucio account: %s at VO: %s." % (
            html_escape(dn), html_escape(ui_account), html_escape(ui_vo))
    else:
        msg = "<br><br>Your certificate (%s) is not mapped to (possibly any) rucio account: %s." % (
            html_escape(dn), html_escape(ui_account))
    msg += "<br><br><font color=\"red\">First, please make sure it is correctly registered in <a href=\"https://voms2.cern.ch:8443/voms/atlas\">VOMS</a> and be patient until it has been fully propagated through the system.</font>"
    msg += "<br><br>Then, if it is still not working please contact <a href=\"mailto:[email protected]\">DDM Support</a>."
    if not ui_account:
        return render_template("problem.html", msg=msg)
    token = get_token(auth.get_auth_token_x509,
                      acc=ui_account,
                      vo=ui_vo,
                      idt=dn)
    if not token:
        return render_template("problem.html", msg=msg)
    return finalize_auth(token, 'x509')
Пример #8
0
def userpass_auth(data, rendered_tpl):
    """
    Manages login via Rucio USERPASS method.
    :param data: data object containing account, VO (if multi_vo), username and password string
    :param rendered_tpl: rendered page template
    :returns: final page or a page with an error message
    """
    if not data:
        return RENDERER.problem("No input credentials were provided.")
    else:
        # if user tries to access a page through URL without logging in, then redirect to login page.
        if rendered_tpl:
            return RENDERER.login(None)
        if not MULTI_VO:
            ui_vo = 'def'
        elif hasattr(data, 'vo') and data.vo:
            ui_vo = data.vo
        else:
            ui_vo = None
        if hasattr(data, 'account') and data.account:
            ui_account = data.account
        else:
            ui_account = None

        if ui_account is None and ui_vo is None:
            ui_account, ui_vo = select_account_name(data.username, 'userpass',
                                                    ui_vo)
        elif ui_account is None:
            ui_account, _ = select_account_name(data.username, 'userpass',
                                                ui_vo)
        elif ui_vo is None:
            _, ui_vo = select_account_name(data.username, 'userpass', ui_vo)

        # Try to eliminate VOs based on the account name (if we have one), if we still have multiple options let the user select one
        if type(ui_vo) is list:
            if ui_account:
                valid_vos = []
                for vo in ui_vo:
                    if account_exists(ui_account, vo):
                        valid_vos.append(vo)

                if len(valid_vos) == 0:
                    return RENDERER.problem((
                        'Cannot find any Rucio account %s associated with identity %s at any VO.'
                        %
                        (html_escape(ui_account), html_escape(data.username))))
                elif len(valid_vos) == 1:
                    ui_vo = valid_vos[0]
                else:
                    vos_with_desc = get_vo_descriptions(valid_vos)
                    return RENDERER.login(ui_account, None, vos_with_desc)
            else:
                vos_with_desc = get_vo_descriptions(ui_vo)
                return RENDERER.login(None, None, vos_with_desc)

        if not ui_account:
            if MULTI_VO:
                return RENDERER.problem((
                    'Cannot get find any account associated with %s identity at VO %s.'
                    % (html_escape(data.username), html_escape(ui_vo))))
            else:
                return RENDERER.problem(
                    ('Cannot get find any account associated with %s identity.'
                     % (html_escape(data.username))))
        token = get_token(auth.get_auth_token_user_pass,
                          acc=ui_account,
                          vo=ui_vo,
                          idt=data.username,
                          pwd=data.password.encode("ascii"))
        if not token:
            if MULTI_VO:
                return RENDERER.problem((
                    'Cannot get auth token. It is possible that the presented identity %s is not mapped to any Rucio account %s at VO %s.'
                ) % (html_escape(data.username), html_escape(ui_account),
                     html_escape(ui_vo)))
            else:
                return RENDERER.problem((
                    'Cannot get auth token. It is possible that the presented identity %s is not mapped to any Rucio account %s.'
                ) % (html_escape(data.username), html_escape(ui_account)))

    return finalize_auth(token, 'userpass')
Пример #9
0
def x509token_auth(data=None):
    """
    Manages login via X509 certificate.
    :param data: data object containing account string can be provided
    :returns: final page or a page with an error message
    """
    # checking if Rucio auth server succeeded to verify the certificate
    if ctx.env.get('SSL_CLIENT_VERIFY') != 'SUCCESS':
        return RENDERER.problem(
            "No certificate provided. Please authenticate with a certificate registered in Rucio."
        )
    dn = ctx.env.get('SSL_CLIENT_S_DN')
    if not dn.startswith('/'):
        dn = '/%s' % '/'.join(dn.split(',')[::-1])
    if not MULTI_VO:
        ui_vo = 'def'
    elif hasattr(data, 'vo') and data.vo:
        ui_vo = data.vo
    else:
        ui_vo = None
    if hasattr(data, 'account') and data.account:
        ui_account = data.account
    else:
        ui_account = None

    if ui_account is None and ui_vo is None:
        ui_account, ui_vo = select_account_name(dn, 'x509', ui_vo)
    elif ui_account is None:
        ui_account, _ = select_account_name(dn, 'x509', ui_vo)
    elif ui_vo is None:
        _, ui_vo = select_account_name(dn, 'x509', ui_vo)

    # Try to eliminate VOs based on the account name (if we have one), if we still have multiple options let the user select one
    if type(ui_vo) is list:
        if ui_account:
            valid_vos = []
            for vo in ui_vo:
                if account_exists(ui_account, vo):
                    valid_vos.append(vo)
            if len(valid_vos) == 0:
                return RENDERER.problem((
                    '<br><br>Your certificate (%s) is not mapped to (possibly any) rucio account: %s at any VO.'
                    % (html_escape(dn), html_escape(ui_account))))
            elif len(valid_vos) == 1:
                ui_vo = valid_vos[0]
            else:
                vos_with_desc = get_vo_descriptions(valid_vos)
                return RENDERER.select_login_method(AUTH_ISSUERS, SAML_SUPPORT,
                                                    vos_with_desc)
        else:
            vos_with_desc = get_vo_descriptions(ui_vo)
            return RENDERER.select_login_method(AUTH_ISSUERS, SAML_SUPPORT,
                                                vos_with_desc)

    if not ui_account:
        if MULTI_VO:
            msg = "<br><br>Your certificate (%s) is not mapped to (possibly any) rucio account at VO: %s." % (
                html_escape(dn), html_escape(ui_vo))
        else:
            msg = "<br><br>Your certificate (%s) is not mapped to (possibly any) rucio account." % (
                html_escape(dn))
    else:
        if MULTI_VO:
            msg = "<br><br>Your certificate (%s) is not mapped to (possibly any) rucio account: %s at VO: %s." % (
                html_escape(dn), html_escape(ui_account), html_escape(ui_vo))
        else:
            msg = "<br><br>Your certificate (%s) is not mapped to (possibly any) rucio account: %s." % (
                html_escape(dn), html_escape(ui_account))

    if ADDITIONAL_ERROR_MSG:
        msg += ADDITIONAL_ERROR_MSG
    if not ui_account:
        return RENDERER.problem(msg)
    token = get_token(auth.get_auth_token_x509,
                      acc=ui_account,
                      vo=ui_vo,
                      idt=dn)
    if not token:
        return RENDERER.problem(msg)
    return finalize_auth(token, 'x509')