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/core/oidc.py
CHANGED
|
@@ -36,9 +36,8 @@ from oic.utils.authn.client import CLIENT_AUTHN_METHOD
|
|
|
36
36
|
from sqlalchemy import delete, select, update
|
|
37
37
|
from sqlalchemy.sql.expression import true
|
|
38
38
|
|
|
39
|
-
from rucio.common import
|
|
40
|
-
from rucio.common.
|
|
41
|
-
from rucio.common.config import config_get, config_get_int
|
|
39
|
+
from rucio.common.cache import MemcacheRegion
|
|
40
|
+
from rucio.common.config import config_get, config_get_bool, config_get_int
|
|
42
41
|
from rucio.common.exception import CannotAuthenticate, CannotAuthorize, RucioException
|
|
43
42
|
from rucio.common.stopwatch import Stopwatch
|
|
44
43
|
from rucio.common.utils import all_oidc_req_claims_present, build_url, val_to_space_sep_str
|
|
@@ -52,12 +51,14 @@ from rucio.db.sqla.session import read_session, transactional_session
|
|
|
52
51
|
if TYPE_CHECKING:
|
|
53
52
|
from sqlalchemy.orm import Session
|
|
54
53
|
|
|
54
|
+
from rucio.common.types import InternalAccount
|
|
55
|
+
|
|
55
56
|
# The WLCG Common JWT Profile dictates that the lifetime of access and ID tokens
|
|
56
57
|
# should range from five minutes to six hours.
|
|
57
58
|
TOKEN_MIN_LIFETIME: Final = config_get_int('oidc', 'token_min_lifetime', default=300)
|
|
58
59
|
TOKEN_MAX_LIFETIME: Final = config_get_int('oidc', 'token_max_lifetime', default=21600)
|
|
59
60
|
|
|
60
|
-
REGION: Final =
|
|
61
|
+
REGION: Final = MemcacheRegion(expiration_time=TOKEN_MAX_LIFETIME)
|
|
61
62
|
METRICS = MetricManager(module=__name__)
|
|
62
63
|
|
|
63
64
|
# worokaround for a bug in pyoidc (as of Dec 2019)
|
|
@@ -218,11 +219,11 @@ def __initialize_oidc_clients() -> None:
|
|
|
218
219
|
"""
|
|
219
220
|
|
|
220
221
|
try:
|
|
221
|
-
|
|
222
|
+
all_oidc_clients = __get_rucio_oidc_clients()
|
|
222
223
|
global OIDC_CLIENTS
|
|
223
224
|
global OIDC_ADMIN_CLIENTS
|
|
224
|
-
OIDC_CLIENTS =
|
|
225
|
-
OIDC_ADMIN_CLIENTS =
|
|
225
|
+
OIDC_CLIENTS = all_oidc_clients[0]
|
|
226
|
+
OIDC_ADMIN_CLIENTS = all_oidc_clients[1]
|
|
226
227
|
except Exception as error:
|
|
227
228
|
logging.debug("OIDC clients not properly loaded: %s", error)
|
|
228
229
|
pass
|
|
@@ -297,7 +298,8 @@ def __get_init_oidc_client(token_object: models.Token = None, token_type: str =
|
|
|
297
298
|
"state": kwargs.get('state', rndstr()),
|
|
298
299
|
"nonce": kwargs.get('nonce', rndstr())}
|
|
299
300
|
auth_args["scope"] = token_object.oidc_scope if token_object else kwargs.get('scope', " ")
|
|
300
|
-
|
|
301
|
+
if config_get_bool('oidc', 'supports_audience', raise_exception=False, default=True):
|
|
302
|
+
auth_args["audience"] = token_object.audience if token_object else kwargs.get('audience', " ")
|
|
301
303
|
|
|
302
304
|
if token_object:
|
|
303
305
|
issuer = token_object.identity.split(", ")[1].split("=")[1]
|
|
@@ -643,7 +645,7 @@ def get_token_oidc(
|
|
|
643
645
|
|
|
644
646
|
|
|
645
647
|
@transactional_session
|
|
646
|
-
def __get_admin_token_oidc(account:
|
|
648
|
+
def __get_admin_token_oidc(account: 'InternalAccount', req_scope, req_audience, issuer, *, session: "Session"):
|
|
647
649
|
"""
|
|
648
650
|
Get a token for Rucio application to act on behalf of itself.
|
|
649
651
|
client_credential flow is used for this purpose.
|
|
@@ -13,12 +13,15 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import importlib
|
|
16
|
+
import logging
|
|
16
17
|
from configparser import NoOptionError, NoSectionError
|
|
17
18
|
from os import environ
|
|
18
19
|
from typing import TYPE_CHECKING, Any
|
|
19
20
|
|
|
21
|
+
import rucio.core.permission.generic
|
|
20
22
|
from rucio.common import config, exception
|
|
21
|
-
from rucio.common.
|
|
23
|
+
from rucio.common.plugins import check_policy_package_version
|
|
24
|
+
from rucio.common.policy import get_policy
|
|
22
25
|
|
|
23
26
|
if TYPE_CHECKING:
|
|
24
27
|
from typing import Optional
|
|
@@ -27,6 +30,8 @@ if TYPE_CHECKING:
|
|
|
27
30
|
|
|
28
31
|
from rucio.common.types import InternalAccount
|
|
29
32
|
|
|
33
|
+
LOGGER = logging.getLogger('policy')
|
|
34
|
+
|
|
30
35
|
# dictionary of permission modules for each VO
|
|
31
36
|
permission_modules = {}
|
|
32
37
|
|
|
@@ -37,83 +42,120 @@ except (NoOptionError, NoSectionError):
|
|
|
37
42
|
|
|
38
43
|
# in multi-vo mode packages are loaded on demand when needed
|
|
39
44
|
if not multivo:
|
|
40
|
-
|
|
45
|
+
generic_fallback = 'generic'
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
except (NoOptionError, NoSectionError):
|
|
46
|
-
FALLBACK_POLICY = GENERIC_FALLBACK
|
|
47
|
-
elif config.config_has_section('policy'):
|
|
48
|
-
try:
|
|
49
|
-
FALLBACK_POLICY = config.config_get('policy', 'permission')
|
|
50
|
-
except (NoOptionError, NoSectionError):
|
|
51
|
-
FALLBACK_POLICY = GENERIC_FALLBACK
|
|
52
|
-
else:
|
|
53
|
-
FALLBACK_POLICY = GENERIC_FALLBACK
|
|
47
|
+
fallback_policy = get_policy()
|
|
48
|
+
if fallback_policy == 'def':
|
|
49
|
+
fallback_policy = generic_fallback
|
|
54
50
|
|
|
55
51
|
if config.config_has_section('policy'):
|
|
56
52
|
try:
|
|
57
53
|
if 'RUCIO_POLICY_PACKAGE' in environ:
|
|
58
|
-
|
|
54
|
+
policy = environ['RUCIO_POLICY_PACKAGE']
|
|
59
55
|
else:
|
|
60
|
-
|
|
61
|
-
check_policy_package_version(
|
|
62
|
-
|
|
56
|
+
policy = config.config_get('policy', 'package', check_config_table=False)
|
|
57
|
+
check_policy_package_version(policy)
|
|
58
|
+
policy = policy + ".permission"
|
|
63
59
|
except (NoOptionError, NoSectionError):
|
|
64
60
|
# fall back to old system for now
|
|
65
|
-
|
|
61
|
+
policy = 'rucio.core.permission.' + fallback_policy.lower()
|
|
66
62
|
else:
|
|
67
|
-
|
|
63
|
+
policy = 'rucio.core.permission.' + generic_fallback.lower()
|
|
68
64
|
|
|
69
65
|
try:
|
|
70
|
-
module = importlib.import_module(
|
|
66
|
+
module = importlib.import_module(policy)
|
|
71
67
|
except ModuleNotFoundError:
|
|
72
|
-
|
|
68
|
+
# if policy package does not contain permission module, load fallback module instead
|
|
69
|
+
# this allows a policy package to omit modules that do not need customisation
|
|
70
|
+
try:
|
|
71
|
+
LOGGER.warning('Unable to load permission module %s from policy package, falling back to %s'
|
|
72
|
+
% (policy, fallback_policy))
|
|
73
|
+
policy = 'rucio.core.permission.' + fallback_policy.lower()
|
|
74
|
+
module = importlib.import_module(policy)
|
|
75
|
+
except ModuleNotFoundError:
|
|
76
|
+
raise exception.PolicyPackageNotFound(policy)
|
|
77
|
+
except ImportError:
|
|
78
|
+
raise exception.ErrorLoadingPolicyPackage(policy)
|
|
73
79
|
except ImportError:
|
|
74
|
-
raise exception.ErrorLoadingPolicyPackage(
|
|
80
|
+
raise exception.ErrorLoadingPolicyPackage(policy)
|
|
75
81
|
|
|
76
82
|
permission_modules["def"] = module
|
|
77
83
|
|
|
78
84
|
|
|
79
85
|
def load_permission_for_vo(vo: str) -> None:
|
|
80
|
-
|
|
86
|
+
generic_fallback = 'generic_multi_vo'
|
|
81
87
|
if config.config_has_section('policy'):
|
|
82
88
|
try:
|
|
83
89
|
env_name = 'RUCIO_POLICY_PACKAGE_' + vo.upper()
|
|
84
90
|
if env_name in environ:
|
|
85
|
-
|
|
91
|
+
policy = environ[env_name]
|
|
86
92
|
else:
|
|
87
|
-
|
|
88
|
-
check_policy_package_version(
|
|
89
|
-
|
|
93
|
+
policy = config.config_get('policy', 'package-' + vo)
|
|
94
|
+
check_policy_package_version(policy)
|
|
95
|
+
policy = policy + ".permission"
|
|
90
96
|
except (NoOptionError, NoSectionError):
|
|
91
97
|
# fall back to old system for now
|
|
92
98
|
try:
|
|
93
|
-
|
|
99
|
+
policy = config.config_get('policy', 'permission')
|
|
94
100
|
except (NoOptionError, NoSectionError):
|
|
95
|
-
|
|
96
|
-
|
|
101
|
+
policy = generic_fallback
|
|
102
|
+
policy = 'rucio.core.permission.' + policy.lower()
|
|
97
103
|
else:
|
|
98
|
-
|
|
104
|
+
policy = 'rucio.core.permission.' + generic_fallback.lower()
|
|
99
105
|
|
|
100
106
|
try:
|
|
101
|
-
module = importlib.import_module(
|
|
107
|
+
module = importlib.import_module(policy)
|
|
102
108
|
except ModuleNotFoundError:
|
|
103
|
-
|
|
109
|
+
# if policy package does not contain permission module, load fallback module instead
|
|
110
|
+
# this allows a policy package to omit modules that do not need customisation
|
|
111
|
+
try:
|
|
112
|
+
LOGGER.warning('Unable to load permission module %s from policy package, falling back to %s'
|
|
113
|
+
% (policy, generic_fallback))
|
|
114
|
+
policy = 'rucio.core.permission.' + generic_fallback.lower()
|
|
115
|
+
module = importlib.import_module(policy)
|
|
116
|
+
except ModuleNotFoundError:
|
|
117
|
+
raise exception.PolicyPackageNotFound(policy)
|
|
118
|
+
except ImportError:
|
|
119
|
+
raise exception.ErrorLoadingPolicyPackage(policy)
|
|
120
|
+
raise exception.PolicyPackageNotFound(policy)
|
|
104
121
|
except ImportError:
|
|
105
|
-
raise exception.ErrorLoadingPolicyPackage(
|
|
122
|
+
raise exception.ErrorLoadingPolicyPackage(policy)
|
|
106
123
|
|
|
107
124
|
permission_modules[vo] = module
|
|
108
125
|
|
|
109
126
|
|
|
127
|
+
class PermissionResult:
|
|
128
|
+
"""
|
|
129
|
+
Represents the result of a permission check, allowing an optional message to be
|
|
130
|
+
included to give the user more information.
|
|
131
|
+
"""
|
|
132
|
+
def __init__(self, allowed: bool, message: "Optional[str]" = "") -> None:
|
|
133
|
+
self.allowed = allowed
|
|
134
|
+
self.message = message
|
|
135
|
+
|
|
136
|
+
# allow this to be tested as a bool for backwards compatibility
|
|
137
|
+
def __bool__(self) -> bool:
|
|
138
|
+
return self.allowed
|
|
139
|
+
|
|
140
|
+
|
|
110
141
|
def has_permission(
|
|
111
142
|
issuer: "InternalAccount",
|
|
112
143
|
action: str,
|
|
113
144
|
kwargs: dict[str, Any],
|
|
114
145
|
*,
|
|
115
146
|
session: "Optional[Session]" = None
|
|
116
|
-
) ->
|
|
147
|
+
) -> PermissionResult:
|
|
117
148
|
if issuer.vo not in permission_modules:
|
|
118
149
|
load_permission_for_vo(issuer.vo)
|
|
119
|
-
|
|
150
|
+
try:
|
|
151
|
+
result = permission_modules[issuer.vo].has_permission(issuer, action, kwargs, session=session)
|
|
152
|
+
except TypeError:
|
|
153
|
+
# will be thrown if policy package is missing the action in its perm dictionary
|
|
154
|
+
result = None
|
|
155
|
+
# if this permission is missing from the policy package, fallback to generic
|
|
156
|
+
if result is None:
|
|
157
|
+
result = rucio.core.permission.generic.has_permission(issuer, action, kwargs, session=session)
|
|
158
|
+
# continue to support policy packages that just return a boolean and no message
|
|
159
|
+
if isinstance(result, bool):
|
|
160
|
+
result = PermissionResult(result)
|
|
161
|
+
return result
|
rucio/core/permission/generic.py
CHANGED
|
@@ -410,13 +410,7 @@ def perm_add_dids(issuer: "InternalAccount", kwargs: dict[str, Any], *, session:
|
|
|
410
410
|
:returns: True if account is allowed, otherwise False
|
|
411
411
|
"""
|
|
412
412
|
# Check the accounts of the issued rules
|
|
413
|
-
|
|
414
|
-
for did in kwargs['dids']:
|
|
415
|
-
for rule in did.get('rules', []):
|
|
416
|
-
if rule['account'] != issuer:
|
|
417
|
-
return False
|
|
418
|
-
|
|
419
|
-
return _is_root(issuer) or has_account_attribute(account=issuer, key='admin', session=session)
|
|
413
|
+
return all(perm_add_did(issuer, kwargs=did, session=session) for did in kwargs['dids'])
|
|
420
414
|
|
|
421
415
|
|
|
422
416
|
def perm_attach_dids(issuer: "InternalAccount", kwargs: dict[str, Any], *, session: "Optional[Session]" = None) -> bool:
|
|
@@ -412,13 +412,7 @@ def perm_add_dids(issuer, kwargs, *, session: "Optional[Session]" = None):
|
|
|
412
412
|
:returns: True if account is allowed, otherwise False
|
|
413
413
|
"""
|
|
414
414
|
# Check the accounts of the issued rules
|
|
415
|
-
|
|
416
|
-
for did in kwargs['dids']:
|
|
417
|
-
for rule in did.get('rules', []):
|
|
418
|
-
if rule['account'] != issuer:
|
|
419
|
-
return False
|
|
420
|
-
|
|
421
|
-
return _is_root(issuer) or has_account_attribute(account=issuer, key='admin', session=session)
|
|
415
|
+
return all(perm_add_did(issuer, kwargs=did, session=session) for did in kwargs['dids'])
|
|
422
416
|
|
|
423
417
|
|
|
424
418
|
def perm_attach_dids(issuer, kwargs, *, session: "Optional[Session]" = None):
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import datetime
|
|
16
|
-
from collections.abc import Iterable
|
|
17
16
|
from typing import TYPE_CHECKING, Any, Optional
|
|
18
17
|
|
|
19
18
|
from sqlalchemy import and_, delete, or_, select
|
|
@@ -24,6 +23,8 @@ from rucio.db.sqla import filter_thread_work, models
|
|
|
24
23
|
from rucio.db.sqla.session import read_session, transactional_session
|
|
25
24
|
|
|
26
25
|
if TYPE_CHECKING:
|
|
26
|
+
from collections.abc import Iterable
|
|
27
|
+
|
|
27
28
|
from sqlalchemy.orm import Session
|
|
28
29
|
|
|
29
30
|
|
|
@@ -88,7 +89,7 @@ def add_quarantined_replicas(rse_id: str, replicas: list[dict[str, Any]], *, ses
|
|
|
88
89
|
|
|
89
90
|
|
|
90
91
|
@transactional_session
|
|
91
|
-
def delete_quarantined_replicas(rse_id: str, replicas: Iterable[dict[str, Any]], *, session: "Session") -> None:
|
|
92
|
+
def delete_quarantined_replicas(rse_id: str, replicas: "Iterable[dict[str, Any]]", *, session: "Session") -> None:
|
|
92
93
|
"""
|
|
93
94
|
Delete file replicas.
|
|
94
95
|
|
|
@@ -158,7 +159,7 @@ def list_quarantined_replicas(rse_id: str, limit: int, worker_number: Optional[i
|
|
|
158
159
|
limit
|
|
159
160
|
)
|
|
160
161
|
for path, bytes_, scope, name, created_at in session.execute(stmt).all():
|
|
161
|
-
if
|
|
162
|
+
if (scope, name) not in quarantined_replicas:
|
|
162
163
|
quarantined_replicas[(scope, name)] = []
|
|
163
164
|
replicas_clause.append(and_(models.RSEFileAssociation.scope == scope,
|
|
164
165
|
models.RSEFileAssociation.name == name))
|