rucio-clients 34.1.0__tar.gz → 34.2.0__tar.gz
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-clients might be problematic. Click here for more details.
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/PKG-INFO +1 -1
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/bin/rucio +1 -1
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/baseclient.py +151 -129
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/downloadclient.py +3 -2
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/config.py +11 -9
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/utils.py +10 -10
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/vcsversion.py +3 -3
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/version.py +4 -4
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_clients.py +68 -16
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/AUTHORS.rst +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/ChangeLog +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/LICENSE +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/MANIFEST.in +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/README.rst +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/bin/rucio-admin +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/etc/rse-accounts.cfg.template +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/etc/rucio.cfg.atlas.client.template +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/etc/rucio.cfg.template +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/__init__.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/alembicrevision.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/__init__.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/accountclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/accountlimitclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/client.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/configclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/credentialclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/didclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/diracclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/exportclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/fileclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/importclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/lifetimeclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/lockclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/metaconventionsclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/pingclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/replicaclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/requestclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/rseclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/ruleclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/scopeclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/subscriptionclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/touchclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/client/uploadclient.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/__init__.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/cache.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/constants.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/constraints.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/didtype.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/exception.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/extra.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/logging.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/pcache.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/plugins.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/policy.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/__init__.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/atlas.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/belleii.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/cms.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/domatpc.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/escape.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/generic.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/generic_multi_vo.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/icecube.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/schema/lsst.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/stomp_utils.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/stopwatch.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/test_rucio_server.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/common/types.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/__init__.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/__init__.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/bittorrent.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/cache.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/dummy.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/gfal.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/globus.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/gsiftp.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/http_cache.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/mock.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/ngarc.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/posix.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/protocol.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/rclone.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/rfio.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/srm.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/ssh.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/storm.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/webdav.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/protocols/xrootd.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio/rse/rsemanager.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/lib/rucio_clients.egg-info/SOURCES.txt +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/pylintrc +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/pyproject.toml +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/requirements.txt +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/setup.cfg +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/setup.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/setuputil.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_abacus_account.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_abacus_collection_replica.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_abacus_rse.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_account.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_account_limits.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_api_external_representation.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_archive.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_auditor.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_auditor_hdfs.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_auditor_srmdumps.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_authentication.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_automatix.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_bad_replica.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_bb8.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_belleii.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_bin_rucio.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_boolean.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_common_types.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_config.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_conveyor.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_conveyor_submitter.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_counter.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_credential.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_curl.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_daemons.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_dataset_replicas.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_db.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_did.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_did_meta_plugins.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_didtype.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_download.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_dumper.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_dumper_consistency.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_dumper_data_model.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_dumper_path_parsing.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_filter_engine.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_heartbeat.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_hermes.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_identity.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_impl_upload_download.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_import_export.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_judge_cleaner.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_judge_evaluator.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_judge_injector.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_judge_repairer.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_lifetime.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_message.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_meta_conventions.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_meta_did.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_module_import.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_monitor.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_multi_vo.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_naming_convention.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_oauthmanager.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_oidc.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_permission.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_pfns.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_ping.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_preparer.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_qos.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_quarantined_replica.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_reaper.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_redirect.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_replica.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_replica_recoverer.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_replica_sorting.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_request.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_root_proxy.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_expression_parser.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_lfn2path.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_protocol_gfal2.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_protocol_gfal2_impl.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_protocol_posix.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_protocol_rclone.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_protocol_rsync.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_protocol_srm.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_protocol_ssh.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_protocol_webdav.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_protocol_xrootd.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rse_selector.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rucio_server.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_rule.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_schema_cms.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_scope.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_subscription.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_throttler.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_tpc.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_trace.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_transfer.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_transfer_plugins.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_undertaker.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_upload.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tests/test_utils.py +0 -0
- {rucio-clients-34.1.0 → rucio_clients-34.2.0}/tools/merge_rucio_configs.py +0 -0
|
@@ -1151,7 +1151,7 @@ def set_metadata(args):
|
|
|
1151
1151
|
client = get_client(args)
|
|
1152
1152
|
value = args.value
|
|
1153
1153
|
if args.key == 'lifetime':
|
|
1154
|
-
value = float(args.value)
|
|
1154
|
+
value = None if args.value.lower() == 'none' else float(args.value)
|
|
1155
1155
|
scope, name = get_scope(args.did, client)
|
|
1156
1156
|
client.set_metadata(scope=scope, name=name, key=args.key, value=value)
|
|
1157
1157
|
return SUCCESS
|
|
@@ -19,15 +19,18 @@
|
|
|
19
19
|
import errno
|
|
20
20
|
import getpass
|
|
21
21
|
import os
|
|
22
|
-
import
|
|
22
|
+
import secrets
|
|
23
23
|
import sys
|
|
24
24
|
import time
|
|
25
25
|
from configparser import NoOptionError, NoSectionError
|
|
26
|
+
from logging import Logger
|
|
26
27
|
from os import environ, fdopen, geteuid, makedirs, path
|
|
27
28
|
from shutil import move
|
|
28
29
|
from tempfile import mkstemp
|
|
30
|
+
from typing import Any, Generator, Optional
|
|
29
31
|
from urllib.parse import urlparse
|
|
30
32
|
|
|
33
|
+
import requests
|
|
31
34
|
from dogpile.cache import make_region
|
|
32
35
|
from requests import Response, Session
|
|
33
36
|
from requests.exceptions import ConnectionError
|
|
@@ -36,7 +39,7 @@ from requests.status_codes import codes
|
|
|
36
39
|
from rucio import version
|
|
37
40
|
from rucio.common import exception
|
|
38
41
|
from rucio.common.config import config_get, config_get_bool, config_get_int
|
|
39
|
-
from rucio.common.exception import CannotAuthenticate, ClientProtocolNotSupported, MissingClientParameter, MissingModuleException, NoAuthInformation, ServerConnectionException
|
|
42
|
+
from rucio.common.exception import CannotAuthenticate, ClientProtocolNotSupported, ConfigNotFound, MissingClientParameter, MissingModuleException, NoAuthInformation, ServerConnectionException
|
|
40
43
|
from rucio.common.extra import import_extras
|
|
41
44
|
from rucio.common.utils import build_url, get_tmp_dir, my_key_generator, parse_response, setup_logger, ssh_sign
|
|
42
45
|
|
|
@@ -64,7 +67,7 @@ def choice(hosts):
|
|
|
64
67
|
:param hosts: Lost of hosts
|
|
65
68
|
:return: A randomly selected host.
|
|
66
69
|
"""
|
|
67
|
-
return
|
|
70
|
+
return secrets.choice(hosts)
|
|
68
71
|
|
|
69
72
|
|
|
70
73
|
class BaseClient:
|
|
@@ -76,7 +79,17 @@ class BaseClient:
|
|
|
76
79
|
TOKEN_PREFIX = 'auth_token_'
|
|
77
80
|
TOKEN_EXP_PREFIX = 'auth_token_exp_'
|
|
78
81
|
|
|
79
|
-
def __init__(self,
|
|
82
|
+
def __init__(self,
|
|
83
|
+
rucio_host: Optional[str] = None,
|
|
84
|
+
auth_host: Optional[str] = None,
|
|
85
|
+
account: Optional[str] = None,
|
|
86
|
+
ca_cert: Optional[str] = None,
|
|
87
|
+
auth_type: Optional[str] = None,
|
|
88
|
+
creds: Optional[dict[str, Any]] = None,
|
|
89
|
+
timeout: Optional[int] = 600,
|
|
90
|
+
user_agent: Optional[str] = 'rucio-clients',
|
|
91
|
+
vo: Optional[str] = None,
|
|
92
|
+
logger: Logger = LOG) -> None:
|
|
80
93
|
"""
|
|
81
94
|
Constructor of the BaseClient.
|
|
82
95
|
:param rucio_host: The address of the rucio server, if None it is read from the config file.
|
|
@@ -94,9 +107,8 @@ class BaseClient:
|
|
|
94
107
|
"""
|
|
95
108
|
|
|
96
109
|
self.host = rucio_host
|
|
97
|
-
self.list_hosts = []
|
|
98
110
|
self.auth_host = auth_host
|
|
99
|
-
self.logger = logger
|
|
111
|
+
self.logger = logger
|
|
100
112
|
self.session = Session()
|
|
101
113
|
self.user_agent = "%s/%s" % (user_agent, version.version_string()) # e.g. "rucio-clients/0.2.13"
|
|
102
114
|
sys.argv[0] = sys.argv[0].split('/')[-1]
|
|
@@ -113,110 +125,26 @@ class BaseClient:
|
|
|
113
125
|
|
|
114
126
|
try:
|
|
115
127
|
self.trace_host = config_get('trace', 'trace_host')
|
|
116
|
-
except (NoOptionError, NoSectionError):
|
|
128
|
+
except (NoOptionError, NoSectionError, ConfigNotFound):
|
|
117
129
|
self.trace_host = self.host
|
|
118
130
|
self.logger.debug('No trace_host passed. Using rucio_host instead')
|
|
119
131
|
|
|
132
|
+
self.list_hosts = [self.host]
|
|
120
133
|
self.account = account
|
|
121
134
|
self.vo = vo
|
|
122
135
|
self.ca_cert = ca_cert
|
|
123
|
-
self.
|
|
124
|
-
self.creds = creds
|
|
125
|
-
self.auth_token = None
|
|
126
|
-
self.auth_token_file_path = config_get('client', 'auth_token_file_path', False, None)
|
|
136
|
+
self.auth_token = ""
|
|
127
137
|
self.headers = {}
|
|
128
138
|
self.timeout = timeout
|
|
129
139
|
self.request_retries = self.REQUEST_RETRIES
|
|
130
140
|
self.token_exp_epoch = None
|
|
131
|
-
self.token_exp_epoch_file = None
|
|
132
141
|
self.auth_oidc_refresh_active = config_get_bool('client', 'auth_oidc_refresh_active', False, False)
|
|
142
|
+
|
|
133
143
|
# defining how many minutes before token expires, oidc refresh (if active) should start
|
|
134
144
|
self.auth_oidc_refresh_before_exp = config_get_int('client', 'auth_oidc_refresh_before_exp', False, 20)
|
|
135
145
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if 'RUCIO_AUTH_TYPE' in environ:
|
|
139
|
-
if environ['RUCIO_AUTH_TYPE'] not in ['userpass', 'x509', 'x509_proxy', 'gss', 'ssh', 'saml', 'oidc']:
|
|
140
|
-
raise MissingClientParameter('Possible RUCIO_AUTH_TYPE values: userpass, x509, x509_proxy, gss, ssh, saml, oidc, vs. ' + environ['RUCIO_AUTH_TYPE'])
|
|
141
|
-
self.auth_type = environ['RUCIO_AUTH_TYPE']
|
|
142
|
-
else:
|
|
143
|
-
try:
|
|
144
|
-
self.auth_type = config_get('client', 'auth_type')
|
|
145
|
-
except (NoOptionError, NoSectionError) as error:
|
|
146
|
-
raise MissingClientParameter('Option \'%s\' cannot be found in config file' % error.args[0])
|
|
147
|
-
|
|
148
|
-
if self.auth_type == 'oidc':
|
|
149
|
-
if not self.creds:
|
|
150
|
-
self.creds = {}
|
|
151
|
-
# if there are defautl values, check if rucio.cfg does not specify them, otherwise put default
|
|
152
|
-
if 'oidc_refresh_lifetime' not in self.creds or self.creds['oidc_refresh_lifetime'] is None:
|
|
153
|
-
self.creds['oidc_refresh_lifetime'] = config_get('client', 'oidc_refresh_lifetime', False, None)
|
|
154
|
-
if 'oidc_issuer' not in self.creds or self.creds['oidc_issuer'] is None:
|
|
155
|
-
self.creds['oidc_issuer'] = config_get('client', 'oidc_issuer', False, None)
|
|
156
|
-
if 'oidc_audience' not in self.creds or self.creds['oidc_audience'] is None:
|
|
157
|
-
self.creds['oidc_audience'] = config_get('client', 'oidc_audience', False, None)
|
|
158
|
-
if 'oidc_auto' not in self.creds or self.creds['oidc_auto'] is False:
|
|
159
|
-
self.creds['oidc_auto'] = config_get_bool('client', 'oidc_auto', False, False)
|
|
160
|
-
if self.creds['oidc_auto']:
|
|
161
|
-
if 'oidc_username' not in self.creds or self.creds['oidc_username'] is None:
|
|
162
|
-
self.creds['oidc_username'] = config_get('client', 'oidc_username', False, None)
|
|
163
|
-
if 'oidc_password' not in self.creds or self.creds['oidc_password'] is None:
|
|
164
|
-
self.creds['oidc_password'] = config_get('client', 'oidc_password', False, None)
|
|
165
|
-
if 'oidc_scope' not in self.creds or self.creds['oidc_scope'] == 'openid profile':
|
|
166
|
-
self.creds['oidc_scope'] = config_get('client', 'oidc_scope', False, 'openid profile')
|
|
167
|
-
if 'oidc_polling' not in self.creds or self.creds['oidc_polling'] is False:
|
|
168
|
-
self.creds['oidc_polling'] = config_get_bool('client', 'oidc_polling', False, False)
|
|
169
|
-
|
|
170
|
-
if not self.creds:
|
|
171
|
-
self.logger.debug('No creds passed. Trying to get it from the config file.')
|
|
172
|
-
self.creds = {}
|
|
173
|
-
try:
|
|
174
|
-
if self.auth_type in ['userpass', 'saml']:
|
|
175
|
-
self.creds['username'] = config_get('client', 'username')
|
|
176
|
-
self.creds['password'] = config_get('client', 'password')
|
|
177
|
-
elif self.auth_type == 'x509':
|
|
178
|
-
if "RUCIO_CLIENT_CERT" in environ:
|
|
179
|
-
client_cert = environ["RUCIO_CLIENT_CERT"]
|
|
180
|
-
else:
|
|
181
|
-
client_cert = config_get('client', 'client_cert')
|
|
182
|
-
self.creds['client_cert'] = path.abspath(path.expanduser(path.expandvars(client_cert)))
|
|
183
|
-
if not path.exists(self.creds['client_cert']):
|
|
184
|
-
raise MissingClientParameter('X.509 client certificate not found: %s' % self.creds['client_cert'])
|
|
185
|
-
|
|
186
|
-
if "RUCIO_CLIENT_KEY" in environ:
|
|
187
|
-
client_key = environ["RUCIO_CLIENT_KEY"]
|
|
188
|
-
else:
|
|
189
|
-
client_key = config_get('client', 'client_key')
|
|
190
|
-
self.creds['client_key'] = path.abspath(path.expanduser(path.expandvars(client_key)))
|
|
191
|
-
if not path.exists(self.creds['client_key']):
|
|
192
|
-
raise MissingClientParameter('X.509 client key not found: %s' % self.creds['client_key'])
|
|
193
|
-
else:
|
|
194
|
-
perms = oct(os.stat(self.creds['client_key']).st_mode)[-3:]
|
|
195
|
-
if perms not in ['400', '600']:
|
|
196
|
-
raise CannotAuthenticate('X.509 authentication selected, but private key (%s) permissions are liberal (required: 400 or 600, found: %s)' % (self.creds['client_key'], perms))
|
|
197
|
-
|
|
198
|
-
elif self.auth_type == 'x509_proxy':
|
|
199
|
-
try:
|
|
200
|
-
self.creds['client_proxy'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'client_x509_proxy'))))
|
|
201
|
-
except NoOptionError:
|
|
202
|
-
# Recreate the classic GSI logic for locating the proxy:
|
|
203
|
-
# - $X509_USER_PROXY, if it is set.
|
|
204
|
-
# - /tmp/x509up_u`id -u` otherwise.
|
|
205
|
-
# If neither exists (at this point, we don't care if it exists but is invalid), then rethrow
|
|
206
|
-
if 'X509_USER_PROXY' in environ:
|
|
207
|
-
self.creds['client_proxy'] = environ['X509_USER_PROXY']
|
|
208
|
-
else:
|
|
209
|
-
fname = '/tmp/x509up_u%d' % geteuid()
|
|
210
|
-
if path.exists(fname):
|
|
211
|
-
self.creds['client_proxy'] = fname
|
|
212
|
-
else:
|
|
213
|
-
raise MissingClientParameter('Cannot find a valid X509 proxy; not in %s, $X509_USER_PROXY not set, and '
|
|
214
|
-
'\'x509_proxy\' not set in the configuration file.' % fname)
|
|
215
|
-
elif self.auth_type == 'ssh':
|
|
216
|
-
self.creds['ssh_private_key'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'ssh_private_key'))))
|
|
217
|
-
except (NoOptionError, NoSectionError) as error:
|
|
218
|
-
if error.args[0] != 'client_key':
|
|
219
|
-
raise MissingClientParameter('Option \'%s\' cannot be found in config file' % error.args[0])
|
|
146
|
+
self.auth_type = self._get_auth_type(auth_type)
|
|
147
|
+
self.creds = self._get_creds(creds)
|
|
220
148
|
|
|
221
149
|
rucio_scheme = urlparse(self.host).scheme
|
|
222
150
|
auth_scheme = urlparse(self.auth_host).scheme
|
|
@@ -238,8 +166,6 @@ class BaseClient:
|
|
|
238
166
|
self.logger.debug('No ca_cert found in configuration. Falling back to Mozilla default CA bundle (certifi).')
|
|
239
167
|
self.ca_cert = True
|
|
240
168
|
|
|
241
|
-
self.list_hosts = [self.host]
|
|
242
|
-
|
|
243
169
|
if account is None:
|
|
244
170
|
self.logger.debug('No account passed. Trying to get it from the RUCIO_ACCOUNT environment variable or the config file.')
|
|
245
171
|
try:
|
|
@@ -262,30 +188,126 @@ class BaseClient:
|
|
|
262
188
|
self.logger.debug('No VO found. Using default VO.')
|
|
263
189
|
self.vo = 'def'
|
|
264
190
|
|
|
265
|
-
|
|
191
|
+
self.auth_token_file_path, self.token_exp_epoch_file, self.token_file, self.token_path = self._get_auth_tokens()
|
|
192
|
+
self.__authenticate()
|
|
266
193
|
|
|
194
|
+
try:
|
|
195
|
+
self.request_retries = config_get_int('client', 'request_retries')
|
|
196
|
+
except (NoOptionError, ConfigNotFound):
|
|
197
|
+
self.logger.debug('request_retries not specified in config file. Taking default.')
|
|
198
|
+
except ValueError:
|
|
199
|
+
self.logger.debug('request_retries must be an integer. Taking default.')
|
|
200
|
+
|
|
201
|
+
def _get_auth_tokens(self) -> tuple[Optional[str], str, str, str]:
|
|
267
202
|
# if token file path is defined in the rucio.cfg file, use that file. Currently this prevents authenticating as another user or VO.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
203
|
+
auth_token_file_path = config_get('client', 'auth_token_file_path', False, None)
|
|
204
|
+
token_filename_suffix = "for_default_account" if self.account is None else "for_account_" + self.account
|
|
205
|
+
|
|
206
|
+
if auth_token_file_path:
|
|
207
|
+
token_file = auth_token_file_path
|
|
208
|
+
token_path = '/'.join(auth_token_file_path.split('/')[:-1])
|
|
209
|
+
|
|
271
210
|
else:
|
|
272
|
-
|
|
211
|
+
token_path = self.TOKEN_PATH_PREFIX + getpass.getuser()
|
|
273
212
|
if self.vo != 'def':
|
|
274
|
-
|
|
275
|
-
self.token_file = self.token_path + '/' + self.TOKEN_PREFIX + token_filename_suffix
|
|
213
|
+
token_path += '@%s' % self.vo
|
|
276
214
|
|
|
277
|
-
|
|
215
|
+
token_file = token_path + '/' + self.TOKEN_PREFIX + token_filename_suffix
|
|
278
216
|
|
|
279
|
-
self.
|
|
217
|
+
token_exp_epoch_file = token_path + '/' + self.TOKEN_EXP_PREFIX + token_filename_suffix
|
|
218
|
+
return auth_token_file_path, token_exp_epoch_file, token_file, token_path
|
|
280
219
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
220
|
+
def _get_auth_type(self, auth_type: Optional[str]) -> str:
|
|
221
|
+
if auth_type is None:
|
|
222
|
+
self.logger.debug('No auth_type passed. Trying to get it from the environment variable RUCIO_AUTH_TYPE and config file.')
|
|
223
|
+
if 'RUCIO_AUTH_TYPE' in environ:
|
|
224
|
+
if environ['RUCIO_AUTH_TYPE'] not in ['userpass', 'x509', 'x509_proxy', 'gss', 'ssh', 'saml', 'oidc']:
|
|
225
|
+
raise MissingClientParameter('Possible RUCIO_AUTH_TYPE values: userpass, x509, x509_proxy, gss, ssh, saml, oidc, vs. ' + environ['RUCIO_AUTH_TYPE'])
|
|
226
|
+
auth_type = environ['RUCIO_AUTH_TYPE']
|
|
227
|
+
else:
|
|
228
|
+
try:
|
|
229
|
+
auth_type = config_get('client', 'auth_type')
|
|
230
|
+
except (NoOptionError, NoSectionError) as error:
|
|
231
|
+
raise MissingClientParameter('Option \'%s\' cannot be found in config file' % error.args[0])
|
|
232
|
+
return auth_type
|
|
233
|
+
|
|
234
|
+
def _get_creds(self, creds: Optional[dict[str, Any]]) -> dict[str, Any]:
|
|
235
|
+
if self.auth_type == 'oidc':
|
|
236
|
+
if not creds:
|
|
237
|
+
creds = {}
|
|
238
|
+
# if there are defautl values, check if rucio.cfg does not specify them, otherwise put default
|
|
239
|
+
if 'oidc_refresh_lifetime' not in creds or creds['oidc_refresh_lifetime'] is None:
|
|
240
|
+
creds['oidc_refresh_lifetime'] = config_get('client', 'oidc_refresh_lifetime', False, None)
|
|
241
|
+
if 'oidc_issuer' not in creds or creds['oidc_issuer'] is None:
|
|
242
|
+
creds['oidc_issuer'] = config_get('client', 'oidc_issuer', False, None)
|
|
243
|
+
if 'oidc_audience' not in creds or creds['oidc_audience'] is None:
|
|
244
|
+
creds['oidc_audience'] = config_get('client', 'oidc_audience', False, None)
|
|
245
|
+
if 'oidc_auto' not in creds or creds['oidc_auto'] is False:
|
|
246
|
+
creds['oidc_auto'] = config_get_bool('client', 'oidc_auto', False, False)
|
|
247
|
+
if creds['oidc_auto']:
|
|
248
|
+
if 'oidc_username' not in creds or creds['oidc_username'] is None:
|
|
249
|
+
creds['oidc_username'] = config_get('client', 'oidc_username', False, None)
|
|
250
|
+
if 'oidc_password' not in creds or creds['oidc_password'] is None:
|
|
251
|
+
creds['oidc_password'] = config_get('client', 'oidc_password', False, None)
|
|
252
|
+
if 'oidc_scope' not in creds or creds['oidc_scope'] == 'openid profile':
|
|
253
|
+
creds['oidc_scope'] = config_get('client', 'oidc_scope', False, 'openid profile')
|
|
254
|
+
if 'oidc_polling' not in creds or creds['oidc_polling'] is False:
|
|
255
|
+
creds['oidc_polling'] = config_get_bool('client', 'oidc_polling', False, False)
|
|
256
|
+
|
|
257
|
+
if creds is None:
|
|
258
|
+
self.logger.debug('No creds passed. Trying to get it from the config file.')
|
|
259
|
+
creds = {}
|
|
260
|
+
try:
|
|
261
|
+
if self.auth_type in ['userpass', 'saml']:
|
|
262
|
+
creds['username'] = config_get('client', 'username')
|
|
263
|
+
creds['password'] = config_get('client', 'password')
|
|
264
|
+
elif self.auth_type == 'x509':
|
|
265
|
+
if "RUCIO_CLIENT_CERT" in environ:
|
|
266
|
+
client_cert = environ["RUCIO_CLIENT_CERT"]
|
|
267
|
+
else:
|
|
268
|
+
client_cert = config_get('client', 'client_cert')
|
|
269
|
+
creds['client_cert'] = path.abspath(path.expanduser(path.expandvars(client_cert)))
|
|
270
|
+
if not path.exists(creds['client_cert']):
|
|
271
|
+
raise MissingClientParameter('X.509 client certificate not found: %s' % creds['client_cert'])
|
|
272
|
+
|
|
273
|
+
if "RUCIO_CLIENT_KEY" in environ:
|
|
274
|
+
client_key = environ["RUCIO_CLIENT_KEY"]
|
|
275
|
+
else:
|
|
276
|
+
client_key = config_get('client', 'client_key')
|
|
277
|
+
creds['client_key'] = path.abspath(path.expanduser(path.expandvars(client_key)))
|
|
278
|
+
if not path.exists(creds['client_key']):
|
|
279
|
+
raise MissingClientParameter('X.509 client key not found: %s' % creds['client_key'])
|
|
280
|
+
else:
|
|
281
|
+
perms = oct(os.stat(creds['client_key']).st_mode)[-3:]
|
|
282
|
+
if perms not in ['400', '600']:
|
|
283
|
+
raise CannotAuthenticate('X.509 authentication selected, but private key (%s) permissions are liberal (required: 400 or 600, found: %s)' % (creds['client_key'], perms))
|
|
284
|
+
|
|
285
|
+
elif self.auth_type == 'x509_proxy':
|
|
286
|
+
try:
|
|
287
|
+
creds['client_proxy'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'client_x509_proxy'))))
|
|
288
|
+
except NoOptionError:
|
|
289
|
+
# Recreate the classic GSI logic for locating the proxy:
|
|
290
|
+
# - $X509_USER_PROXY, if it is set.
|
|
291
|
+
# - /tmp/x509up_u`id -u` otherwise.
|
|
292
|
+
# If neither exists (at this point, we don't care if it exists but is invalid), then rethrow
|
|
293
|
+
if 'X509_USER_PROXY' in environ:
|
|
294
|
+
creds['client_proxy'] = environ['X509_USER_PROXY']
|
|
295
|
+
else:
|
|
296
|
+
fname = '/tmp/x509up_u%d' % geteuid()
|
|
297
|
+
if path.exists(fname):
|
|
298
|
+
creds['client_proxy'] = fname
|
|
299
|
+
else:
|
|
300
|
+
raise MissingClientParameter(
|
|
301
|
+
'Cannot find a valid X509 proxy; not in %s, $X509_USER_PROXY not set, and '
|
|
302
|
+
'\'x509_proxy\' not set in the configuration file.' % fname)
|
|
303
|
+
elif self.auth_type == 'ssh':
|
|
304
|
+
creds['ssh_private_key'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'ssh_private_key'))))
|
|
305
|
+
except (NoOptionError, NoSectionError) as error:
|
|
306
|
+
if error.args[0] != 'client_key':
|
|
307
|
+
raise MissingClientParameter('Option \'%s\' cannot be found in config file' % error.args[0])
|
|
308
|
+
return creds
|
|
287
309
|
|
|
288
|
-
def _get_exception(self, headers, status_code=None, data=None):
|
|
310
|
+
def _get_exception(self, headers: dict[str, str], status_code: Optional[int] = None, data=None) -> tuple[type[exception.RucioException], str]:
|
|
289
311
|
"""
|
|
290
312
|
Helper method to parse an error string send by the server and transform it into the corresponding rucio exception.
|
|
291
313
|
|
|
@@ -316,7 +338,7 @@ class BaseClient:
|
|
|
316
338
|
else:
|
|
317
339
|
return exception.RucioException, "%s: %s" % (exc_cls, exc_msg)
|
|
318
340
|
|
|
319
|
-
def _load_json_data(self, response):
|
|
341
|
+
def _load_json_data(self, response: requests.Response) -> Generator[Any, Any, Any]:
|
|
320
342
|
"""
|
|
321
343
|
Helper method to correctly load json data based on the content type of the http response.
|
|
322
344
|
|
|
@@ -332,13 +354,13 @@ class BaseClient:
|
|
|
332
354
|
if response.text:
|
|
333
355
|
yield response.text
|
|
334
356
|
|
|
335
|
-
def _reduce_data(self, data, maxlen=132):
|
|
357
|
+
def _reduce_data(self, data, maxlen: int = 132) -> str:
|
|
336
358
|
text = data if isinstance(data, str) else data.decode("utf-8")
|
|
337
359
|
if len(text) > maxlen:
|
|
338
360
|
text = "%s ... %s" % (text[:maxlen - 15], text[-10:])
|
|
339
361
|
return text
|
|
340
362
|
|
|
341
|
-
def _back_off(self, retry_number, reason):
|
|
363
|
+
def _back_off(self, retry_number: int, reason: str) -> None:
|
|
342
364
|
"""
|
|
343
365
|
Sleep a certain amount of time which increases with the retry count
|
|
344
366
|
:param retry_number: the retry iteration
|
|
@@ -433,7 +455,7 @@ class BaseClient:
|
|
|
433
455
|
raise ServerConnectionException
|
|
434
456
|
return result
|
|
435
457
|
|
|
436
|
-
def __get_token_userpass(self):
|
|
458
|
+
def __get_token_userpass(self) -> bool:
|
|
437
459
|
"""
|
|
438
460
|
Sends a request to get an auth token from the server and stores it as a class attribute. Uses username/password.
|
|
439
461
|
|
|
@@ -469,7 +491,7 @@ class BaseClient:
|
|
|
469
491
|
self.auth_token = result.headers['x-rucio-auth-token']
|
|
470
492
|
return True
|
|
471
493
|
|
|
472
|
-
def __refresh_token_OIDC(self):
|
|
494
|
+
def __refresh_token_OIDC(self) -> bool:
|
|
473
495
|
"""
|
|
474
496
|
Checks if there is active refresh token and if so returns
|
|
475
497
|
either active token with expiration timestamp or requests a new
|
|
@@ -523,7 +545,7 @@ class BaseClient:
|
|
|
523
545
|
\nRucio Auth Server when attempting token refresh.")
|
|
524
546
|
return False
|
|
525
547
|
|
|
526
|
-
def __get_token_OIDC(self):
|
|
548
|
+
def __get_token_OIDC(self) -> bool:
|
|
527
549
|
"""
|
|
528
550
|
First authenticates the user via a Identity Provider server
|
|
529
551
|
(with user's username & password), by specifying oidc_scope,
|
|
@@ -647,7 +669,7 @@ class BaseClient:
|
|
|
647
669
|
self.__refresh_token_OIDC()
|
|
648
670
|
return True
|
|
649
671
|
|
|
650
|
-
def __get_token_x509(self):
|
|
672
|
+
def __get_token_x509(self) -> bool:
|
|
651
673
|
"""
|
|
652
674
|
Sends a request to get an auth token from the server and stores it as a class attribute. Uses x509 authentication.
|
|
653
675
|
|
|
@@ -664,7 +686,7 @@ class BaseClient:
|
|
|
664
686
|
url = build_url(self.auth_host, path='auth/x509_proxy')
|
|
665
687
|
client_cert = self.creds['client_proxy']
|
|
666
688
|
|
|
667
|
-
if not path.exists(client_cert):
|
|
689
|
+
if (client_cert is not None) and not (path.exists(client_cert)):
|
|
668
690
|
self.logger.error('given client cert (%s) doesn\'t exist' % client_cert)
|
|
669
691
|
return False
|
|
670
692
|
if client_key is not None and not path.exists(client_key):
|
|
@@ -692,7 +714,7 @@ class BaseClient:
|
|
|
692
714
|
self.auth_token = result.headers['x-rucio-auth-token']
|
|
693
715
|
return True
|
|
694
716
|
|
|
695
|
-
def __get_token_ssh(self):
|
|
717
|
+
def __get_token_ssh(self) -> bool:
|
|
696
718
|
"""
|
|
697
719
|
Sends a request to get an auth token from the server and stores it as a class attribute. Uses SSH key exchange authentication.
|
|
698
720
|
|
|
@@ -748,7 +770,7 @@ class BaseClient:
|
|
|
748
770
|
self.auth_token = result.headers['x-rucio-auth-token']
|
|
749
771
|
return True
|
|
750
772
|
|
|
751
|
-
def __get_token_gss(self):
|
|
773
|
+
def __get_token_gss(self) -> bool:
|
|
752
774
|
"""
|
|
753
775
|
Sends a request to get an auth token from the server and stores it as a class attribute. Uses Kerberos authentication.
|
|
754
776
|
|
|
@@ -774,7 +796,7 @@ class BaseClient:
|
|
|
774
796
|
self.auth_token = result.headers['x-rucio-auth-token']
|
|
775
797
|
return True
|
|
776
798
|
|
|
777
|
-
def __get_token_saml(self):
|
|
799
|
+
def __get_token_saml(self) -> bool:
|
|
778
800
|
"""
|
|
779
801
|
Sends a request to get an auth token from the server and stores it as a class attribute. Uses saml authentication.
|
|
780
802
|
|
|
@@ -804,7 +826,7 @@ class BaseClient:
|
|
|
804
826
|
self.auth_token = result.headers['X-Rucio-Auth-Token']
|
|
805
827
|
return True
|
|
806
828
|
|
|
807
|
-
def __get_token(self):
|
|
829
|
+
def __get_token(self) -> None:
|
|
808
830
|
"""
|
|
809
831
|
Calls the corresponding method to receive an auth token depending on the auth type. To be used if a 401 - Unauthorized error is received.
|
|
810
832
|
"""
|
|
@@ -846,7 +868,7 @@ class BaseClient:
|
|
|
846
868
|
if self.auth_token is None:
|
|
847
869
|
raise CannotAuthenticate('cannot get an auth token from server')
|
|
848
870
|
|
|
849
|
-
def __read_token(self):
|
|
871
|
+
def __read_token(self) -> bool:
|
|
850
872
|
"""
|
|
851
873
|
Checks if a local token file exists and reads the token from it.
|
|
852
874
|
|
|
@@ -868,7 +890,7 @@ class BaseClient:
|
|
|
868
890
|
self.logger.debug('got token from file')
|
|
869
891
|
return True
|
|
870
892
|
|
|
871
|
-
def __write_token(self):
|
|
893
|
+
def __write_token(self) -> None:
|
|
872
894
|
"""
|
|
873
895
|
Write the current auth_token to the local token file.
|
|
874
896
|
"""
|
|
@@ -895,7 +917,7 @@ class BaseClient:
|
|
|
895
917
|
except Exception:
|
|
896
918
|
raise
|
|
897
919
|
|
|
898
|
-
def __authenticate(self):
|
|
920
|
+
def __authenticate(self) -> None:
|
|
899
921
|
"""
|
|
900
922
|
Main method for authentication. It first tries to read a locally saved token. If not available it requests a new one.
|
|
901
923
|
"""
|
|
@@ -18,6 +18,7 @@ import itertools
|
|
|
18
18
|
import logging
|
|
19
19
|
import os
|
|
20
20
|
import random
|
|
21
|
+
import secrets
|
|
21
22
|
import shutil
|
|
22
23
|
import signal
|
|
23
24
|
import subprocess
|
|
@@ -762,7 +763,7 @@ class DownloadClient:
|
|
|
762
763
|
logger = self.logger
|
|
763
764
|
trace_custom_fields['uuid'] = generate_uuid()
|
|
764
765
|
|
|
765
|
-
rpc_secret = '%x' % (
|
|
766
|
+
rpc_secret = '%x' % (secrets.randbits(64))
|
|
766
767
|
rpc_auth = 'token:%s' % rpc_secret
|
|
767
768
|
rpcproc, aria_rpc = self._start_aria2c_rpc(rpc_secret)
|
|
768
769
|
|
|
@@ -823,7 +824,7 @@ class DownloadClient:
|
|
|
823
824
|
|
|
824
825
|
# trying up to 3 random ports
|
|
825
826
|
for attempt in range(3):
|
|
826
|
-
port = random.randint(1024, 65534)
|
|
827
|
+
port = random.randint(1024, 65534) # noqa: S311
|
|
827
828
|
logger(logging.DEBUG, 'Trying to start rpc server on port: %d' % port)
|
|
828
829
|
try:
|
|
829
830
|
to_exec = cmd % (os.getpid(), rpc_secret, port)
|
|
@@ -188,12 +188,12 @@ def config_get(
|
|
|
188
188
|
"""
|
|
189
189
|
try:
|
|
190
190
|
return convert_type_fnc(get_config().get(section, option))
|
|
191
|
-
except (configparser.NoOptionError, configparser.NoSectionError,
|
|
191
|
+
except (configparser.NoOptionError, configparser.NoSectionError, ConfigNotFound) as err:
|
|
192
192
|
try:
|
|
193
193
|
legacy_config = get_legacy_config(section, option)
|
|
194
194
|
if legacy_config is not None:
|
|
195
195
|
return convert_type_fnc(legacy_config)
|
|
196
|
-
except
|
|
196
|
+
except ConfigNotFound:
|
|
197
197
|
pass
|
|
198
198
|
|
|
199
199
|
from rucio.common.utils import is_client
|
|
@@ -729,7 +729,7 @@ def get_lfn2pfn_algorithm_default():
|
|
|
729
729
|
default_lfn2pfn = "hash"
|
|
730
730
|
try:
|
|
731
731
|
default_lfn2pfn = config_get('policy', 'lfn2pfn_algorithm_default')
|
|
732
|
-
except (configparser.NoOptionError, configparser.NoSectionError, RuntimeError):
|
|
732
|
+
except (configparser.NoOptionError, configparser.NoSectionError, ConfigNotFound, RuntimeError):
|
|
733
733
|
pass
|
|
734
734
|
return default_lfn2pfn
|
|
735
735
|
|
|
@@ -785,11 +785,13 @@ class Config:
|
|
|
785
785
|
configs = [os.path.join(confdir, 'rucio.cfg') for confdir in get_config_dirs()]
|
|
786
786
|
self.configfile = next(iter(filter(os.path.exists, configs)), None)
|
|
787
787
|
if self.configfile is None:
|
|
788
|
-
raise
|
|
789
|
-
|
|
790
|
-
|
|
788
|
+
raise ConfigNotFound(
|
|
789
|
+
'Could not load Rucio configuration file. '
|
|
790
|
+
'Rucio looked in the following paths for a configuration file, in order:'
|
|
791
|
+
'\n\t' + '\n\t'.join(configs))
|
|
791
792
|
|
|
792
793
|
if not self.parser.read(self.configfile) == [self.configfile]:
|
|
793
|
-
raise
|
|
794
|
-
|
|
795
|
-
|
|
794
|
+
raise ConfigNotFound(
|
|
795
|
+
'Could not load Rucio configuration file. '
|
|
796
|
+
'Rucio tried loading the following configuration file:'
|
|
797
|
+
'\n\t' + self.configfile)
|
|
@@ -50,7 +50,7 @@ from xml.etree import ElementTree
|
|
|
50
50
|
import requests
|
|
51
51
|
|
|
52
52
|
from rucio.common.config import config_get, config_has_section
|
|
53
|
-
from rucio.common.exception import DIDFilterSyntaxError, DuplicateCriteriaInDIDFilter, InputValidationError, InvalidType, MetalinkJsonParsingError, MissingModuleException, PolicyPackageVersionError, RucioException
|
|
53
|
+
from rucio.common.exception import ConfigNotFound, DIDFilterSyntaxError, DuplicateCriteriaInDIDFilter, InputValidationError, InvalidType, MetalinkJsonParsingError, MissingModuleException, PolicyPackageVersionError, RucioException
|
|
54
54
|
from rucio.common.extra import import_extras
|
|
55
55
|
from rucio.common.plugins import PolicyPackageAlgorithms
|
|
56
56
|
from rucio.common.types import InternalAccount, InternalScope
|
|
@@ -147,7 +147,7 @@ def build_url(url, path=None, params=None, doseq=False):
|
|
|
147
147
|
return complete_url
|
|
148
148
|
|
|
149
149
|
|
|
150
|
-
def all_oidc_req_claims_present(scope, audience, required_scope, required_audience,
|
|
150
|
+
def all_oidc_req_claims_present(scope, audience, required_scope, required_audience, separator=" "):
|
|
151
151
|
"""
|
|
152
152
|
Checks if both of the following statements are true:
|
|
153
153
|
- all items in required_scope are present in scope string
|
|
@@ -159,7 +159,7 @@ def all_oidc_req_claims_present(scope, audience, required_scope, required_audien
|
|
|
159
159
|
:params audience: list of strings or one string where items are separated by a separator input variable
|
|
160
160
|
:params required_scope: list of strings or one string where items are separated by a separator input variable
|
|
161
161
|
:params required_audience: list of strings or one string where items are separated by a separator input variable
|
|
162
|
-
:params
|
|
162
|
+
:params separator: separator string, space by default
|
|
163
163
|
:returns : True or False
|
|
164
164
|
"""
|
|
165
165
|
if not scope:
|
|
@@ -183,24 +183,24 @@ def all_oidc_req_claims_present(scope, audience, required_scope, required_audien
|
|
|
183
183
|
audience = str(audience)
|
|
184
184
|
required_scope = str(required_scope)
|
|
185
185
|
required_audience = str(required_audience)
|
|
186
|
-
req_scope_present = all(elem in scope.split(
|
|
187
|
-
req_audience_present = all(elem in audience.split(
|
|
186
|
+
req_scope_present = all(elem in scope.split(separator) for elem in required_scope.split(separator))
|
|
187
|
+
req_audience_present = all(elem in audience.split(separator) for elem in required_audience.split(separator))
|
|
188
188
|
return req_scope_present and req_audience_present
|
|
189
189
|
elif (isinstance(scope, list) and isinstance(audience, list) and isinstance(required_scope, str) and isinstance(required_audience, str)):
|
|
190
190
|
scope = [str(it) for it in scope]
|
|
191
191
|
audience = [str(it) for it in audience]
|
|
192
192
|
required_scope = str(required_scope)
|
|
193
193
|
required_audience = str(required_audience)
|
|
194
|
-
req_scope_present = all(elem in scope for elem in required_scope.split(
|
|
195
|
-
req_audience_present = all(elem in audience for elem in required_audience.split(
|
|
194
|
+
req_scope_present = all(elem in scope for elem in required_scope.split(separator))
|
|
195
|
+
req_audience_present = all(elem in audience for elem in required_audience.split(separator))
|
|
196
196
|
return req_scope_present and req_audience_present
|
|
197
197
|
elif (isinstance(scope, str) and isinstance(audience, str) and isinstance(required_scope, list) and isinstance(required_audience, list)):
|
|
198
198
|
scope = str(scope)
|
|
199
199
|
audience = str(audience)
|
|
200
200
|
required_scope = [str(it) for it in required_scope]
|
|
201
201
|
required_audience = [str(it) for it in required_audience]
|
|
202
|
-
req_scope_present = all(elem in scope.split(
|
|
203
|
-
req_audience_present = all(elem in audience.split(
|
|
202
|
+
req_scope_present = all(elem in scope.split(separator) for elem in required_scope)
|
|
203
|
+
req_audience_present = all(elem in audience.split(separator) for elem in required_audience)
|
|
204
204
|
return req_scope_present and req_audience_present
|
|
205
205
|
else:
|
|
206
206
|
return False
|
|
@@ -1844,7 +1844,7 @@ def is_client():
|
|
|
1844
1844
|
client_mode = True
|
|
1845
1845
|
else:
|
|
1846
1846
|
client_mode = False
|
|
1847
|
-
except RuntimeError:
|
|
1847
|
+
except (RuntimeError, ConfigNotFound):
|
|
1848
1848
|
# If no configuration file is found the default value should be True
|
|
1849
1849
|
client_mode = True
|
|
1850
1850
|
else:
|
|
@@ -4,8 +4,8 @@ This file is automatically generated; Do not edit it. :)
|
|
|
4
4
|
'''
|
|
5
5
|
VERSION_INFO = {
|
|
6
6
|
'final': True,
|
|
7
|
-
'version': '34.
|
|
7
|
+
'version': '34.2.0',
|
|
8
8
|
'branch_nick': 'release-34',
|
|
9
|
-
'revision_id': '
|
|
10
|
-
'revno':
|
|
9
|
+
'revision_id': '84e9b64a9f76c27f40451295bcf97be779124447',
|
|
10
|
+
'revno': 12794
|
|
11
11
|
}
|