def get(self): """ .. :quickref: SAML; :status 200: OK :status 401: Unauthorized :reqheader Rucio-VO: VO name as a string (Multi-VO only) :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-Username: Username as a string. :reqheader Rucio-Password: Password as a string. :reqheader Rucio-AppID: Application identifier as a string. :resheader X-Rucio-SAML-Auth-URL: as a variable-length string header. """ headers = Headers() headers.set('Access-Control-Allow-Origin', request.environ.get('HTTP_ORIGIN')) headers.set('Access-Control-Allow-Headers', request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) headers.set('Access-Control-Allow-Methods', '*') headers.set('Access-Control-Allow-Credentials', 'true') headers.set('Access-Control-Expose-Headers', 'X-Rucio-Auth-Token') headers.set('Content-Type', 'application/octet-stream') headers.set('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') headers.add('Cache-Control', 'post-check=0, pre-check=0') headers.set('Pragma', 'no-cache') if not EXTRA_MODULES['onelogin']: return "SAML not configured on the server side.", 400, headers saml_nameid = cookies().get('saml-nameid') vo = request.headers.get('X-Rucio-VO', default='def') account = request.headers.get('X-Rucio-Account', default=None) appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) if saml_nameid: try: result = get_auth_token_saml(account, saml_nameid, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals(), headers=headers) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0], headers=headers) except Exception as error: logging.exception("Internal Error") return str(error), 500, headers if not result: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals(), headers=headers) headers.set('X-Rucio-Auth-Token', result.token) headers.set('X-Rucio-Auth-Token-Expires', date_to_str(result.expired_at)) return '', 200, headers # Path to the SAML config folder SAML_PATH = config_get('saml', 'config_path') req = prepare_saml_request(request.environ, dict(request.args.items(multi=False))) auth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH) headers.set('X-Rucio-SAML-Auth-URL', auth.login()) return '', 200, headers
def get(self): """ .. :quickref: SAML; :status 200: OK :status 401: Unauthorized :reqheader Rucio-VO: VO name as a string (Multi-VO only) :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-Username: Username as a string. :reqheader Rucio-Password: Password as a string. :reqheader Rucio-AppID: Application identifier as a string. :resheader X-Rucio-SAML-Auth-URL: as a variable-length string header. """ headers = self.get_headers() headers.set('Content-Type', 'application/octet-stream') headers.set('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') headers.add('Cache-Control', 'post-check=0, pre-check=0') headers.set('Pragma', 'no-cache') if not EXTRA_MODULES['onelogin']: return "SAML not configured on the server side.", 400, headers saml_nameid = request.cookies.get('saml-nameid', default=None) vo = request.headers.get('X-Rucio-VO', default='def') account = request.headers.get('X-Rucio-Account', default=None) appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) if saml_nameid: try: result = get_auth_token_saml(account, saml_nameid, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg=f'Cannot authenticate to account {account} with given credentials', headers=headers ) if not result: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg=f'Cannot authenticate to account {account} with given credentials', headers=headers ) headers.set('X-Rucio-Auth-Token', result.token) headers.set('X-Rucio-Auth-Token-Expires', date_to_str(result.expired_at)) return '', 200, headers # Path to the SAML config folder SAML_PATH = config_get('saml', 'config_path') req = prepare_saml_request(request.environ, dict(request.args.items(multi=False))) auth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH) headers.set('X-Rucio-SAML-Auth-URL', auth.login()) return '', 200, headers
def get(self): """ Authenticate a Rucio account temporarily via SSH key exchange. .. :quickref: SSH; Authenticate with SSH key exchange. :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-SSH-Signature: Response to server challenge signed with SSH private key as a base64 encoded string. :reqheader Rucio-AppID: Application identifier as a string. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ headers = Headers() headers['Access-Control-Allow-Origin'] = request.environ.get('HTTP_ORIGIN') headers['Access-Control-Allow-Headers'] = request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') headers['Access-Control-Allow-Methods'] = '*' headers['Access-Control-Allow-Credentials'] = 'true' headers['Access-Control-Expose-Headers'] = 'X-Rucio-Auth-Token' headers['Content-Type'] = 'application/octet-stream' headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' headers.add('Cache-Control', 'post-check=0, pre-check=0') headers['Pragma'] = 'no-cache' vo = request.headers.get('X-Rucio-VO', default='def') account = request.headers.get('X-Rucio-Account', default=None) signature = request.headers.get('X-Rucio-SSH-Signature', default=None) appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) # decode the signature which must come in base64 encoded try: signature = base64.b64decode(signature) except TypeError: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with malformed signature' % locals(), headers=headers) try: result = get_auth_token_ssh(account, signature, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals(), headers=headers) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0], headers=headers) except Exception as error: logging.exception("Internal Error") return str(error), 500 if not result: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals(), headers=headers) headers['X-Rucio-Auth-Token'] = result.token headers['X-Rucio-Auth-Token-Expires'] = date_to_str(result.expired_at) return '', 200, headers
def list_dids(self, scope, filters, type='collection', long=False): """ List all data identifiers in a scope which match a given pattern. :param scope: The scope name. :param filters: A dictionary of key/value pairs like {'name': 'file_name','rse-expression': 'tier0'}. :param type: The type of the did: 'all'(container, dataset or file)|'collection'(dataset or container)|'dataset'|'container'|'file' :param long: Long format option to display more information for each DID. """ path = '/'.join( [self.DIDS_BASEURL, quote_plus(scope), 'dids', 'search']) payload = {} if long: payload['long'] = 1 for k, v in filters.items(): if k in ('created_before', 'created_after'): payload[k] = date_to_str(v) else: payload[k] = v payload['type'] = type url = build_url(choice(self.list_hosts), path=path, params=payload) r = self._send_request(url, type='GET') if r.status_code == codes.ok: dids = self._load_json_data(r) return dids else: exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content) raise exc_cls(exc_msg)
def list_dids_extended(self, scope, filters, did_type='collection', long=False, recursive=False): """ List all data identifiers in a scope which match a given pattern. Extended version that goes through plugin mechanism. :param scope: The scope name. :param filters: A dictionary of key/value pairs like {'type': 'dataset', 'scope': 'test'}. :param did_type: The type of the did: 'all'(container, dataset or file)|'collection'(dataset or container)|'dataset'|'container'|'file' :param long: Long format option to display more information for each DID. :param recursive: Recursively list DIDs content. """ path = '/'.join([self.DIDS_BASEURL, quote_plus(scope), 'dids', 'search_extended']) payload = {} for k, v in list(filters.items()): if k in ('created_before', 'created_after'): payload[k] = date_to_str(v) else: payload[k] = v payload['long'] = long payload['type'] = did_type payload['recursive'] = recursive url = build_url(choice(self.list_hosts), path=path, params=payload) r = self._send_request(url, type_='GET') if r.status_code == codes.ok: dids = self._load_json_data(r) return dids else: exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content) raise exc_cls(exc_msg)
def get(self): """ Authenticate a Rucio account temporarily via username and password. .. :quickref: UserPass; Authenticate with username/password :reqheader X-Rucio-VO: VO name as a string (Multi-VO Only) :reqheader X-Rucio-Account: Account identifier as a string. :reqheader X-Rucio-Username: Username as a string. :reqheader X-Rucio-Password: password as a text-plain string. :reqheader X-Rucio-AppID: Application identifier as a string. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ headers = Headers() headers['Access-Control-Allow-Origin'] = request.environ.get('HTTP_ORIGIN') headers['Access-Control-Allow-Headers'] = request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') headers['Access-Control-Allow-Methods'] = '*' headers['Access-Control-Allow-Credentials'] = 'true' headers['Access-Control-Expose-Headers'] = 'X-Rucio-Auth-Token' headers['Content-Type'] = 'application/octet-stream' headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' headers.add('Cache-Control', 'post-check=0, pre-check=0') headers['Pragma'] = 'no-cache' vo = request.headers.get('X-Rucio-VO', default='def') account = request.headers.get('X-Rucio-Account', default=None) username = request.headers.get('X-Rucio-Username', default=None) password = request.headers.get('X-Rucio-Password', default=None) appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) if not account or not username or not password: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate without passing all required arguments', headers=headers) try: result = get_auth_token_user_pass(account, username, password, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals(), headers=headers) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0], headers=headers) except Exception as error: logging.exception("Internal Error") return str(error), 500, headers if not result: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals(), headers=headers) headers['X-Rucio-Auth-Token'] = result.token headers['X-Rucio-Auth-Token-Expires'] = date_to_str(result.expired_at) return '', 200, headers
def GET(self): """ HTTP Success: 200 OK HTTP Error: 401 Unauthorized :param QUERY_STRING: the URL query string itself :returns: "Rucio-Auth-Token" as a variable-length string header. """ header('Access-Control-Allow-Origin', ctx.env.get('HTTP_ORIGIN')) header('Access-Control-Allow-Headers', ctx.env.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) header('Access-Control-Allow-Methods', '*') header('Access-Control-Allow-Credentials', 'true') header('Content-Type', 'application/octet-stream') header('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') header('Cache-Control', 'post-check=0, pre-check=0', False) header('Pragma', 'no-cache') query_string = ctx.env.get('QUERY_STRING') ip = ctx.env.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = ctx.ip try: result = get_token_oidc(query_string, ip) except AccessDenied: raise generate_http_error(401, 'CannotAuthorize', 'Cannot authorize token request.') except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) if not result: raise generate_http_error(401, 'CannotAuthorize', 'Cannot authorize token request.') if 'token' in result and 'webhome' not in result: header('X-Rucio-Auth-Token', result['token'].token) # pylint: disable=no-member header('X-Rucio-Auth-Token-Expires', date_to_str(result['token'].expired_at)) # pylint: disable=no-member return str() elif 'webhome' in result: webhome = result['webhome'] if webhome is None: header('Content-Type', 'text/html') render = template.render(join(dirname(__file__), '../auth_templates/')) return render.auth_crash('unknown_identity') # domain setting is necessary so that the token gets distributed also to the webui server domain = '.'.join(urlparse.urlparse(webhome).netloc.split('.')[1:]) setcookie('x-rucio-auth-token', value=result['token'].token, domain=domain, path='/') setcookie('rucio-auth-token-created-at', value=int(time.time()), domain=domain, path='/') return seeother(webhome) else: raise BadRequest()
def GET(self): """ HTTP Success: 200 OK HTTP Error: 401 Unauthorized :param Rucio-VO: VO name as a string (Multi-VO only). :param Rucio-Account: Account identifier as a string. :param Rucio-AppID: Application identifier as a string. :param SavedCredentials: Apache mod_auth_kerb SavedCredentials. :returns: "Rucio-Auth-Token" as a variable-length string header. """ header('Access-Control-Allow-Origin', ctx.env.get('HTTP_ORIGIN')) header('Access-Control-Allow-Headers', ctx.env.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) header('Access-Control-Allow-Methods', '*') header('Access-Control-Allow-Credentials', 'true') header('Access-Control-Expose-Headers', 'X-Rucio-Auth-Token') header('Content-Type', 'application/octet-stream') header('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') header('Cache-Control', 'post-check=0, pre-check=0', False) header('Pragma', 'no-cache') vo = ctx.env.get('HTTP_X_RUCIO_VO', '') account = ctx.env.get('HTTP_X_RUCIO_ACCOUNT') gsscred = ctx.env.get('REMOTE_USER') appid = ctx.env.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = ctx.env.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = ctx.ip try: result = get_auth_token_gss(account, gsscred, appid, ip, vo=vo) except AccessDenied: raise generate_http_error( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) if result is None: raise generate_http_error( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) else: header('X-Rucio-Auth-Token', result.token) header('X-Rucio-Auth-Token-Expires', date_to_str(result.expired_at)) return str() raise BadRequest()
def GET(self): """ HTTP Success: 200 OK HTTP Error: 401 Unauthorized :param Rucio-VO: VO name as a string (Multi-VO only). :param Rucio-Account: Account identifier as a string. :param Rucio-SSH-Signature: Response to server challenge signed with SSH private key as a base64 encoded string. :param Rucio-AppID: Application identifier as a string. :returns: "Rucio-Auth-Token" as a variable-length string header. """ header('Access-Control-Allow-Origin', ctx.env.get('HTTP_ORIGIN')) header('Access-Control-Allow-Headers', ctx.env.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) header('Access-Control-Allow-Methods', '*') header('Access-Control-Allow-Credentials', 'true') header('Access-Control-Expose-Headers', 'X-Rucio-Auth-Token') header('Content-Type', 'application/octet-stream') header('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') header('Cache-Control', 'post-check=0, pre-check=0', False) header('Pragma', 'no-cache') vo = ctx.env.get('HTTP_X_RUCIO_VO', 'def') account = ctx.env.get('HTTP_X_RUCIO_ACCOUNT') signature = ctx.env.get('HTTP_X_RUCIO_SSH_SIGNATURE') appid = ctx.env.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = ctx.env.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = ctx.ip # decode the signature which must come in base64 encoded try: signature = base64.b64decode(signature) except: raise generate_http_error(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with malformed signature' % locals()) try: result = get_auth_token_ssh(account, signature, appid, ip, vo=vo) except AccessDenied: raise generate_http_error(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) if not result: raise generate_http_error(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) header('X-Rucio-Auth-Token', result.token) header('X-Rucio-Auth-Token-Expires', date_to_str(result.expired_at)) return str()
def get(self): """ Authenticate a Rucio account temporarily via a GSS token. .. :quickref: GSS; Authenticate with GSS token :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-AppID: Application identifier as a string. :reqheader SavedCredentials: Apache mod_auth_kerb SavedCredentials. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ headers = self.get_headers() headers['Content-Type'] = 'application/octet-stream' headers[ 'Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' headers.add('Cache-Control', 'post-check=0, pre-check=0') headers['Pragma'] = 'no-cache' vo = extract_vo(request.headers) account = request.headers.get('X-Rucio-Account', default=None) gsscred = request.environ.get('REMOTE_USER') appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) try: result = get_auth_token_gss(account, gsscred, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg= f'Cannot authenticate to account {account} with given credentials', headers=headers) if result is None: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg= f'Cannot authenticate to account {account} with given credentials', headers=headers) headers['X-Rucio-Auth-Token'] = result['token'] headers['X-Rucio-Auth-Token-Expires'] = date_to_str( result['expires_at']) return '', 200, headers
def get(self): """ .. :quickref: OIDC; :status 200: OK :status 401: Unauthorized :resheader X-Rucio-Auth-Token: The authentication token :resheader X-Rucio-Auth-Token-Expires: The time when the token expires """ headers = Headers() headers.set('Access-Control-Allow-Origin', request.environ.get('HTTP_ORIGIN')) headers.set('Access-Control-Allow-Headers', request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) headers.set('Access-Control-Allow-Methods', '*') headers.set('Access-Control-Allow-Credentials', 'true') headers.set('Content-Type', 'application/octet-stream') headers.set('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') headers.add('Cache-Control', 'post-check=0, pre-check=0') headers.set('Pragma', 'no-cache') query_string = request.query_string.decode(encoding='utf-8') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) try: result = get_token_oidc(query_string, ip) except AccessDenied: return generate_http_error_flask(401, 'CannotAuthorize', 'Cannot authorize token request.', headers=headers) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0], headers=headers) except Exception as error: logging.exception("Internal Error") return str(error), 500, headers if not result: return generate_http_error_flask(401, 'CannotAuthorize', 'Cannot authorize token request.', headers=headers) if 'token' in result and 'webhome' not in result: headers.set('X-Rucio-Auth-Token', result['token'].token) headers.set('X-Rucio-Auth-Token-Expires', date_to_str(result['token'].expired_at)) return '', 200, headers elif 'webhome' in result: webhome = result['webhome'] if webhome is None: headers.extend(error_headers('CannotAuthenticate', 'Cannot find your OIDC identity linked to any Rucio account')) headers.set('Content-Type', 'text/html') return render_template('auth_crash.html', crashtype='unknown_identity'), 401, headers # domain setting is necessary so that the token gets distributed also to the webui server domain = '.'.join(urlparse.urlparse(webhome).netloc.split('.')[1:]) response = redirect(webhome, code=303) response.headers.extend(headers) response.set_cookie('x-rucio-auth-token', value=result['token'].token, domain=domain, path='/') response.set_cookie('rucio-auth-token-created-at', value=str(time.time()), domain=domain, path='/') return response else: return '', 400, headers
def GET(self): """ HTTP Success: 200 OK HTTP Error: 401 Unauthorized :param Rucio-VO: VO name as a string (Multi-VO only). :param Rucio-Account: Account identifier as a string. :param Rucio-AppID: Application identifier as a string. :returns: "Rucio-Auth-Token" as a variable-length string header. """ header('Access-Control-Allow-Origin', ctx.env.get('HTTP_ORIGIN')) header('Access-Control-Allow-Headers', ctx.env.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) header('Access-Control-Allow-Methods', '*') header('Access-Control-Allow-Credentials', 'true') header('Access-Control-Expose-Headers', 'X-Rucio-Auth-Token') header('Content-Type', 'application/octet-stream') header('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') header('Cache-Control', 'post-check=0, pre-check=0', False) header('Pragma', 'no-cache') vo = ctx.env.get('HTTP_X_RUCIO_VO', 'def') account = ctx.env.get('HTTP_X_RUCIO_ACCOUNT') appid = ctx.env.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = ctx.env.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = ctx.ip try: result = get_ssh_challenge_token(account, appid, ip, vo=vo) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) if not result: raise generate_http_error( 401, 'CannotAuthenticate', 'Cannot generate challenge for account %(account)s' % locals()) header('X-Rucio-SSH-Challenge-Token', result.token) header('X-Rucio-SSH-Challenge-Token-Expires', date_to_str(result.expired_at)) return str()
def GET(self): """ HTTP Success: 200 OK HTTP Error: 401 Unauthorized :param Rucio-Account: Account identifier as a string. :param Rucio-Username: Username as a string. :param Rucio-Password: SHA1 hash of the password as a string. :param Rucio-AppID: Application identifier as a string. :returns: "Rucio-Auth-Token" as a variable-length string header. """ header('Access-Control-Allow-Origin', ctx.env.get('HTTP_ORIGIN')) header('Access-Control-Allow-Headers', ctx.env.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) header('Access-Control-Allow-Methods', '*') header('Access-Control-Allow-Credentials', 'true') header('Access-Control-Expose-Headers', 'X-Rucio-Auth-Token') header('Content-Type', 'application/octet-stream') header('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') header('Cache-Control', 'post-check=0, pre-check=0', False) header('Pragma', 'no-cache') account = ctx.env.get('HTTP_X_RUCIO_ACCOUNT') username = ctx.env.get('HTTP_X_RUCIO_USERNAME') password = ctx.env.get('HTTP_X_RUCIO_PASSWORD') appid = ctx.env.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = ctx.env.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = ctx.ip try: result = get_auth_token_user_pass(account, username, password, appid, ip) except AccessDenied: raise generate_http_error(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) if not result: raise generate_http_error(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) header('X-Rucio-Auth-Token', result.token) header('X-Rucio-Auth-Token-Expires', date_to_str(result.expired_at)) return str()
def get(self): """ Request a challenge token for SSH authentication .. :quickref: SSH; Request SSH Challenge Token :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-AppID: Application identifier as a string. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-SSH-Challenge-Token: The SSH challenge token :resheader X-Rucio-SSH-Challenge-Token-Expires: The expiry time of the token :status 200: Successfully authenticated :status 404: Invalid credentials """ headers = Headers() headers['Access-Control-Allow-Origin'] = request.environ.get('HTTP_ORIGIN') headers['Access-Control-Allow-Headers'] = request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') headers['Access-Control-Allow-Methods'] = '*' headers['Access-Control-Allow-Credentials'] = 'true' headers['Access-Control-Expose-Headers'] = 'X-Rucio-Auth-Token' headers['Content-Type'] = 'application/octet-stream' headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' headers.add('Cache-Control', 'post-check=0, pre-check=0') headers['Pragma'] = 'no-cache' vo = request.headers.get('X-Rucio-VO', default='def') account = request.headers.get('X-Rucio-Account', default=None) appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) try: result = get_ssh_challenge_token(account, appid, ip, vo=vo) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0], headers=headers) except Exception as error: logging.exception("Internal Error") return str(error), 500, headers if not result: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot generate challenge for account %(account)s' % locals(), headers=headers) headers['X-Rucio-SSH-Challenge-Token'] = result.token headers['X-Rucio-SSH-Challenge-Token-Expires'] = date_to_str(result.expired_at) return '', 200, headers
def list_dids_extended(self, scope, filters, did_type='collection', long=False, recursive=False): """ List all data identifiers in a scope which match a given pattern. :param scope: The scope name. :param filters: A nested dictionary of key/value pairs like [{'key1': 'value1', 'key2.lte': 'value2'}, {'key3.gte, 'value3'}]. Keypairs in the same dictionary are AND'ed together, dictionaries are OR'ed together. Keys should be suffixed like <key>.<operation>, e.g. key1 >= value1 is equivalent to {'key1.gte': value}, where <operation> belongs to one of the set {'lte', 'gte', 'gt', 'lt', 'ne' or ''}. Equivalence doesn't require an operator. :param did_type: The type of the did: 'all'(container, dataset or file)|'collection'(dataset or container)|'dataset'|'container'|'file' :param long: Long format option to display more information for each DID. :param recursive: Recursively list DIDs content. """ path = '/'.join( [self.DIDS_BASEURL, quote_plus(scope), 'dids', 'search_extended']) # stringify dates. if isinstance( filters, dict): # backwards compatability for filters as single {} filters = [filters] for or_group in filters: for key, value in or_group.items(): if isinstance(value, datetime): or_group[key] = date_to_str(value) payload = { 'type': did_type, 'filters': filters, 'long': long, 'recursive': recursive } url = build_url(choice(self.list_hosts), path=path, params=payload) r = self._send_request(url, type_='GET') if r.status_code == codes.ok: dids = self._load_json_data(r) return dids else: exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content) raise exc_cls(exc_msg)
def get(self): """ Authenticate a Rucio account temporarily via a GSS token. .. :quickref: GSS; Authenticate with GSS token :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-AppID: Application identifier as a string. :reqheader SavedCredentials: Apache mod_auth_kerb SavedCredentials. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ headers = Headers() headers['Access-Control-Allow-Origin'] = request.environ.get('HTTP_ORIGIN') headers['Access-Control-Allow-Headers'] = request.environ.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') headers['Access-Control-Allow-Methods'] = '*' headers['Access-Control-Allow-Credentials'] = 'true' headers['Access-Control-Expose-Headers'] = 'X-Rucio-Auth-Token' headers['Content-Type'] = 'application/octet-stream' headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' headers.add('Cache-Control', 'post-check=0, pre-check=0') headers['Pragma'] = 'no-cache' vo = request.headers.get('X-Rucio-VO', default='def') account = request.headers.get('X-Rucio-Account', default=None) gsscred = request.environ.get('REMOTE_USER') appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) try: result = get_auth_token_gss(account, gsscred, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals(), headers=headers) if result is None: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals(), headers=headers) headers['X-Rucio-Auth-Token'] = result.token headers['X-Rucio-Auth-Token-Expires'] = date_to_str(result.expired_at) return '', 200, headers
def list_dids(self, scope, filters, did_type='collection', long=False, recursive=False): """ List all data identifiers in a scope which match a given pattern. :param scope: The scope name. :param filters: A dictionary of key/value pairs like {'type': 'dataset', 'scope': 'test'}. :param did_type: The type of the did: 'all'(container, dataset or file)|'collection'(dataset or container)|'dataset'|'container'|'file' :param long: Long format option to display more information for each DID. :param recursive: Recursively list DIDs content. """ path = '/'.join( [self.DIDS_BASEURL, quote_plus(scope), 'dids', 'search']) # stringify dates. if isinstance( filters, dict): # backwards compatability for filters as single {} filters = [filters] for or_group in filters: for key, value in or_group.items(): if isinstance(value, datetime): or_group[key] = date_to_str(value) payload = { 'type': did_type, 'filters': filters, 'long': long, 'recursive': recursive } url = build_url(choice(self.list_hosts), path=path, params=payload) r = self._send_request(url, type_='GET') if r.status_code == codes.ok: dids = self._load_json_data(r) return dids else: exc_cls, exc_msg = self._get_exception(headers=r.headers, status_code=r.status_code, data=r.content) raise exc_cls(exc_msg)
def get(self): """ Request a challenge token for SSH authentication .. :quickref: SSH; Request SSH Challenge Token :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-AppID: Application identifier as a string. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-SSH-Challenge-Token: The SSH challenge token :resheader X-Rucio-SSH-Challenge-Token-Expires: The expiry time of the token :status 200: Successfully authenticated :status 404: Invalid credentials """ headers = self.get_headers() headers['Content-Type'] = 'application/octet-stream' headers[ 'Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' headers.add('Cache-Control', 'post-check=0, pre-check=0') headers['Pragma'] = 'no-cache' vo = request.headers.get('X-Rucio-VO', default='def') account = request.headers.get('X-Rucio-Account', default=None) appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) result = get_ssh_challenge_token(account, appid, ip, vo=vo) if not result: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg=f'Cannot generate challenge for account {account}', headers=headers) headers['X-Rucio-SSH-Challenge-Token'] = result.token headers['X-Rucio-SSH-Challenge-Token-Expires'] = date_to_str( result.expired_at) return '', 200, headers
def get(self): """ Authenticate a Rucio account temporarily via an x509 certificate. .. :quickref: x509; Authenticate with x509 certificate. :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-AppID: Application identifier as a string. :reqheader SSLStdEnv: Apache mod_ssl SSL Standard Env Variables. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ response = Response() response.headers['Access-Control-Allow-Origin'] = request.environ.get( 'HTTP_ORIGIN') response.headers['Access-Control-Allow-Headers'] = request.environ.get( 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS') response.headers['Access-Control-Allow-Methods'] = '*' response.headers['Access-Control-Allow-Credentials'] = 'true' response.headers[ 'Access-Control-Expose-Headers'] = 'X-Rucio-Auth-Token' response.headers['Content-Type'] = 'application/octet-stream' response.headers[ 'Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' response.headers['Cache-Control'] = 'post-check=0, pre-check=0' response.headers['Pragma'] = 'no-cache' vo = request.environ.get('HTTP_X_RUCIO_VO', 'def') account = request.environ.get('HTTP_X_RUCIO_ACCOUNT') dn = request.environ.get('SSL_CLIENT_S_DN') if not dn: return generate_http_error_flask(401, 'CannotAuthenticate', 'Cannot get DN') if not dn.startswith('/'): dn = '/%s' % '/'.join(dn.split(',')[::-1]) appid = request.environ.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = request.environ.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = request.remote_addr # If we get a valid proxy certificate we have to strip this postfix, # otherwise we would have to store the proxy DN in the database as well. # Alternative: use the SSL_CLIENT_I_DN, but that would require a separate # endpoint as you cannot programmatically decide, by examining the SSL variables, # if you got a proxy or regular certificate while True: if dn.endswith('/CN=limited proxy'): dn = dn[:-17] elif dn.endswith('/CN=proxy'): dn = dn[:-9] elif search('/CN=[0-9]*$', dn): dn = dn.rpartition('/')[0] else: break try: result = get_auth_token_x509(account, dn, appid, ip, vo=vo) except AccessDenied: print('Cannot Authenticate', account, dn, appid, ip, vo) return generate_http_error_flask( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) except IdentityError: print('Cannot Authenticate', account, dn, appid, ip, vo) return generate_http_error_flask( 401, 'CannotAuthenticate', 'No default account set for %(dn)s' % locals()) if not result: print('Cannot Authenticate', account, dn, appid, ip, vo) return generate_http_error_flask( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) response.headers['X-Rucio-Auth-Token'] = result.token response.headers['X-Rucio-Auth-Token-Expires'] = date_to_str( result.expired_at) return response
def get(self): """ Request a challenge token for SSH authentication .. :quickref: SSHChallengeToken; Request SSH Challenge Token :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-AppID: Application identifier as a string. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ response = Response() response.headers['Access-Control-Allow-Origin'] = request.environ.get( 'HTTP_ORIGIN') response.headers['Access-Control-Allow-Headers'] = request.environ.get( 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS') response.headers['Access-Control-Allow-Methods'] = '*' response.headers['Access-Control-Allow-Credentials'] = 'true' response.headers[ 'Access-Control-Expose-Headers'] = 'X-Rucio-Auth-Token' response.headers['Content-Type'] = 'application/octet-stream' response.headers[ 'Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' response.headers['Cache-Control'] = 'post-check=0, pre-check=0' response.headers['Pragma'] = 'no-cache' vo = request.environ.get('HTTP_X_RUCIO_VO', 'def') account = request.environ.get('HTTP_X_RUCIO_ACCOUNT') appid = request.environ.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = request.environ.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = request.remote_addr try: result = get_ssh_challenge_token(account, appid, ip, vo=vo) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) return error, 500 if not result: return generate_http_error_flask( 401, 'CannotAuthenticate', 'Cannot generate challenge for account %(account)s' % locals()) response.headers['X-Rucio-Auth-Token'] = result.token response.headers['X-Rucio-Auth-Token-Expires'] = date_to_str( result.expired_at) return response
def get(self): """ Authenticate a Rucio account temporarily via username and password. .. :quickref: UserPass; Authenticate with username/password :reqheader X-Rucio-VO: VO name as a string (Multi-VO Only) :reqheader X-Rucio-Account: Account identifier as a string. :reqheader X-Rucio-Username: Username as a string. :reqheader X-Rucio-Password: password as a text-plain string. :reqheader X-Rucio-AppID: Application identifier as a string. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ response = Response() response.headers['Access-Control-Allow-Origin'] = request.environ.get( 'HTTP_ORIGIN') response.headers['Access-Control-Allow-Headers'] = request.environ.get( 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS') response.headers['Access-Control-Allow-Methods'] = '*' response.headers['Access-Control-Allow-Credentials'] = 'true' response.headers[ 'Access-Control-Expose-Headers'] = 'X-Rucio-Auth-Token' response.headers['Content-Type'] = 'application/octet-stream' response.headers[ 'Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' response.headers['Cache-Control'] = 'post-check=0, pre-check=0' response.headers['Pragma'] = 'no-cache' vo = request.environ.get('HTTP_X_RUCIO_VO', 'def') account = request.environ.get('HTTP_X_RUCIO_ACCOUNT') username = request.environ.get('HTTP_X_RUCIO_USERNAME') password = request.environ.get('HTTP_X_RUCIO_PASSWORD') appid = request.environ.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = request.environ.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = request.remote_addr print(account, username, password, appid) try: result = get_auth_token_user_pass(account, username, password, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) return error, 500 if not result: return generate_http_error_flask( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) response.headers['X-Rucio-Auth-Token'] = result.token response.headers['X-Rucio-Auth-Token-Expires'] = date_to_str( result.expired_at) return response
def GET(self): """ HTTP Success: 200 OK HTTP Error: 401 Unauthorized :param Rucio-VO: VO name as a string (Multi-VO only). :param Rucio-Account: Account identifier as a string. :param Rucio-AppID: Application identifier as a string. :param SSLStdEnv: Apache mod_ssl SSL Standard Env Variables. :returns: "Rucio-Auth-Token" as a variable-length string header. """ header('Access-Control-Allow-Origin', ctx.env.get('HTTP_ORIGIN')) header('Access-Control-Allow-Headers', ctx.env.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) header('Access-Control-Allow-Methods', '*') header('Access-Control-Allow-Credentials', 'true') header('Access-Control-Expose-Headers', 'X-Rucio-Auth-Token') header('Content-Type', 'application/octet-stream') header('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') header('Cache-Control', 'post-check=0, pre-check=0', False) header('Pragma', 'no-cache') vo = ctx.env.get('HTTP_X_RUCIO_VO', 'def') account = ctx.env.get('HTTP_X_RUCIO_ACCOUNT') dn = ctx.env.get('SSL_CLIENT_S_DN') if not dn: raise generate_http_error(401, 'CannotAuthenticate', 'Cannot get DN') if not dn.startswith('/'): dn = '/%s' % '/'.join(dn.split(',')[::-1]) appid = ctx.env.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = ctx.env.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = ctx.ip # If we get a valid proxy certificate we have to strip this postfix, # otherwise we would have to store the proxy DN in the database as well. # Alternative: use the SSL_CLIENT_I_DN, but that would require a separate # endpoint as you cannot programmatically decide, by examining the SSL variables, # if you got a proxy or regular certificate while True: if dn.endswith('/CN=limited proxy'): dn = dn[:-17] elif dn.endswith('/CN=proxy'): dn = dn[:-9] elif search('/CN=[0-9]*$', dn): dn = dn.rpartition('/')[0] else: break try: result = get_auth_token_x509(account, dn, appid, ip, vo=vo) except AccessDenied: print('Cannot Authenticate', account, dn, appid, ip, vo) raise generate_http_error( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) except IdentityError: print('Cannot Authenticate', account, dn, appid, ip, vo) raise generate_http_error( 401, 'CannotAuthenticate', 'No default account set for %(dn)s' % locals()) if not result: print('Cannot Authenticate', account, dn, appid, ip, vo) raise generate_http_error( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) header('X-Rucio-Auth-Token', result.token) header('X-Rucio-Auth-Token-Expires', date_to_str(result.expired_at)) return str()
def GET(self): """ HTTP Success: 200 OK HTTP Error: 401 Unauthorized :param Rucio-VO: VO name as a string (Multi-VO only) :param Rucio-Account: Account identifier as a string. :param Rucio-Username: Username as a string. :param Rucio-Password: Password as a string. :param Rucio-AppID: Application identifier as a string. :returns: "X-Rucio-SAML-Auth-URL" as a variable-length string header. """ header('Access-Control-Allow-Origin', ctx.env.get('HTTP_ORIGIN')) header('Access-Control-Allow-Headers', ctx.env.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')) header('Access-Control-Allow-Methods', '*') header('Access-Control-Allow-Credentials', 'true') header('Access-Control-Expose-Headers', 'X-Rucio-Auth-Token') header('Content-Type', 'application/octet-stream') header('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') header('Cache-Control', 'post-check=0, pre-check=0', False) header('Pragma', 'no-cache') if not EXTRA_MODULES['onelogin']: header('X-Rucio-Auth-Token', None) return "SAML not configured on the server side." saml_nameid = cookies().get('saml-nameid') vo = ctx.env.get('HTTP_X_RUCIO_VO', 'def') account = ctx.env.get('HTTP_X_RUCIO_ACCOUNT') appid = ctx.env.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = ctx.env.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = ctx.ip if saml_nameid: try: result = get_auth_token_saml(account, saml_nameid, appid, ip, vo=vo) except AccessDenied: raise generate_http_error( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) except RucioException as error: raise generate_http_error(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) raise InternalError(error) if not result: raise generate_http_error( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) header('X-Rucio-Auth-Token', result.token) header('X-Rucio-Auth-Token-Expires', date_to_str(result.expired_at)) return str() # Path to the SAML config folder SAML_PATH = config_get('saml', 'config_path') request = ctx.env data = dict(param_input()) req = prepare_saml_request(request, data) auth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH) header('X-Rucio-SAML-Auth-URL', auth.login()) return str()
def get(self): """ .. :quickref: OIDC; :status 200: OK :status 401: Unauthorized :resheader X-Rucio-Auth-Token: The authentication token :resheader X-Rucio-Auth-Token-Expires: The time when the token expires """ headers = self.get_headers() headers.set('Content-Type', 'application/octet-stream') headers.set('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate') headers.add('Cache-Control', 'post-check=0, pre-check=0') headers.set('Pragma', 'no-cache') query_string = request.query_string.decode(encoding='utf-8') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) try: result = get_token_oidc(query_string, ip) except AccessDenied: return generate_http_error_flask(401, CannotAuthorize.__name__, 'Cannot authorize token request.', headers=headers) if not result: return generate_http_error_flask(401, CannotAuthorize.__name__, 'Cannot authorize token request.', headers=headers) if 'token' in result and 'webhome' not in result: headers.set('X-Rucio-Auth-Token', result['token']['token']) headers.set('X-Rucio-Auth-Token-Expires', date_to_str(result['token']['expires_at'])) return '', 200, headers elif 'webhome' in result: webhome = result['webhome'] if webhome is None: headers.extend( error_headers( CannotAuthenticate.__name__, 'Cannot find your OIDC identity linked to any Rucio account' )) headers.set('Content-Type', 'text/html') return render_template( 'auth_crash.html', crashtype='unknown_identity'), 401, headers # domain setting is necessary so that the token gets distributed also to the webui server domain = '.'.join(urlparse(webhome).netloc.split('.')[1:]) response = redirect(webhome, code=303) response.headers.extend(headers) response.set_cookie('x-rucio-auth-token', value=result['token']['token'], domain=domain, path='/') response.set_cookie('rucio-auth-token-created-at', value=str(time.time()), domain=domain, path='/') return response else: return '', 400, headers
def get(self): """ Authenticate a Rucio account temporarily via SSH key exchange. .. :quickref: SSH; Authenticate with SSH key exchange. :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-SSH-Signature: Response to server challenge signed with SSH private key as a base64 encoded string. :reqheader Rucio-AppID: Application identifier as a string. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ headers = self.get_headers() headers['Content-Type'] = 'application/octet-stream' headers[ 'Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' headers.add('Cache-Control', 'post-check=0, pre-check=0') headers['Pragma'] = 'no-cache' vo = request.headers.get('X-Rucio-VO', default='def') account = request.headers.get('X-Rucio-Account', default=None) signature = request.headers.get('X-Rucio-SSH-Signature', default=None) appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) # decode the signature which must come in base64 encoded try: signature = base64.b64decode(signature) except TypeError: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg= f'Cannot authenticate to account {account} with malformed signature', headers=headers) try: result = get_auth_token_ssh(account, signature, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg= f'Cannot authenticate to account {account} with given credentials', headers=headers) if not result: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg= f'Cannot authenticate to account {account} with given credentials', headers=headers) headers['X-Rucio-Auth-Token'] = result.token headers['X-Rucio-Auth-Token-Expires'] = date_to_str(result.expired_at) return '', 200, headers
def get(self): """ Authenticate a Rucio account temporarily via an x509 certificate. .. :quickref: x509; Authenticate with x509 certificate. :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-AppID: Application identifier as a string. :reqheader SSLStdEnv: Apache mod_ssl SSL Standard Env Variables. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ headers = self.get_headers() headers['Content-Type'] = 'application/octet-stream' headers[ 'Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' headers.add('Cache-Control', 'post-check=0, pre-check=0') headers['Pragma'] = 'no-cache' vo = request.headers.get('X-Rucio-VO', default='def') account = request.headers.get('X-Rucio-Account', default=None) dn = request.environ.get('SSL_CLIENT_S_DN') if not dn: return generate_http_error_flask(401, CannotAuthenticate.__name__, 'Cannot get DN', headers=headers) if not dn.startswith('/'): dn = '/' + '/'.join(dn.split(',')[::-1]) appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) # If we get a valid proxy certificate we have to strip this postfix, # otherwise we would have to store the proxy DN in the database as well. # Alternative: use the SSL_CLIENT_I_DN, but that would require a separate # endpoint as you cannot programmatically decide, by examining the SSL variables, # if you got a proxy or regular certificate while True: if dn.endswith('/CN=limited proxy'): dn = dn[:-17] elif dn.endswith('/CN=proxy'): dn = dn[:-9] elif search('/CN=[0-9]*$', dn): dn = dn.rpartition('/')[0] else: break try: result = get_auth_token_x509(account, dn, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg= f'Cannot authenticate to account {account} with given credentials', headers=headers) except IdentityError: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg=f'No default account set for {dn}', headers=headers) if not result: return generate_http_error_flask( status_code=401, exc=CannotAuthenticate.__name__, exc_msg= f'Cannot authenticate to account {account} with given credentials', headers=headers) headers['X-Rucio-Auth-Token'] = result.token headers['X-Rucio-Auth-Token-Expires'] = date_to_str(result.expired_at) return '', 200, headers
def get(self): """ Authenticate a Rucio account temporarily via username and password. .. :quickref: UserPass; Authenticate with username/password :reqheader X-Rucio-VO: VO name as a string (Multi-VO Only) :reqheader X-Rucio-Account: Account identifier as a string. :reqheader X-Rucio-Username: Username as a string. :reqheader X-Rucio-Password: password as a text-plain string. :reqheader X-Rucio-AppID: Application identifier as a string. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ headers = self.get_headers() headers['Content-Type'] = 'application/octet-stream' headers[ 'Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' headers.add('Cache-Control', 'post-check=0, pre-check=0') headers['Pragma'] = 'no-cache' vo = extract_vo(request.headers) account = request.headers.get('X-Rucio-Account', default=None) username = request.headers.get('X-Rucio-Username', default=None) password = request.headers.get('X-Rucio-Password', default=None) appid = request.headers.get('X-Rucio-AppID', default='unknown') ip = request.headers.get('X-Forwarded-For', default=request.remote_addr) if not account or not username or not password: return generate_http_error_flask( 401, CannotAuthenticate.__name__, 'Cannot authenticate without passing all required arguments', headers=headers) try: result = get_auth_token_user_pass(account, username, password, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask( 401, CannotAuthenticate.__name__, f'Cannot authenticate to account {account} with given credentials', headers=headers) if not result: return generate_http_error_flask( 401, CannotAuthenticate.__name__, f'Cannot authenticate to account {account} with given credentials', headers=headers) headers['X-Rucio-Auth-Token'] = result['token'] headers['X-Rucio-Auth-Token-Expires'] = date_to_str( result['expires_at']) return '', 200, headers
def get(self): """ Authenticate a Rucio account temporarily via SSH key exchange. .. :quickref: SSH; Authenticate with SSH key exchange. :reqheader Rucio-VO: VO name as a string (Multi-VO only). :reqheader Rucio-Account: Account identifier as a string. :reqheader Rucio-SSH-Signature: Response to server challenge signed with SSH private key as a base64 encoded string. :reqheader Rucio-AppID: Application identifier as a string. :resheader Access-Control-Allow-Origin: :resheader Access-Control-Allow-Headers: :resheader Access-Control-Allow-Methods: :resheader Access-Control-Allow-Credentials: :resheader Access-Control-Expose-Headers: :resheader X-Rucio-Auth-Token: The authentication token :status 200: Successfully authenticated :status 404: Invalid credentials """ response = Response() response.headers['Access-Control-Allow-Origin'] = request.environ.get( 'HTTP_ORIGIN') response.headers['Access-Control-Allow-Headers'] = request.environ.get( 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS') response.headers['Access-Control-Allow-Methods'] = '*' response.headers['Access-Control-Allow-Credentials'] = 'true' response.headers[ 'Access-Control-Expose-Headers'] = 'X-Rucio-Auth-Token' response.headers['Content-Type'] = 'application/octet-stream' response.headers[ 'Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate' response.headers['Cache-Control'] = 'post-check=0, pre-check=0' response.headers['Pragma'] = 'no-cache' vo = request.environ.get('HTTP_X_RUCIO_VO', 'def') account = request.environ.get('HTTP_X_RUCIO_ACCOUNT') signature = request.environ.get('HTTP_X_RUCIO_SSH_SIGNATURE') appid = request.environ.get('HTTP_X_RUCIO_APPID') if appid is None: appid = 'unknown' ip = request.environ.get('HTTP_X_FORWARDED_FOR') if ip is None: ip = request.remote_addr # decode the signature which must come in base64 encoded try: signature = base64.b64decode(signature) except Exception as error: # noqa: F841 return generate_http_error_flask( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with malformed signature' % locals()) try: result = get_auth_token_ssh(account, signature, appid, ip, vo=vo) except AccessDenied: return generate_http_error_flask( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) except RucioException as error: return generate_http_error_flask(500, error.__class__.__name__, error.args[0]) except Exception as error: print(format_exc()) return error, 500 if not result: return generate_http_error_flask( 401, 'CannotAuthenticate', 'Cannot authenticate to account %(account)s with given credentials' % locals()) response.headers['X-Rucio-Auth-Token'] = result.token response.headers['X-Rucio-Auth-Token-Expires'] = date_to_str( result.expired_at) return response