rucio 35.7.0__py3-none-any.whl → 37.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rucio might be problematic. Click here for more details.
- rucio/alembicrevision.py +1 -1
- rucio/{daemons/c3po/collectors → cli}/__init__.py +1 -0
- rucio/cli/account.py +216 -0
- rucio-35.7.0.data/scripts/rucio → rucio/cli/bin_legacy/rucio.py +769 -486
- rucio-35.7.0.data/scripts/rucio-admin → rucio/cli/bin_legacy/rucio_admin.py +476 -423
- rucio/cli/command.py +272 -0
- rucio/cli/config.py +72 -0
- rucio/cli/did.py +191 -0
- rucio/cli/download.py +128 -0
- rucio/cli/lifetime_exception.py +33 -0
- rucio/cli/replica.py +162 -0
- rucio/cli/rse.py +293 -0
- rucio/cli/rule.py +158 -0
- rucio/cli/scope.py +40 -0
- rucio/cli/subscription.py +73 -0
- rucio/cli/upload.py +60 -0
- rucio/cli/utils.py +226 -0
- rucio/client/accountclient.py +0 -1
- rucio/client/baseclient.py +33 -24
- rucio/client/client.py +45 -1
- rucio/client/didclient.py +5 -3
- rucio/client/downloadclient.py +6 -8
- rucio/client/replicaclient.py +0 -2
- rucio/client/richclient.py +317 -0
- rucio/client/rseclient.py +4 -4
- rucio/client/uploadclient.py +26 -12
- rucio/common/bittorrent.py +234 -0
- rucio/common/cache.py +66 -29
- rucio/common/checksum.py +168 -0
- rucio/common/client.py +122 -0
- rucio/common/config.py +22 -35
- rucio/common/constants.py +61 -3
- rucio/common/didtype.py +72 -24
- rucio/common/dumper/__init__.py +45 -38
- rucio/common/dumper/consistency.py +75 -30
- rucio/common/dumper/data_models.py +63 -19
- rucio/common/dumper/path_parsing.py +19 -8
- rucio/common/exception.py +65 -8
- rucio/common/extra.py +5 -10
- rucio/common/logging.py +13 -13
- rucio/common/pcache.py +8 -7
- rucio/common/plugins.py +59 -27
- rucio/common/policy.py +12 -3
- rucio/common/schema/__init__.py +84 -34
- rucio/common/schema/generic.py +0 -17
- rucio/common/schema/generic_multi_vo.py +0 -17
- rucio/common/test_rucio_server.py +12 -6
- rucio/common/types.py +132 -52
- rucio/common/utils.py +93 -643
- rucio/core/account_limit.py +14 -12
- rucio/core/authentication.py +2 -2
- rucio/core/config.py +23 -42
- rucio/core/credential.py +14 -15
- rucio/core/did.py +5 -1
- rucio/core/did_meta_plugins/elasticsearch_meta.py +407 -0
- rucio/core/did_meta_plugins/filter_engine.py +62 -3
- rucio/core/did_meta_plugins/json_meta.py +2 -2
- rucio/core/did_meta_plugins/mongo_meta.py +43 -30
- rucio/core/did_meta_plugins/postgres_meta.py +75 -39
- rucio/core/identity.py +6 -5
- rucio/core/importer.py +4 -3
- rucio/core/lifetime_exception.py +2 -2
- rucio/core/lock.py +8 -7
- rucio/core/message.py +6 -0
- rucio/core/monitor.py +30 -29
- rucio/core/naming_convention.py +2 -2
- rucio/core/nongrid_trace.py +2 -2
- rucio/core/oidc.py +11 -9
- rucio/core/permission/__init__.py +79 -37
- rucio/core/permission/generic.py +1 -7
- rucio/core/permission/generic_multi_vo.py +1 -7
- rucio/core/quarantined_replica.py +4 -3
- rucio/core/replica.py +464 -139
- rucio/core/replica_sorter.py +55 -59
- rucio/core/request.py +34 -32
- rucio/core/rse.py +301 -97
- rucio/core/rse_counter.py +1 -2
- rucio/core/rse_expression_parser.py +7 -7
- rucio/core/rse_selector.py +9 -7
- rucio/core/rule.py +41 -40
- rucio/core/rule_grouping.py +42 -40
- rucio/core/scope.py +5 -4
- rucio/core/subscription.py +26 -28
- rucio/core/topology.py +11 -11
- rucio/core/trace.py +2 -2
- rucio/core/transfer.py +29 -15
- rucio/core/volatile_replica.py +4 -3
- rucio/daemons/atropos/atropos.py +1 -1
- rucio/daemons/auditor/__init__.py +2 -2
- rucio/daemons/auditor/srmdumps.py +6 -6
- rucio/daemons/automatix/automatix.py +32 -21
- rucio/daemons/badreplicas/necromancer.py +2 -2
- rucio/daemons/bb8/nuclei_background_rebalance.py +1 -1
- rucio/daemons/bb8/t2_background_rebalance.py +1 -1
- rucio/daemons/common.py +15 -25
- rucio/daemons/conveyor/finisher.py +2 -2
- rucio/daemons/conveyor/poller.py +18 -28
- rucio/daemons/conveyor/receiver.py +2 -2
- rucio/daemons/conveyor/stager.py +1 -0
- rucio/daemons/conveyor/submitter.py +3 -3
- rucio/daemons/hermes/hermes.py +91 -30
- rucio/daemons/judge/evaluator.py +2 -2
- rucio/daemons/oauthmanager/oauthmanager.py +3 -3
- rucio/daemons/reaper/dark_reaper.py +7 -3
- rucio/daemons/reaper/reaper.py +12 -16
- rucio/daemons/rsedecommissioner/config.py +1 -1
- rucio/daemons/rsedecommissioner/profiles/generic.py +5 -4
- rucio/daemons/rsedecommissioner/profiles/types.py +7 -6
- rucio/daemons/rsedecommissioner/rse_decommissioner.py +1 -1
- rucio/daemons/storage/consistency/actions.py +8 -6
- rucio/daemons/tracer/kronos.py +4 -4
- rucio/db/sqla/constants.py +5 -0
- rucio/db/sqla/migrate_repo/versions/1677d4d803c8_split_rse_availability_into_multiple.py +4 -4
- rucio/db/sqla/migrate_repo/versions/30d5206e9cad_increase_oauthrequest_redirect_msg_.py +37 -0
- rucio/db/sqla/models.py +157 -154
- rucio/db/sqla/session.py +58 -27
- rucio/db/sqla/types.py +2 -2
- rucio/db/sqla/util.py +2 -2
- rucio/gateway/account.py +18 -12
- rucio/gateway/account_limit.py +137 -60
- rucio/gateway/authentication.py +18 -12
- rucio/gateway/config.py +30 -20
- rucio/gateway/credential.py +9 -10
- rucio/gateway/did.py +70 -53
- rucio/gateway/dirac.py +6 -4
- rucio/gateway/exporter.py +3 -2
- rucio/gateway/heartbeat.py +6 -4
- rucio/gateway/identity.py +36 -51
- rucio/gateway/importer.py +3 -2
- rucio/gateway/lifetime_exception.py +3 -2
- rucio/gateway/meta_conventions.py +17 -6
- rucio/gateway/permission.py +4 -1
- rucio/gateway/quarantined_replica.py +3 -2
- rucio/gateway/replica.py +31 -22
- rucio/gateway/request.py +27 -18
- rucio/gateway/rse.py +69 -37
- rucio/gateway/rule.py +46 -26
- rucio/gateway/scope.py +3 -2
- rucio/gateway/subscription.py +14 -11
- rucio/gateway/vo.py +12 -8
- rucio/rse/__init__.py +3 -3
- rucio/rse/protocols/bittorrent.py +11 -1
- rucio/rse/protocols/cache.py +0 -11
- rucio/rse/protocols/dummy.py +0 -11
- rucio/rse/protocols/gfal.py +14 -9
- rucio/rse/protocols/globus.py +1 -1
- rucio/rse/protocols/http_cache.py +1 -1
- rucio/rse/protocols/posix.py +2 -2
- rucio/rse/protocols/protocol.py +84 -317
- rucio/rse/protocols/rclone.py +2 -1
- rucio/rse/protocols/rfio.py +10 -1
- rucio/rse/protocols/ssh.py +2 -1
- rucio/rse/protocols/storm.py +2 -13
- rucio/rse/protocols/webdav.py +74 -30
- rucio/rse/protocols/xrootd.py +2 -1
- rucio/rse/rsemanager.py +170 -53
- rucio/rse/translation.py +260 -0
- rucio/tests/common.py +23 -13
- rucio/tests/common_server.py +26 -9
- rucio/transfertool/bittorrent.py +15 -14
- rucio/transfertool/bittorrent_driver.py +5 -7
- rucio/transfertool/bittorrent_driver_qbittorrent.py +9 -8
- rucio/transfertool/fts3.py +20 -16
- rucio/transfertool/mock.py +2 -3
- rucio/vcsversion.py +4 -4
- rucio/version.py +7 -0
- rucio/web/rest/flaskapi/v1/accounts.py +17 -3
- rucio/web/rest/flaskapi/v1/auth.py +5 -5
- rucio/web/rest/flaskapi/v1/credentials.py +3 -2
- rucio/web/rest/flaskapi/v1/dids.py +21 -15
- rucio/web/rest/flaskapi/v1/identities.py +33 -9
- rucio/web/rest/flaskapi/v1/redirect.py +5 -4
- rucio/web/rest/flaskapi/v1/replicas.py +12 -8
- rucio/web/rest/flaskapi/v1/rses.py +15 -4
- rucio/web/rest/flaskapi/v1/traces.py +56 -19
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic.ini.template +1 -1
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/alembic_offline.ini.template +1 -1
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.atlas.client.template +3 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio.cfg.template +3 -19
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rucio_multi_vo.cfg.template +1 -18
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/requirements.server.txt +97 -68
- rucio-37.0.0.data/scripts/rucio +133 -0
- rucio-37.0.0.data/scripts/rucio-admin +97 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-atropos +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-auditor +2 -1
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-automatix +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-client +17 -10
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-receiver +1 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-kronos +1 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-minos-temporary-expiration +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-necromancer +2 -2
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-reaper +6 -6
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-transmogrifier +2 -2
- rucio-37.0.0.dist-info/METADATA +92 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/RECORD +237 -243
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/licenses/AUTHORS.rst +3 -0
- rucio/common/schema/atlas.py +0 -413
- rucio/common/schema/belleii.py +0 -408
- rucio/common/schema/domatpc.py +0 -401
- rucio/common/schema/escape.py +0 -426
- rucio/common/schema/icecube.py +0 -406
- rucio/core/permission/atlas.py +0 -1348
- rucio/core/permission/belleii.py +0 -1077
- rucio/core/permission/escape.py +0 -1078
- rucio/daemons/c3po/algorithms/__init__.py +0 -13
- rucio/daemons/c3po/algorithms/simple.py +0 -134
- rucio/daemons/c3po/algorithms/t2_free_space.py +0 -128
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop.py +0 -130
- rucio/daemons/c3po/algorithms/t2_free_space_only_pop_with_network.py +0 -294
- rucio/daemons/c3po/c3po.py +0 -371
- rucio/daemons/c3po/collectors/agis.py +0 -108
- rucio/daemons/c3po/collectors/free_space.py +0 -81
- rucio/daemons/c3po/collectors/jedi_did.py +0 -57
- rucio/daemons/c3po/collectors/mock_did.py +0 -51
- rucio/daemons/c3po/collectors/network_metrics.py +0 -71
- rucio/daemons/c3po/collectors/workload.py +0 -112
- rucio/daemons/c3po/utils/__init__.py +0 -13
- rucio/daemons/c3po/utils/dataset_cache.py +0 -50
- rucio/daemons/c3po/utils/expiring_dataset_cache.py +0 -56
- rucio/daemons/c3po/utils/expiring_list.py +0 -62
- rucio/daemons/c3po/utils/popularity.py +0 -85
- rucio/daemons/c3po/utils/timeseries.py +0 -89
- rucio/rse/protocols/gsiftp.py +0 -92
- rucio-35.7.0.data/scripts/rucio-c3po +0 -85
- rucio-35.7.0.dist-info/METADATA +0 -72
- /rucio/{daemons/c3po → cli/bin_legacy}/__init__.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/globus-config.yml.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/ldap.cfg.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approval_request.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_admin.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_approved_user.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_admin.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_denied_user.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/mail_templates/rule_ok_notification.tmpl +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/etc/rse-accounts.cfg.template +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/bootstrap.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/merge_rucio_configs.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/data/rucio/tools/reset_database.py +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-account +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-collection-replica +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-abacus-rse +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-bb8 +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-cache-consumer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-finisher +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-poller +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-preparer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-stager +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-submitter +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-conveyor-throttler +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dark-reaper +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-dumper +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-follower +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-hermes +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-cleaner +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-evaluator +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-injector +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-judge-repairer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-oauth-manager +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-replica-recoverer +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-rse-decommissioner +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-storage-consistency-actions +0 -0
- {rucio-35.7.0.data → rucio-37.0.0.data}/scripts/rucio-undertaker +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/WHEEL +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/licenses/LICENSE +0 -0
- {rucio-35.7.0.dist-info → rucio-37.0.0.dist-info}/top_level.txt +0 -0
rucio/gateway/exporter.py
CHANGED
|
@@ -35,8 +35,9 @@ def export_data(issuer: str, distance: bool = True, vo: str = 'def', *, session:
|
|
|
35
35
|
:param session: The database session in use.
|
|
36
36
|
"""
|
|
37
37
|
kwargs = {'issuer': issuer}
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='export', kwargs=kwargs, session=session)
|
|
39
|
+
if not auth_result.allowed:
|
|
40
|
+
raise exception.AccessDenied('Account %s can not export data. %s' % (issuer, auth_result.message))
|
|
40
41
|
|
|
41
42
|
data = exporter.export_data(distance=distance, vo=vo, session=session)
|
|
42
43
|
rses = {}
|
rucio/gateway/heartbeat.py
CHANGED
|
@@ -37,8 +37,9 @@ def list_heartbeats(issuer: Optional[str] = None, vo: str = 'def', *, session: "
|
|
|
37
37
|
"""
|
|
38
38
|
|
|
39
39
|
kwargs = {'issuer': issuer}
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='list_heartbeats', kwargs=kwargs, session=session)
|
|
41
|
+
if not auth_result.allowed:
|
|
42
|
+
raise exception.AccessDenied('%s cannot list heartbeats. %s' % (issuer, auth_result.message))
|
|
42
43
|
return heartbeat.list_heartbeats(session=session)
|
|
43
44
|
|
|
44
45
|
|
|
@@ -69,6 +70,7 @@ def create_heartbeat(
|
|
|
69
70
|
|
|
70
71
|
"""
|
|
71
72
|
kwargs = {'issuer': issuer}
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='send_heartbeats', kwargs=kwargs, session=session)
|
|
74
|
+
if not auth_result.allowed:
|
|
75
|
+
raise exception.AccessDenied('%s cannot send heartbeats. %s' % (issuer, auth_result.message))
|
|
74
76
|
heartbeat.live(executable=executable, hostname=hostname, pid=pid, thread=thread, older_than=older_than, payload=payload, session=session)
|
rucio/gateway/identity.py
CHANGED
|
@@ -21,25 +21,21 @@ from typing import TYPE_CHECKING, Optional
|
|
|
21
21
|
from rucio.common import exception
|
|
22
22
|
from rucio.common.types import InternalAccount
|
|
23
23
|
from rucio.core import identity
|
|
24
|
-
from rucio.db.sqla.constants import IdentityType
|
|
25
|
-
from rucio.db.sqla.session import
|
|
24
|
+
from rucio.db.sqla.constants import DatabaseOperationType, IdentityType
|
|
25
|
+
from rucio.db.sqla.session import db_session
|
|
26
26
|
from rucio.gateway import permission
|
|
27
27
|
|
|
28
28
|
if TYPE_CHECKING:
|
|
29
29
|
from collections.abc import Sequence
|
|
30
30
|
|
|
31
31
|
from sqlalchemy import Row
|
|
32
|
-
from sqlalchemy.orm import Session
|
|
33
32
|
|
|
34
33
|
|
|
35
|
-
@transactional_session
|
|
36
34
|
def add_identity(
|
|
37
35
|
identity_key: str,
|
|
38
36
|
id_type: str,
|
|
39
37
|
email: str,
|
|
40
38
|
password: Optional[str] = None,
|
|
41
|
-
*,
|
|
42
|
-
session: "Session"
|
|
43
39
|
) -> None:
|
|
44
40
|
"""
|
|
45
41
|
Creates a user identity.
|
|
@@ -48,19 +44,16 @@ def add_identity(
|
|
|
48
44
|
:param id_type: The type of the authentication (x509, gss, userpass, ssh, saml)
|
|
49
45
|
:param email: The Email address associated with the identity.
|
|
50
46
|
:param password: If type==userpass, this sets the password.
|
|
51
|
-
:param session: The database session in use.
|
|
52
47
|
"""
|
|
53
|
-
|
|
48
|
+
with db_session(DatabaseOperationType.WRITE) as session:
|
|
49
|
+
return identity.add_identity(identity_key, IdentityType[id_type.upper()], email, password=password, session=session)
|
|
54
50
|
|
|
55
51
|
|
|
56
|
-
@transactional_session
|
|
57
52
|
def del_identity(
|
|
58
53
|
identity_key: str,
|
|
59
54
|
id_type: str,
|
|
60
55
|
issuer: str,
|
|
61
56
|
vo: str = 'def',
|
|
62
|
-
*,
|
|
63
|
-
session: "Session"
|
|
64
57
|
) -> None:
|
|
65
58
|
"""
|
|
66
59
|
Deletes a user identity.
|
|
@@ -68,17 +61,18 @@ def del_identity(
|
|
|
68
61
|
:param id_type: The type of the authentication (x509, gss, userpass, ssh, saml).
|
|
69
62
|
:param issuer: The issuer account.
|
|
70
63
|
:param vo: the VO of the issuer.
|
|
71
|
-
:param session: The database session in use.
|
|
72
64
|
"""
|
|
73
65
|
converted_id_type = IdentityType[id_type.upper()]
|
|
74
|
-
kwargs = {'accounts': identity.list_accounts_for_identity(identity_key, converted_id_type, session=session)}
|
|
75
|
-
if not permission.has_permission(issuer=issuer, vo=vo, action='del_identity', kwargs=kwargs, session=session):
|
|
76
|
-
raise exception.AccessDenied('Account %s can not delete identity' % (issuer))
|
|
77
66
|
|
|
78
|
-
|
|
67
|
+
with db_session(DatabaseOperationType.WRITE) as session:
|
|
68
|
+
kwargs = {'accounts': identity.list_accounts_for_identity(identity_key, converted_id_type, session=session)}
|
|
69
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='del_identity', kwargs=kwargs, session=session)
|
|
70
|
+
if not auth_result.allowed:
|
|
71
|
+
raise exception.AccessDenied('Account %s can not delete identity. %s' % (issuer, auth_result.message))
|
|
72
|
+
|
|
73
|
+
return identity.del_identity(identity_key, converted_id_type, session=session)
|
|
79
74
|
|
|
80
75
|
|
|
81
|
-
@transactional_session
|
|
82
76
|
def add_account_identity(
|
|
83
77
|
identity_key: str,
|
|
84
78
|
id_type: str,
|
|
@@ -88,8 +82,6 @@ def add_account_identity(
|
|
|
88
82
|
default: bool = False,
|
|
89
83
|
password: Optional[str] = None,
|
|
90
84
|
vo: str = 'def',
|
|
91
|
-
*,
|
|
92
|
-
session: "Session"
|
|
93
85
|
) -> None:
|
|
94
86
|
"""
|
|
95
87
|
Adds a membership association between identity and account.
|
|
@@ -102,39 +94,37 @@ def add_account_identity(
|
|
|
102
94
|
:param default: If True, the account should be used by default with the provided identity.
|
|
103
95
|
:param password: Password if id_type is userpass.
|
|
104
96
|
:param vo: the VO to act on.
|
|
105
|
-
:param session: The database session in use.
|
|
106
97
|
"""
|
|
107
98
|
kwargs = {'identity': identity_key, 'type': id_type, 'account': account}
|
|
108
|
-
if not permission.has_permission(issuer=issuer, vo=vo, action='add_account_identity', kwargs=kwargs, session=session):
|
|
109
|
-
raise exception.AccessDenied('Account %s can not add account identity' % (issuer))
|
|
110
99
|
|
|
111
|
-
|
|
100
|
+
with db_session(DatabaseOperationType.WRITE) as session:
|
|
101
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='add_account_identity', kwargs=kwargs, session=session)
|
|
102
|
+
if not auth_result.allowed:
|
|
103
|
+
raise exception.AccessDenied('Account %s can not add account identity. %s' % (issuer, auth_result.message))
|
|
104
|
+
|
|
105
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
112
106
|
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
return identity.add_account_identity(identity=identity_key, type_=IdentityType[id_type.upper()], default=default,
|
|
108
|
+
email=email, account=internal_account, password=password, session=session)
|
|
115
109
|
|
|
116
110
|
|
|
117
|
-
|
|
118
|
-
def verify_identity(identity_key: str, id_type: str, password: Optional[str] = None, *, session: "Session") -> bool:
|
|
111
|
+
def verify_identity(identity_key: str, id_type: str, password: Optional[str] = None) -> bool:
|
|
119
112
|
"""
|
|
120
113
|
Verifies a user identity.
|
|
121
114
|
:param identity_key: The identity key name. For example x509 DN, or a username.
|
|
122
115
|
:param id_type: The type of the authentication (x509, gss, userpass, ssh, saml)
|
|
123
116
|
:param password: If type==userpass, verifies the identity_key, .
|
|
124
|
-
:param session: The database session in use.
|
|
125
117
|
"""
|
|
126
|
-
|
|
118
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
119
|
+
return identity.verify_identity(identity_key, IdentityType[id_type.upper()], password=password, session=session)
|
|
127
120
|
|
|
128
121
|
|
|
129
|
-
@transactional_session
|
|
130
122
|
def del_account_identity(
|
|
131
123
|
identity_key: str,
|
|
132
124
|
id_type: str,
|
|
133
125
|
account: str,
|
|
134
126
|
issuer: str,
|
|
135
127
|
vo: str = 'def',
|
|
136
|
-
*,
|
|
137
|
-
session: "Session"
|
|
138
128
|
) -> None:
|
|
139
129
|
"""
|
|
140
130
|
Removes a membership association between identity and account.
|
|
@@ -144,61 +134,56 @@ def del_account_identity(
|
|
|
144
134
|
:param account: The account name.
|
|
145
135
|
:param issuer: The issuer account.
|
|
146
136
|
:param vo: the VO to act on.
|
|
147
|
-
:param session: The database session in use.
|
|
148
137
|
"""
|
|
149
138
|
kwargs = {'account': account}
|
|
150
|
-
if not permission.has_permission(issuer=issuer, vo=vo, action='del_account_identity', kwargs=kwargs, session=session):
|
|
151
|
-
raise exception.AccessDenied('Account %s can not delete account identity' % (issuer))
|
|
152
139
|
|
|
153
|
-
|
|
140
|
+
with db_session(DatabaseOperationType.WRITE) as session:
|
|
141
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='del_account_identity', kwargs=kwargs, session=session)
|
|
142
|
+
if not auth_result.allowed:
|
|
143
|
+
raise exception.AccessDenied('Account %s can not delete account identity. %s' % (issuer, auth_result.message))
|
|
144
|
+
|
|
145
|
+
internal_account = InternalAccount(account, vo=vo)
|
|
154
146
|
|
|
155
|
-
|
|
147
|
+
return identity.del_account_identity(identity_key, IdentityType[id_type.upper()], internal_account, session=session)
|
|
156
148
|
|
|
157
149
|
|
|
158
|
-
|
|
159
|
-
def list_identities(*, session: "Session", **kwargs) -> "Sequence[Row[tuple[str, IdentityType]]]":
|
|
150
|
+
def list_identities(**kwargs) -> "Sequence[Row[tuple[str, IdentityType]]]":
|
|
160
151
|
"""
|
|
161
152
|
Returns a list of all enabled identities.
|
|
162
153
|
|
|
163
|
-
:param session: The database session in use.
|
|
164
154
|
returns: A list of all enabled identities.
|
|
165
155
|
"""
|
|
166
|
-
|
|
156
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
157
|
+
return identity.list_identities(session=session, **kwargs)
|
|
167
158
|
|
|
168
159
|
|
|
169
|
-
@read_session
|
|
170
160
|
def get_default_account(
|
|
171
161
|
identity_key: str,
|
|
172
162
|
id_type: str,
|
|
173
|
-
*,
|
|
174
|
-
session: "Session"
|
|
175
163
|
) -> str:
|
|
176
164
|
"""
|
|
177
165
|
Returns the default account for this identity.
|
|
178
166
|
|
|
179
167
|
:param identity_key: The identity key name. For example x509 DN, or a username.
|
|
180
168
|
:param id_type: The type of the authentication (x509, gss, userpass, ssh, saml).
|
|
181
|
-
:param session: The database session in use.
|
|
182
169
|
"""
|
|
183
|
-
|
|
170
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
171
|
+
account = identity.get_default_account(identity_key, IdentityType[id_type.upper()], session=session)
|
|
184
172
|
return account.external
|
|
185
173
|
|
|
186
174
|
|
|
187
|
-
@read_session
|
|
188
175
|
def list_accounts_for_identity(
|
|
189
176
|
identity_key: str,
|
|
190
177
|
id_type: str,
|
|
191
|
-
*,
|
|
192
|
-
session: "Session"
|
|
193
178
|
) -> list[str]:
|
|
194
179
|
"""
|
|
195
180
|
Returns a list of all accounts for an identity.
|
|
196
181
|
|
|
197
182
|
:param identity: The identity key name. For example x509 DN, or a username.
|
|
198
183
|
:param id_type: The type of the authentication (x509, gss, userpass, ssh, saml).
|
|
199
|
-
:param session: The database session in use.
|
|
200
184
|
|
|
201
185
|
returns: A list of all accounts for the identity.
|
|
202
186
|
"""
|
|
203
|
-
|
|
187
|
+
with db_session(DatabaseOperationType.READ) as session:
|
|
188
|
+
accounts = identity.list_accounts_for_identity(identity_key, IdentityType[id_type.upper()], session=session)
|
|
204
189
|
return [account.external for account in accounts]
|
rucio/gateway/importer.py
CHANGED
|
@@ -37,8 +37,9 @@ def import_data(data: dict[str, Any], issuer: str, vo: str = 'def', *, session:
|
|
|
37
37
|
"""
|
|
38
38
|
kwargs = {'issuer': issuer}
|
|
39
39
|
validate_schema(name='import', obj=data, vo=vo)
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='import', kwargs=kwargs, session=session)
|
|
41
|
+
if not auth_result.allowed:
|
|
42
|
+
raise exception.AccessDenied('Account %s can not import data. %s' % (issuer, auth_result.message))
|
|
42
43
|
|
|
43
44
|
for account in data.get('accounts', []):
|
|
44
45
|
account['account'] = InternalAccount(account['account'], vo=vo)
|
|
@@ -115,6 +115,7 @@ def update_exception(
|
|
|
115
115
|
:param session: The database session in use.
|
|
116
116
|
"""
|
|
117
117
|
kwargs = {'exception_id': exception_id, 'vo': vo}
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='update_lifetime_exceptions', kwargs=kwargs, session=session)
|
|
119
|
+
if not auth_result.allowed:
|
|
120
|
+
raise exception.AccessDenied('Account %s can not update lifetime exceptions. %s' % (issuer, auth_result.message))
|
|
120
121
|
return lifetime_exception.update_exception(exception_id=exception_id, state=state, session=session)
|
|
@@ -16,7 +16,6 @@ from typing import TYPE_CHECKING, Optional, Union
|
|
|
16
16
|
|
|
17
17
|
from rucio.common.exception import AccessDenied
|
|
18
18
|
from rucio.core import meta_conventions
|
|
19
|
-
from rucio.db.sqla.constants import KeyType
|
|
20
19
|
from rucio.db.sqla.session import read_session, transactional_session
|
|
21
20
|
from rucio.gateway.permission import has_permission
|
|
22
21
|
|
|
@@ -24,6 +23,7 @@ if TYPE_CHECKING:
|
|
|
24
23
|
from sqlalchemy.orm import Session
|
|
25
24
|
|
|
26
25
|
from rucio.common.types import InternalAccount
|
|
26
|
+
from rucio.db.sqla.constants import KeyType
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
@read_session
|
|
@@ -53,7 +53,16 @@ def list_values(key: str, *, session: "Session") -> list[str]:
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
@transactional_session
|
|
56
|
-
def add_key(
|
|
56
|
+
def add_key(
|
|
57
|
+
key: str,
|
|
58
|
+
key_type: Union["KeyType", str],
|
|
59
|
+
issuer: "InternalAccount",
|
|
60
|
+
value_type: Optional[str] = None,
|
|
61
|
+
value_regexp: Optional[str] = None,
|
|
62
|
+
vo: str = 'def',
|
|
63
|
+
*,
|
|
64
|
+
session: "Session"
|
|
65
|
+
) -> None:
|
|
57
66
|
"""
|
|
58
67
|
Add an allowed key for DID metadata (update the DID Metadata Conventions table with a new key).
|
|
59
68
|
|
|
@@ -66,8 +75,9 @@ def add_key(key: str, key_type: Union[KeyType, str], issuer: "InternalAccount",
|
|
|
66
75
|
:param session: The database session in use.
|
|
67
76
|
"""
|
|
68
77
|
kwargs = {'key': key, 'key_type': key_type, 'value_type': value_type, 'value_regexp': value_regexp}
|
|
69
|
-
|
|
70
|
-
|
|
78
|
+
auth_result = has_permission(issuer=issuer, vo=vo, action='add_key', kwargs=kwargs, session=session)
|
|
79
|
+
if not auth_result.allowed:
|
|
80
|
+
raise AccessDenied('Account %s can not add key. %s' % (issuer, auth_result.message))
|
|
71
81
|
return meta_conventions.add_key(key=key, key_type=key_type, value_type=value_type, value_regexp=value_regexp, session=session)
|
|
72
82
|
|
|
73
83
|
|
|
@@ -82,6 +92,7 @@ def add_value(key: str, value: str, issuer: "InternalAccount", vo: str = 'def',
|
|
|
82
92
|
:param session: The database session in use.
|
|
83
93
|
"""
|
|
84
94
|
kwargs = {'key': key, 'value': value}
|
|
85
|
-
|
|
86
|
-
|
|
95
|
+
auth_result = has_permission(issuer=issuer, vo=vo, action='add_value', kwargs=kwargs, session=session)
|
|
96
|
+
if not auth_result.allowed:
|
|
97
|
+
raise AccessDenied('Account %s can not add value %s to key %s. %s' % (issuer, value, key, auth_result.message))
|
|
87
98
|
return meta_conventions.add_value(key=key, value=value, session=session)
|
rucio/gateway/permission.py
CHANGED
|
@@ -24,9 +24,11 @@ from rucio.db.sqla.session import read_session
|
|
|
24
24
|
if TYPE_CHECKING:
|
|
25
25
|
from sqlalchemy.orm import Session
|
|
26
26
|
|
|
27
|
+
from rucio.core.permission import PermissionResult
|
|
28
|
+
|
|
27
29
|
|
|
28
30
|
@read_session
|
|
29
|
-
def has_permission(issuer: str, action: str, kwargs: dict[str, Any], vo: str = 'def', *, session: "Session") ->
|
|
31
|
+
def has_permission(issuer: str, action: str, kwargs: dict[str, Any], vo: str = 'def', *, session: "Session") -> 'PermissionResult':
|
|
30
32
|
"""
|
|
31
33
|
Checks if an account has the specified permission to
|
|
32
34
|
execute an action with parameters.
|
|
@@ -62,6 +64,7 @@ def has_permission(issuer: str, action: str, kwargs: dict[str, Any], vo: str = '
|
|
|
62
64
|
r['account'] = InternalAccount(r['account'], vo=vo)
|
|
63
65
|
if 'dids' in kwargs:
|
|
64
66
|
for d in kwargs['dids']:
|
|
67
|
+
d['scope'] = InternalScope(d['scope'], vo=vo)
|
|
65
68
|
if 'rules' in d:
|
|
66
69
|
for r in d['rules']:
|
|
67
70
|
r['account'] = InternalAccount(r['account'], vo=vo)
|
|
@@ -57,8 +57,9 @@ def quarantine_file_replicas(
|
|
|
57
57
|
if rse_id is None:
|
|
58
58
|
rse_id = get_rse_id(rse, vo=vo, session=session)
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
auth_result = permission.has_permission(issuer, 'quarantine_file_replicas', {}, vo=vo, session=session)
|
|
61
|
+
if not auth_result.allowed:
|
|
62
|
+
raise exception.AccessDenied('Account %s can not quarantine replicas. %s' % (issuer, auth_result.message))
|
|
62
63
|
|
|
63
64
|
replica_infos = []
|
|
64
65
|
for r in replicas:
|
rucio/gateway/replica.py
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import datetime
|
|
16
|
-
from collections.abc import Iterator
|
|
17
16
|
from typing import TYPE_CHECKING, Any, Optional
|
|
18
17
|
|
|
19
18
|
from rucio.common import exception
|
|
@@ -28,6 +27,8 @@ from rucio.db.sqla.session import read_session, stream_session, transactional_se
|
|
|
28
27
|
from rucio.gateway import permission
|
|
29
28
|
|
|
30
29
|
if TYPE_CHECKING:
|
|
30
|
+
from collections.abc import Iterator
|
|
31
|
+
|
|
31
32
|
from sqlalchemy.orm import Session
|
|
32
33
|
|
|
33
34
|
|
|
@@ -119,11 +120,12 @@ def declare_bad_file_replicas(replicas, reason, issuer, vo='def', force=False, *
|
|
|
119
120
|
rse_id_to_name = invert_dict(rse_map) # RSE id -> RSE name
|
|
120
121
|
|
|
121
122
|
for rse_id in rse_ids_to_check:
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='declare_bad_file_replicas',
|
|
124
|
+
kwargs={"rse_id": rse_id},
|
|
125
|
+
session=session)
|
|
126
|
+
if not auth_result.allowed:
|
|
127
|
+
raise exception.AccessDenied('Account %s can not declare bad replicas in RSE %s. %s' %
|
|
128
|
+
(issuer, rse_id_to_name.get(rse_id, rse_id), auth_result.message))
|
|
127
129
|
|
|
128
130
|
undeclared = replica.declare_bad_file_replicas(replicas_lst, reason=reason,
|
|
129
131
|
issuer=InternalAccount(issuer, vo=vo),
|
|
@@ -159,8 +161,9 @@ def declare_suspicious_file_replicas(pfns, reason, issuer, vo='def', *, session:
|
|
|
159
161
|
:param session: The database session in use.
|
|
160
162
|
"""
|
|
161
163
|
kwargs = {}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='declare_suspicious_file_replicas', kwargs=kwargs, session=session)
|
|
165
|
+
if not auth_result.allowed:
|
|
166
|
+
raise exception.AccessDenied('Account %s can not declare suspicious replicas. %s' % (issuer, auth_result.message))
|
|
164
167
|
|
|
165
168
|
issuer = InternalAccount(issuer, vo=vo)
|
|
166
169
|
|
|
@@ -248,7 +251,7 @@ def list_replicas(dids, schemes=None, unavailable=False, request_id=None,
|
|
|
248
251
|
new_parents = []
|
|
249
252
|
for p in rep['parents']:
|
|
250
253
|
scope, name = p.split(':')
|
|
251
|
-
scope = InternalScope(scope,
|
|
254
|
+
scope = InternalScope(scope, from_external=False).external
|
|
252
255
|
new_parents.append('{}:{}'.format(scope, name))
|
|
253
256
|
rep['parents'] = new_parents
|
|
254
257
|
|
|
@@ -276,8 +279,9 @@ def add_replicas(rse, files, issuer, ignore_availability=False, vo='def', *, ses
|
|
|
276
279
|
rse_id = get_rse_id(rse=rse, vo=vo, session=session)
|
|
277
280
|
|
|
278
281
|
kwargs = {'rse': rse, 'rse_id': rse_id}
|
|
279
|
-
|
|
280
|
-
|
|
282
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='add_replicas', kwargs=kwargs, session=session)
|
|
283
|
+
if not auth_result.allowed:
|
|
284
|
+
raise exception.AccessDenied('Account %s can not add file replicas on %s. %s' % (issuer, rse, auth_result.message))
|
|
281
285
|
if not permission.has_permission(issuer=issuer, vo=vo, action='skip_availability_check', kwargs=kwargs, session=session):
|
|
282
286
|
ignore_availability = False
|
|
283
287
|
|
|
@@ -309,8 +313,9 @@ def delete_replicas(rse, files, issuer, ignore_availability=False, vo='def', *,
|
|
|
309
313
|
rse_id = get_rse_id(rse=rse, vo=vo, session=session)
|
|
310
314
|
|
|
311
315
|
kwargs = {'rse': rse, 'rse_id': rse_id}
|
|
312
|
-
|
|
313
|
-
|
|
316
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='delete_replicas', kwargs=kwargs, session=session)
|
|
317
|
+
if not auth_result.allowed:
|
|
318
|
+
raise exception.AccessDenied('Account %s can not delete file replicas on %s. %s' % (issuer, rse, auth_result.message))
|
|
314
319
|
if not permission.has_permission(issuer=issuer, vo=vo, action='skip_availability_check', kwargs=kwargs, session=session):
|
|
315
320
|
ignore_availability = False
|
|
316
321
|
|
|
@@ -338,8 +343,9 @@ def update_replicas_states(rse, files, issuer, vo='def', *, session: "Session"):
|
|
|
338
343
|
rse_id = get_rse_id(rse=rse, vo=vo, session=session)
|
|
339
344
|
|
|
340
345
|
kwargs = {'rse': rse, 'rse_id': rse_id}
|
|
341
|
-
|
|
342
|
-
|
|
346
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='update_replicas_states', kwargs=kwargs, session=session)
|
|
347
|
+
if not auth_result.allowed:
|
|
348
|
+
raise exception.AccessDenied('Account %s can not update file replicas state on %s. %s' % (issuer, rse, auth_result.message))
|
|
343
349
|
replicas = []
|
|
344
350
|
for file in files:
|
|
345
351
|
rep = file
|
|
@@ -419,7 +425,7 @@ def list_dataset_replicas_vp(scope, name, deep=False, vo='def', *, session: "Ses
|
|
|
419
425
|
|
|
420
426
|
|
|
421
427
|
@stream_session
|
|
422
|
-
def list_datasets_per_rse(rse: str, filters: Optional[dict[str, Any]] = None, limit: Optional[int] = None, vo: str = 'def', *, session: "Session") -> Iterator[dict[str, Any]]:
|
|
428
|
+
def list_datasets_per_rse(rse: str, filters: Optional[dict[str, Any]] = None, limit: Optional[int] = None, vo: str = 'def', *, session: "Session") -> 'Iterator[dict[str, Any]]':
|
|
423
429
|
"""
|
|
424
430
|
:param scope: The scope of the dataset.
|
|
425
431
|
:param name: The name of the dataset.
|
|
@@ -455,8 +461,9 @@ def add_bad_pfns(pfns, issuer, state, reason=None, expires_at=None, vo='def', *,
|
|
|
455
461
|
:returns: True is successful.
|
|
456
462
|
"""
|
|
457
463
|
kwargs = {'state': state}
|
|
458
|
-
|
|
459
|
-
|
|
464
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='add_bad_pfns', kwargs=kwargs, session=session)
|
|
465
|
+
if not auth_result.allowed:
|
|
466
|
+
raise exception.AccessDenied('Account %s can not declare bad PFNs. %s' % (issuer, auth_result.message))
|
|
460
467
|
|
|
461
468
|
if expires_at and datetime.datetime.utcnow() <= expires_at and expires_at > datetime.datetime.utcnow() + datetime.timedelta(days=30):
|
|
462
469
|
raise exception.InputValidationError('The given duration of %s days exceeds the maximum duration of 30 days.' % (expires_at - datetime.datetime.utcnow()).days)
|
|
@@ -483,8 +490,9 @@ def add_bad_dids(dids, rse, issuer, state, reason=None, expires_at=None, vo='def
|
|
|
483
490
|
:returns: The list of replicas not declared bad
|
|
484
491
|
"""
|
|
485
492
|
kwargs = {'state': state}
|
|
486
|
-
|
|
487
|
-
|
|
493
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='add_bad_pfns', kwargs=kwargs, session=session)
|
|
494
|
+
if not auth_result.allowed:
|
|
495
|
+
raise exception.AccessDenied('Account %s can not declare bad PFN or DIDs. %s' % (issuer, auth_result.message))
|
|
488
496
|
|
|
489
497
|
issuer = InternalAccount(issuer, vo=vo)
|
|
490
498
|
rse_id = get_rse_id(rse=rse, session=session)
|
|
@@ -522,8 +530,9 @@ def set_tombstone(rse, scope, name, issuer, vo='def', *, session: "Session"):
|
|
|
522
530
|
|
|
523
531
|
rse_id = get_rse_id(rse, vo=vo, session=session)
|
|
524
532
|
|
|
525
|
-
|
|
526
|
-
|
|
533
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='set_tombstone', kwargs={}, session=session)
|
|
534
|
+
if not auth_result.allowed:
|
|
535
|
+
raise exception.AccessDenied('Account %s can not set tombstones. %s' % (issuer, auth_result.message))
|
|
527
536
|
|
|
528
537
|
scope = InternalScope(scope, vo=vo)
|
|
529
538
|
replica.set_tombstone(rse_id, scope, name, session=session)
|
rucio/gateway/request.py
CHANGED
|
@@ -53,8 +53,9 @@ def queue_requests(
|
|
|
53
53
|
"""
|
|
54
54
|
|
|
55
55
|
kwargs = {'requests': requests, 'issuer': issuer}
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='queue_requests', kwargs=kwargs, session=session)
|
|
57
|
+
if not auth_result.allowed:
|
|
58
|
+
raise exception.AccessDenied(f'{issuer} can not queue request. {auth_result.message}')
|
|
58
59
|
|
|
59
60
|
for req in requests:
|
|
60
61
|
req['scope'] = InternalScope(req['scope'], vo=vo) # type: ignore (type reassignment)
|
|
@@ -85,8 +86,9 @@ def cancel_request(
|
|
|
85
86
|
"""
|
|
86
87
|
|
|
87
88
|
kwargs = {'account': account, 'issuer': issuer, 'request_id': request_id}
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='cancel_request_', kwargs=kwargs, session=session)
|
|
90
|
+
if not auth_result.allowed:
|
|
91
|
+
raise exception.AccessDenied('%s cannot cancel request %s. %s' % (account, request_id, auth_result.message))
|
|
90
92
|
|
|
91
93
|
raise NotImplementedError
|
|
92
94
|
|
|
@@ -119,8 +121,9 @@ def cancel_request_did(
|
|
|
119
121
|
dest_rse_id = get_rse_id(rse=dest_rse, vo=vo, session=session)
|
|
120
122
|
|
|
121
123
|
kwargs = {'account': account, 'issuer': issuer}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='cancel_request_did', kwargs=kwargs, session=session)
|
|
125
|
+
if not auth_result.allowed:
|
|
126
|
+
raise exception.AccessDenied(f'{account} cannot cancel {request_type} request for {scope}:{name}. {auth_result.message}')
|
|
124
127
|
|
|
125
128
|
internal_scope = InternalScope(scope, vo=vo)
|
|
126
129
|
return request.cancel_request_did(internal_scope, name, dest_rse_id, request_type, session=session)
|
|
@@ -149,8 +152,9 @@ def get_next(
|
|
|
149
152
|
"""
|
|
150
153
|
|
|
151
154
|
kwargs = {'account': account, 'issuer': issuer, 'request_type': request_type, 'state': state}
|
|
152
|
-
|
|
153
|
-
|
|
155
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='get_next', kwargs=kwargs, session=session)
|
|
156
|
+
if not auth_result.allowed:
|
|
157
|
+
raise exception.AccessDenied(f'{account} cannot get the next request of type {request_type} in state {state}. {auth_result.message}')
|
|
154
158
|
|
|
155
159
|
reqs = request.get_and_mark_next(request_type, state, session=session)
|
|
156
160
|
return [gateway_update_return_dict(r, session=session) for r in reqs]
|
|
@@ -180,8 +184,9 @@ def get_request_by_did(
|
|
|
180
184
|
rse_id = get_rse_id(rse=rse, vo=vo, session=session)
|
|
181
185
|
|
|
182
186
|
kwargs = {'scope': scope, 'name': name, 'rse': rse, 'rse_id': rse_id, 'issuer': issuer}
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='get_request_by_did', kwargs=kwargs, session=session)
|
|
188
|
+
if not auth_result.allowed:
|
|
189
|
+
raise exception.AccessDenied(f'{issuer} cannot retrieve the request DID {scope}:{name} to RSE {rse}. {auth_result.message}')
|
|
185
190
|
|
|
186
191
|
internal_scope = InternalScope(scope, vo=vo)
|
|
187
192
|
req = request.get_request_by_did(internal_scope, name, rse_id, session=session)
|
|
@@ -213,8 +218,9 @@ def get_request_history_by_did(
|
|
|
213
218
|
rse_id = get_rse_id(rse=rse, vo=vo, session=session)
|
|
214
219
|
|
|
215
220
|
kwargs = {'scope': scope, 'name': name, 'rse': rse, 'rse_id': rse_id, 'issuer': issuer}
|
|
216
|
-
|
|
217
|
-
|
|
221
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='get_request_history_by_did', kwargs=kwargs, session=session)
|
|
222
|
+
if not auth_result.allowed:
|
|
223
|
+
raise exception.AccessDenied(f'{issuer} cannot retrieve the request DID {scope}:{name} to RSE {rse}. {auth_result.message}')
|
|
218
224
|
|
|
219
225
|
internal_scope = InternalScope(scope, vo=vo)
|
|
220
226
|
req = request.get_request_history_by_did(internal_scope, name, rse_id, session=session)
|
|
@@ -245,8 +251,9 @@ def list_requests(
|
|
|
245
251
|
dst_rse_ids = [get_rse_id(rse=rse, vo=vo, session=session) for rse in dst_rses]
|
|
246
252
|
|
|
247
253
|
kwargs = {'src_rse_id': src_rse_ids, 'dst_rse_id': dst_rse_ids, 'issuer': issuer}
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='list_requests', kwargs=kwargs, session=session)
|
|
255
|
+
if not auth_result.allowed:
|
|
256
|
+
raise exception.AccessDenied(f'{issuer} cannot list requests from RSEs {src_rses} to RSEs {dst_rses}. {auth_result.message}')
|
|
250
257
|
|
|
251
258
|
for req in request.list_requests(src_rse_ids, dst_rse_ids, states, session=session):
|
|
252
259
|
req = req.to_dict()
|
|
@@ -279,8 +286,9 @@ def list_requests_history(
|
|
|
279
286
|
dst_rse_ids = [get_rse_id(rse=rse, vo=vo, session=session) for rse in dst_rses]
|
|
280
287
|
|
|
281
288
|
kwargs = {'src_rse_id': src_rse_ids, 'dst_rse_id': dst_rse_ids, 'issuer': issuer}
|
|
282
|
-
|
|
283
|
-
|
|
289
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='list_requests_history', kwargs=kwargs, session=session)
|
|
290
|
+
if not auth_result.allowed:
|
|
291
|
+
raise exception.AccessDenied(f'{issuer} cannot list requests from RSEs {src_rses} to RSEs {dst_rses}. {auth_result.message}')
|
|
284
292
|
|
|
285
293
|
for req in request.list_requests_history(src_rse_ids, dst_rse_ids, states, offset, limit, session=session):
|
|
286
294
|
req = req.to_dict()
|
|
@@ -315,7 +323,8 @@ def get_request_metrics(
|
|
|
315
323
|
if dst_rse:
|
|
316
324
|
dst_rse_id = get_rse_id(rse=dst_rse, vo=vo, session=session)
|
|
317
325
|
kwargs = {'issuer': issuer}
|
|
318
|
-
|
|
319
|
-
|
|
326
|
+
auth_result = permission.has_permission(issuer=issuer, vo=vo, action='get_request_metrics', kwargs=kwargs, session=session)
|
|
327
|
+
if not auth_result.allowed:
|
|
328
|
+
raise exception.AccessDenied(f'{issuer} cannot get request statistics. {auth_result.message}')
|
|
320
329
|
|
|
321
330
|
return request.get_request_metrics(dest_rse_id=dst_rse_id, src_rse_id=src_rse_id, activity=activity, group_by_rse_attribute=group_by_rse_attribute, session=session)
|