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')
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')
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)
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)
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")
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')
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')
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')
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')