Beispiel #1
0
    def __init__(self, rucio_host=None, auth_host=None, account=None, ca_cert=None, auth_type=None, creds=None, timeout=600, user_agent='rucio-clients', vo=None, logger=None):
        """
        Constructor of the BaseClient.
        :param rucio_host: The address of the rucio server, if None it is read from the config file.
        :param rucio_port: The port of the rucio server, if None it is read from the config file.
        :param auth_host: The address of the rucio authentication server, if None it is read from the config file.
        :param auth_port: The port of the rucio authentication server, if None it is read from the config file.
        :param account: The account to authenticate to rucio.
        :param use_ssl: Enable or disable ssl for commucation. Default is enabled.
        :param ca_cert: The path to the rucio server certificate.
        :param auth_type: The type of authentication (e.g.: 'userpass', 'kerberos' ...)
        :param creds: Dictionary with credentials needed for authentication.
        :param user_agent: Indicates the client.
        :param vo: The VO to authenticate into.
        :param logger: Logger object to use. If None, use the default LOG created by the module
        """

        self.host = rucio_host
        self.list_hosts = []
        self.auth_host = auth_host
        self.logger = logger or LOG
        self.session = Session()
        self.user_agent = "%s/%s" % (user_agent, version.version_string())  # e.g. "rucio-clients/0.2.13"
        sys.argv[0] = sys.argv[0].split('/')[-1]
        self.script_id = '::'.join(sys.argv[0:2])
        if self.script_id == '':  # Python interpreter used
            self.script_id = 'python'
        try:
            if self.host is None:
                self.host = config_get('client', 'rucio_host')
            if self.auth_host is None:
                self.auth_host = config_get('client', 'auth_host')
        except (NoOptionError, NoSectionError) as error:
            raise MissingClientParameter('Section client and Option \'%s\' cannot be found in config file' % error.args[0])

        try:
            self.trace_host = config_get('trace', 'trace_host')
        except (NoOptionError, NoSectionError):
            self.trace_host = self.host
            self.logger.debug('No trace_host passed. Using rucio_host instead')

        self.account = account
        self.vo = vo
        self.ca_cert = ca_cert
        self.auth_type = auth_type
        self.creds = creds
        self.auth_token = None
        self.auth_token_file_path = config_get('client', 'auth_token_file_path', False, None)
        self.headers = {}
        self.timeout = timeout
        self.request_retries = self.REQUEST_RETRIES
        self.token_exp_epoch = None
        self.token_exp_epoch_file = None
        self.auth_oidc_refresh_active = config_get_bool('client', 'auth_oidc_refresh_active', False, False)
        # defining how many minutes before token expires, oidc refresh (if active) should start
        self.auth_oidc_refresh_before_exp = config_get_int('client', 'auth_oidc_refresh_before_exp', False, 20)

        if auth_type is None:
            self.logger.debug('No auth_type passed. Trying to get it from the environment variable RUCIO_AUTH_TYPE and config file.')
            if 'RUCIO_AUTH_TYPE' in environ:
                if environ['RUCIO_AUTH_TYPE'] not in ['userpass', 'x509', 'x509_proxy', 'gss', 'ssh', 'saml', 'oidc']:
                    raise MissingClientParameter('Possible RUCIO_AUTH_TYPE values: userpass, x509, x509_proxy, gss, ssh, saml, oidc, vs. ' + environ['RUCIO_AUTH_TYPE'])
                self.auth_type = environ['RUCIO_AUTH_TYPE']
            else:
                try:
                    self.auth_type = config_get('client', 'auth_type')
                except (NoOptionError, NoSectionError) as error:
                    raise MissingClientParameter('Option \'%s\' cannot be found in config file' % error.args[0])

        if self.auth_type == 'oidc':
            if not self.creds:
                self.creds = {}
            # if there are defautl values, check if rucio.cfg does not specify them, otherwise put default
            if 'oidc_refresh_lifetime' not in self.creds or self.creds['oidc_refresh_lifetime'] is None:
                self.creds['oidc_refresh_lifetime'] = config_get('client', 'oidc_refresh_lifetime', False, None)
            if 'oidc_issuer' not in self.creds or self.creds['oidc_issuer'] is None:
                self.creds['oidc_issuer'] = config_get('client', 'oidc_issuer', False, None)
            if 'oidc_audience' not in self.creds or self.creds['oidc_audience'] is None:
                self.creds['oidc_audience'] = config_get('client', 'oidc_audience', False, None)
            if 'oidc_auto' not in self.creds or self.creds['oidc_auto'] is False:
                self.creds['oidc_auto'] = config_get_bool('client', 'oidc_auto', False, False)
            if self.creds['oidc_auto']:
                if 'oidc_username' not in self.creds or self.creds['oidc_username'] is None:
                    self.creds['oidc_username'] = config_get('client', 'oidc_username', False, None)
                if 'oidc_password' not in self.creds or self.creds['oidc_password'] is None:
                    self.creds['oidc_password'] = config_get('client', 'oidc_password', False, None)
            if 'oidc_scope' not in self.creds or self.creds['oidc_scope'] == 'openid profile':
                self.creds['oidc_scope'] = config_get('client', 'oidc_scope', False, 'openid profile')
            if 'oidc_polling' not in self.creds or self.creds['oidc_polling'] is False:
                self.creds['oidc_polling'] = config_get_bool('client', 'oidc_polling', False, False)

        if not self.creds:
            self.logger.debug('No creds passed. Trying to get it from the config file.')
            self.creds = {}
            try:
                if self.auth_type in ['userpass', 'saml']:
                    self.creds['username'] = config_get('client', 'username')
                    self.creds['password'] = config_get('client', 'password')
                elif self.auth_type == 'x509':
                    self.creds['client_cert'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'client_cert'))))
                    if not path.exists(self.creds['client_cert']):
                        raise MissingClientParameter('X.509 client certificate not found: %s' % self.creds['client_cert'])
                    self.creds['client_key'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'client_key'))))
                    if not path.exists(self.creds['client_key']):
                        raise MissingClientParameter('X.509 client key not found: %s' % self.creds['client_key'])
                    else:
                        perms = oct(os.stat(self.creds['client_key']).st_mode)[-3:]
                        if perms not in ['400', '600']:
                            raise CannotAuthenticate('X.509 authentication selected, but private key (%s) permissions are liberal (required: 400 or 600, found: %s)' % (self.creds['client_key'], perms))
                elif self.auth_type == 'x509_proxy':
                    try:
                        self.creds['client_proxy'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'client_x509_proxy'))))
                    except NoOptionError:
                        # Recreate the classic GSI logic for locating the proxy:
                        # - $X509_USER_PROXY, if it is set.
                        # - /tmp/x509up_u`id -u` otherwise.
                        # If neither exists (at this point, we don't care if it exists but is invalid), then rethrow
                        if 'X509_USER_PROXY' in environ:
                            self.creds['client_proxy'] = environ['X509_USER_PROXY']
                        else:
                            fname = '/tmp/x509up_u%d' % geteuid()
                            if path.exists(fname):
                                self.creds['client_proxy'] = fname
                            else:
                                raise MissingClientParameter('Cannot find a valid X509 proxy; not in %s, $X509_USER_PROXY not set, and '
                                                             '\'x509_proxy\' not set in the configuration file.' % fname)
                elif self.auth_type == 'ssh':
                    self.creds['ssh_private_key'] = path.abspath(path.expanduser(path.expandvars(config_get('client', 'ssh_private_key'))))
            except (NoOptionError, NoSectionError) as error:
                if error.args[0] != 'client_key':
                    raise MissingClientParameter('Option \'%s\' cannot be found in config file' % error.args[0])

        rucio_scheme = urlparse(self.host).scheme
        auth_scheme = urlparse(self.auth_host).scheme

        if rucio_scheme != 'http' and rucio_scheme != 'https':
            raise ClientProtocolNotSupported('\'%s\' not supported' % rucio_scheme)

        if auth_scheme != 'http' and auth_scheme != 'https':
            raise ClientProtocolNotSupported('\'%s\' not supported' % auth_scheme)

        if (rucio_scheme == 'https' or auth_scheme == 'https') and ca_cert is None:
            self.logger.debug('HTTPS is required, but no ca_cert was passed. Trying to get it from X509_CERT_DIR.')
            self.ca_cert = os.environ.get('X509_CERT_DIR', None)
            if self.ca_cert is None:
                self.logger.debug('HTTPS is required, but no ca_cert was passed and X509_CERT_DIR is not defined. Trying to get it from the config file.')
                try:
                    self.ca_cert = path.expandvars(config_get('client', 'ca_cert'))
                except (NoOptionError, NoSectionError):
                    self.logger.debug('No ca_cert found in configuration. Falling back to Mozilla default CA bundle (certifi).')
                    self.ca_cert = True

        self.list_hosts = [self.host]

        if account is None:
            self.logger.debug('No account passed. Trying to get it from the RUCIO_ACCOUNT environment variable or the config file.')
            try:
                self.account = environ['RUCIO_ACCOUNT']
            except KeyError:
                try:
                    self.account = config_get('client', 'account')
                except (NoOptionError, NoSectionError):
                    pass

        if vo is None:
            self.logger.debug('No VO passed. Trying to get it from environment variable RUCIO_VO.')
            try:
                self.vo = environ['RUCIO_VO']
            except KeyError:
                self.logger.debug('No VO found. Trying to get it from the config file.')
                try:
                    self.vo = config_get('client', 'vo')
                except (NoOptionError, NoSectionError):
                    self.logger.debug('No VO found. Using default VO.')
                    self.vo = 'def'

        token_filename_suffix = "for_default_account" if self.account is None else "for_account_" + self.account

        # if token file path is defined in the rucio.cfg file, use that file. Currently this prevents authenticating as another user or VO.
        if self.auth_token_file_path:
            self.token_file = self.auth_token_file_path
            self.token_path = '/'.join(self.token_file.split('/')[:-1])
        else:
            self.token_path = self.TOKEN_PATH_PREFIX + getpass.getuser()
            if self.vo != 'def':
                self.token_path += '@%s' % self.vo
            self.token_file = self.token_path + '/' + self.TOKEN_PREFIX + token_filename_suffix

        self.token_exp_epoch_file = self.token_path + '/' + self.TOKEN_EXP_PREFIX + token_filename_suffix

        self.__authenticate()

        try:
            self.request_retries = int(config_get('client', 'request_retries'))
        except (NoOptionError, RuntimeError):
            LOG.debug('request_retries not specified in config file. Taking default.')
        except ValueError:
            self.logger.debug('request_retries must be an integer. Taking default.')
Beispiel #2
0
    def __init__(self,
                 rucio_host=None,
                 auth_host=None,
                 account=None,
                 ca_cert=None,
                 auth_type=None,
                 creds=None,
                 timeout=None,
                 user_agent='rucio-clients'):
        """
        Constructor of the BaseClient.
        :param rucio_host: the address of the rucio server, if None it is read from the config file.
        :param rucio_port: the port of the rucio server, if None it is read from the config file.
        :param auth_host: the address of the rucio authentication server, if None it is read from the config file.
        :param auth_port: the port of the rucio authentication server, if None it is read from the config file.
        :param account: the account to authenticate to rucio.
        :param use_ssl: enable or disable ssl for commucation. Default is enabled.
        :param ca_cert: the path to the rucio server certificate.
        :param auth_type: the type of authentication (e.g.: 'userpass', 'kerberos' ...)
        :param creds: a dictionary with credentials needed for authentication.
        :param user_agent: indicates the client
        """

        self.host = rucio_host
        self.list_hosts = []
        self.auth_host = auth_host
        self.session = session()
        self.user_agent = "%s/%s" % (user_agent, version.version_string()
                                     )  # e.g. "rucio-clients/0.2.13"
        sys.argv[0] = sys.argv[0].split('/')[-1]
        self.script_id = '::'.join(sys.argv[0:2])
        if self.script_id == '':  # Python interpreter used
            self.script_id = 'python'
        try:
            if self.host is None:
                self.host = config_get('client', 'rucio_host')
            if self.auth_host is None:
                self.auth_host = config_get('client', 'auth_host')
        except (NoOptionError, NoSectionError) as error:
            raise MissingClientParameter(
                'Section client and Option \'%s\' cannot be found in config file'
                % error.args[0])

        self.account = account
        self.ca_cert = ca_cert
        self.auth_type = auth_type
        self.creds = creds
        self.auth_token = None
        self.headers = {}
        self.timeout = timeout
        self.request_retries = self.REQUEST_RETRIES

        if auth_type is None:
            LOG.debug(
                'no auth_type passed. Trying to get it from the environment variable RUCIO_AUTH_TYPE and config file.'
            )
            if 'RUCIO_AUTH_TYPE' in environ:
                if environ['RUCIO_AUTH_TYPE'] not in ('userpass', 'x509',
                                                      'x509_proxy', 'gss'):
                    raise MissingClientParameter(
                        'Possible RUCIO_AUTH_TYPE values: userpass, x509, x509_proxy, gss vs. '
                        + environ['RUCIO_AUTH_TYPE'])
                self.auth_type = environ['RUCIO_AUTH_TYPE']
            else:
                try:
                    self.auth_type = config_get('client', 'auth_type')
                except (NoOptionError, NoSectionError) as error:
                    raise MissingClientParameter(
                        'Option \'%s\' cannot be found in config file' %
                        error.args[0])

        if creds is None:
            LOG.debug(
                'no creds passed. Trying to get it from the config file.')
            self.creds = {}
            try:
                if self.auth_type == 'userpass':
                    self.creds['username'] = config_get('client', 'username')
                    self.creds['password'] = config_get('client', 'password')
                elif self.auth_type == 'x509':
                    self.creds['client_cert'] = path.abspath(
                        path.expanduser(
                            path.expandvars(config_get('client',
                                                       'client_cert'))))
                    self.creds['client_key'] = path.abspath(
                        path.expanduser(
                            path.expandvars(config_get('client',
                                                       'client_key'))))
                elif self.auth_type == 'x509_proxy':
                    self.creds['client_proxy'] = path.abspath(
                        path.expanduser(
                            path.expandvars(
                                config_get('client', 'client_x509_proxy'))))
            except (NoOptionError, NoSectionError) as error:
                if error.args[0] != 'client_key':
                    raise MissingClientParameter(
                        'Option \'%s\' cannot be found in config file' %
                        error.args[0])

        rucio_scheme = urlparse(self.host).scheme
        auth_scheme = urlparse(self.auth_host).scheme

        if rucio_scheme != 'http' and rucio_scheme != 'https':
            raise ClientProtocolNotSupported('\'%s\' not supported' %
                                             rucio_scheme)

        if auth_scheme != 'http' and auth_scheme != 'https':
            raise ClientProtocolNotSupported('\'%s\' not supported' %
                                             auth_scheme)

        if (rucio_scheme == 'https'
                or auth_scheme == 'https') and ca_cert is None:
            LOG.debug(
                'no ca_cert passed. Trying to get it from the config file.')
            try:
                self.ca_cert = path.expandvars(config_get('client', 'ca_cert'))
            except (NoOptionError, NoSectionError) as error:
                raise MissingClientParameter(
                    'Option \'%s\' cannot be found in config file' %
                    error.args[0])

        self.list_hosts = [self.host]

        if account is None:
            LOG.debug(
                'no account passed. Trying to get it from the config file.')
            try:
                self.account = config_get('client', 'account')
            except (NoOptionError, NoSectionError):
                try:
                    self.account = environ['RUCIO_ACCOUNT']
                except KeyError:
                    raise MissingClientParameter(
                        'Option \'account\' cannot be found in config file and RUCIO_ACCOUNT is not set.'
                    )

        token_path = self.TOKEN_PATH_PREFIX + self.account
        self.token_file = token_path + '/' + self.TOKEN_PREFIX + self.account
        self.__authenticate()

        try:
            self.request_retries = int(config_get('client', 'request_retries'))
        except NoOptionError:
            LOG.debug(
                'request_retries not specified in config file. Taking default.'
            )
        except ValueError:
            LOG.debug('request_retries must be an integer. Taking default.')
Beispiel #3
0
    def __init__(self,
                 rucio_host=None,
                 auth_host=None,
                 account=None,
                 ca_cert=None,
                 auth_type=None,
                 creds=None,
                 timeout=600,
                 user_agent='rucio-clients'):
        """
        Constructor of the BaseClient.
        :param rucio_host: the address of the rucio server, if None it is read from the config file.
        :param rucio_port: the port of the rucio server, if None it is read from the config file.
        :param auth_host: the address of the rucio authentication server, if None it is read from the config file.
        :param auth_port: the port of the rucio authentication server, if None it is read from the config file.
        :param account: the account to authenticate to rucio.
        :param use_ssl: enable or disable ssl for commucation. Default is enabled.
        :param ca_cert: the path to the rucio server certificate.
        :param auth_type: the type of authentication (e.g.: 'userpass', 'kerberos' ...)
        :param creds: a dictionary with credentials needed for authentication.
        :param user_agent: indicates the client
        """

        self.host = rucio_host
        self.list_hosts = []
        self.auth_host = auth_host
        self.session = Session()
        self.user_agent = "%s/%s" % (user_agent, version.version_string()
                                     )  # e.g. "rucio-clients/0.2.13"
        sys.argv[0] = sys.argv[0].split('/')[-1]
        self.script_id = '::'.join(sys.argv[0:2])
        if self.script_id == '':  # Python interpreter used
            self.script_id = 'python'
        try:
            if self.host is None:
                self.host = config_get('client', 'rucio_host')
            if self.auth_host is None:
                self.auth_host = config_get('client', 'auth_host')
        except (NoOptionError, NoSectionError) as error:
            raise MissingClientParameter(
                'Section client and Option \'%s\' cannot be found in config file'
                % error.args[0])

        self.account = account
        self.ca_cert = ca_cert
        self.auth_type = auth_type
        self.creds = creds
        self.auth_token = None
        self.headers = {}
        self.timeout = timeout
        self.request_retries = self.REQUEST_RETRIES

        if auth_type is None:
            LOG.debug(
                'no auth_type passed. Trying to get it from the environment variable RUCIO_AUTH_TYPE and config file.'
            )
            if 'RUCIO_AUTH_TYPE' in environ:
                if environ['RUCIO_AUTH_TYPE'] not in [
                        'userpass', 'x509', 'x509_proxy', 'gss', 'ssh', 'saml'
                ]:
                    raise MissingClientParameter(
                        'Possible RUCIO_AUTH_TYPE values: userpass, x509, x509_proxy, gss, ssh, saml, oidc, vs. '
                        + environ['RUCIO_AUTH_TYPE'])
                self.auth_type = environ['RUCIO_AUTH_TYPE']
            else:
                try:
                    self.auth_type = config_get('client', 'auth_type')
                except (NoOptionError, NoSectionError) as error:
                    raise MissingClientParameter(
                        'Option \'%s\' cannot be found in config file' %
                        error.args[0])

        if creds is None:
            LOG.debug(
                'no creds passed. Trying to get it from the config file.')
            self.creds = {}
            try:
                if self.auth_type in ['userpass', 'saml']:
                    self.creds['username'] = config_get('client', 'username')
                    self.creds['password'] = config_get('client', 'password')
                elif self.auth_type == 'oidc':
                    self.creds['oidc_auto'] = config_get('client', 'oidc_auto')
                    self.creds['oidc_scope'] = config_get(
                        'client', 'oidc_scope')
                    self.creds['oidc_audience'] = config_get(
                        'client', 'oidc_audience')
                    self.creds['oidc_polling'] = config_get(
                        'client', 'oidc_polling')
                    self.creds['oidc_refresh_lifetime'] = config_get(
                        'client', 'oidc_refresh_lifetime')
                    self.creds['oidc_issuer'] = config_get(
                        'client', 'oidc_issuer')
                    if self.creds['oidc_auto']:
                        self.creds['oidc_username'] = config_get(
                            'client', 'oidc_username')
                        self.creds['oidc_password'] = config_get(
                            'client', 'oidc_password')
                elif self.auth_type == 'x509':
                    self.creds['client_cert'] = path.abspath(
                        path.expanduser(
                            path.expandvars(config_get('client',
                                                       'client_cert'))))
                    self.creds['client_key'] = path.abspath(
                        path.expanduser(
                            path.expandvars(config_get('client',
                                                       'client_key'))))
                elif self.auth_type == 'x509_proxy':
                    try:
                        self.creds['client_proxy'] = path.abspath(
                            path.expanduser(
                                path.expandvars(
                                    config_get('client',
                                               'client_x509_proxy'))))
                    except NoOptionError as error:
                        # Recreate the classic GSI logic for locating the proxy:
                        # - $X509_USER_PROXY, if it is set.
                        # - /tmp/x509up_u`id -u` otherwise.
                        # If neither exists (at this point, we don't care if it exists but is invalid), then rethrow
                        if 'X509_USER_PROXY' in environ:
                            self.creds['client_proxy'] = environ[
                                'X509_USER_PROXY']
                        else:
                            fname = '/tmp/x509up_u%d' % geteuid()
                            if path.exists(fname):
                                self.creds['client_proxy'] = fname
                            else:
                                raise MissingClientParameter(
                                    'Cannot find a valid X509 proxy; not in %s, $X509_USER_PROXY not set, and '
                                    '\'x509_proxy\' not set in the configuration file.'
                                    % fname)
                elif self.auth_type == 'ssh':
                    self.creds['ssh_private_key'] = path.abspath(
                        path.expanduser(
                            path.expandvars(
                                config_get('client', 'ssh_private_key'))))
            except (NoOptionError, NoSectionError) as error:
                if error.args[0] != 'client_key':
                    raise MissingClientParameter(
                        'Option \'%s\' cannot be found in config file' %
                        error.args[0])

        rucio_scheme = urlparse(self.host).scheme
        auth_scheme = urlparse(self.auth_host).scheme

        if rucio_scheme != 'http' and rucio_scheme != 'https':
            raise ClientProtocolNotSupported('\'%s\' not supported' %
                                             rucio_scheme)

        if auth_scheme != 'http' and auth_scheme != 'https':
            raise ClientProtocolNotSupported('\'%s\' not supported' %
                                             auth_scheme)

        if (rucio_scheme == 'https'
                or auth_scheme == 'https') and ca_cert is None:
            LOG.debug(
                'no ca_cert passed. Trying to get it from the config file.')
            try:
                self.ca_cert = path.expandvars(config_get('client', 'ca_cert'))
            except (NoOptionError, NoSectionError) as error:
                raise MissingClientParameter(
                    'Option \'%s\' cannot be found in config file' %
                    error.args[0])

        self.list_hosts = [self.host]

        if account is None:
            LOG.debug(
                'no account passed. Trying to get it from the config file.')
            try:
                self.account = environ['RUCIO_ACCOUNT']
            except KeyError:
                try:
                    self.account = config_get('client', 'account')
                except (NoOptionError, NoSectionError):
                    raise MissingClientParameter(
                        'Option \'account\' cannot be found in config file and RUCIO_ACCOUNT is not set.'
                    )

        token_path = self.TOKEN_PATH_PREFIX + self.account
        self.token_file = token_path + '/' + self.TOKEN_PREFIX + self.account
        self.__authenticate()

        try:
            self.request_retries = int(config_get('client', 'request_retries'))
        except NoOptionError:
            LOG.debug(
                'request_retries not specified in config file. Taking default.'
            )
        except ValueError:
            LOG.debug('request_retries must be an integer. Taking default.')