Skip to content

Commit

Permalink
Deletion/Transfers: Make token support WebDAV-only #6412
Browse files Browse the repository at this point in the history
There are some requirements in XRootD that might make token support more
complex. It was agreed to focus on WebDAV for now and review XRootD
after the Data Challenge 2024.

This commits also applies a stronger restriction to the content of the
`oidc_support` RSE attribute.
  • Loading branch information
dchristidis authored and bari12 committed Dec 18, 2023
1 parent ce3e464 commit 76cfecf
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 24 deletions.
11 changes: 5 additions & 6 deletions lib/rucio/core/rse.py
Expand Up @@ -17,7 +17,7 @@
from collections.abc import Iterator, Iterable
from datetime import datetime
from io import StringIO
from re import match, sub
from re import match
from typing import Any, Generic, Optional, TypeVar, Union, TYPE_CHECKING

import sqlalchemy
Expand Down Expand Up @@ -1857,7 +1857,7 @@ def determine_audience_for_rse(rse_id: str) -> str:
# that the protocol hostname be sufficient, but this may not come to pass.
filtered_hostnames = {p['hostname']
for p in rse_protocols['protocols']
if p['scheme'] in ('davs', 'root')}
if p['scheme'] == 'davs'}
return ' '.join(sorted(filtered_hostnames))


Expand All @@ -1872,15 +1872,14 @@ def determine_scope_for_rse(
rse_protocols = get_rse_protocols(rse_id)
filtered_prefixes = set()
for protocol in rse_protocols['protocols']:
# Skip protocol schemes which do not support tokens.
if protocol['scheme'] not in ('davs', 'root'):
# Token support is exclusive to WebDAV.
if protocol['scheme'] != 'davs':
continue
# Squeeze leading double slashes, typically found in XRootD protocols.
prefix = sub('^//', '/', protocol['prefix'])
# Remove base path from prefix. Storages typically map an issuer (i.e.
# a VO) to a particular area. If so, then the path to that area acts as
# a base which should be removed from the prefix (in order for '/' to
# mean the entire resource associated with that issuer).
prefix = protocol['prefix']
if base_path := get_rse_attribute(rse_id, 'oidc_base_path'):
prefix = prefix.removeprefix(base_path)
filtered_prefixes.add(prefix)
Expand Down
13 changes: 13 additions & 0 deletions lib/rucio/core/transfer.py
Expand Up @@ -167,6 +167,19 @@ def use_ipv4(self):
return self.dst.rse.attributes.get('use_ipv4', False) or any(src.rse.attributes.get('use_ipv4', False)
for src in self.sources)

@property
def use_tokens(self) -> bool:
"""Whether a transfer can be performed with tokens.
In order to be so, all the involved RSEs must have it explicitly enabled
and the protocol being used must be WebDAV.
"""
for endpoint in [*self.sources, self.destination]:
if (endpoint.rse.attributes.get('oidc_support') is not True
or endpoint.scheme != 'davs'):
return False
return True

@staticmethod
def __rewrite_source_url(source_url, source_sign_url, dest_sign_url, source_scheme):
"""
Expand Down
2 changes: 1 addition & 1 deletion lib/rucio/daemons/reaper/reaper.py
Expand Up @@ -580,7 +580,7 @@ def _run_once(rses_to_process, chunk_size, greedy, scheme,
try:
rse.ensure_loaded(load_info=True, load_attributes=True)
auth_token = None
if rse.attributes.get('oidc_support', False):
if rse.attributes.get('oidc_support') is True and scheme == 'davs':
audience = config_get('reaper', 'oidc_audience', False) or determine_audience_for_rse(rse.id)
# FIXME: At the time of writing, StoRM requires `storage.read`
# in order to perform a stat operation.
Expand Down
18 changes: 1 addition & 17 deletions lib/rucio/transfertool/fts3.py
Expand Up @@ -196,22 +196,6 @@ def _configured_source_strategy(activity: str, logger: Callable[..., Any]) -> st
return activity_source_strategy.get(str(activity), default_source_strategy)


def oidc_supported(transfer_hop) -> bool:
"""
checking OIDC AuthN/Z support per destination and source RSEs;
for oidc_support to be activated, all sources and the destination must explicitly support it
"""
# assumes use of boolean 'oidc_support' RSE attribute
if not transfer_hop.dst.rse.attributes.get('oidc_support', False):
return False

for source in transfer_hop.sources:
if not source.rse.attributes.get('oidc_support', False):
return False
return True


def _available_checksums(
transfer: "DirectTransferDefinition",
) -> tuple[set[str], set[str]]:
Expand Down Expand Up @@ -885,7 +869,7 @@ def submission_builder_for_path(cls, transfer_path, logger=logging.log):

if sub_path:
oidc_support = False
if all(oidc_supported(t) for t in sub_path):
if all(t.use_tokens for t in sub_path):
logger(logging.DEBUG, 'OAuth2/OIDC available for transfer {}'.format([str(hop) for hop in sub_path]))
oidc_support = True
return sub_path, TransferToolBuilder(cls, external_host=fts_hosts[0], oidc_support=oidc_support, vo=vo)
Expand Down

0 comments on commit 76cfecf

Please sign in to comment.