예제 #1
0
    def test_missing_from_config_file_throws(self, _, missing_attributes, token):
        """
        Tests that if some required fields are missing from the ApiConfiguration an error is thrown

        :return:
        """
        # Create an ApiConfiguration with all values populated
        proxy_config = ProxyConfig(**{
            key.replace("proxy_", ""): value for key, value in source_config_details.items() if value is not None and "proxy" in key
        }) if source_config_details["proxy_address"] is not None else None

        api_config_kwargs = {key: value for key, value in source_config_details.items() if value is not None and "proxy" not in key}
        api_config_kwargs["proxy_config"] = proxy_config
        api_configuration = ApiConfiguration(**api_config_kwargs)

        # Pop off the missing attributes
        [setattr(api_configuration, missing_attribute, None) for missing_attribute in missing_attributes]

        # Ensure that there are no environment variables which can be used to fill the missing Api Url
        with patch.dict('os.environ', clear=True), self.assertRaises(ValueError) as ex:
            ApiClientBuilder.build(api_configuration=api_configuration, token=token)

        self.assertEqual(
            ex.exception.args[0], f"The fields {str(missing_attributes)} on the ApiConfiguration are set to None, "
                                  f"please ensure that you have provided them directly, via a secrets file or environment "
                                  f"variables")
    def test_get_token_with_proxy(self):

        secrets = {
            "api": {
                config_keys[key]["config"]: value for key, value in source_config_details.items() if
                value is not None and "proxy" not in key
            },
            "proxy": {
                config_keys[key]["config"]: value for key, value in source_config_details.items() if
                value is not None and "proxy" in key
            }
        }

        secrets["api"].pop("clientCertificate", None)

        if secrets["proxy"].get("address", None) is None:
            self.skipTest(f"missing proxy configuration")

        secrets_file = TempFileManager.create_temp_file(secrets)

        original_token, refresh_token = tu.get_okta_tokens(secrets_file.name)

        proxy_config = ProxyConfig(
            address=secrets["proxy"]["address"],
            username=secrets["proxy"]["username"],
            password=secrets["proxy"]["password"]
        )

        proxies = proxy_config.format_proxy_schema()

        with patch.dict('os.environ', {"HTTPS_PROXY": proxies["https"]}, clear=True):
            proxy_url = os.getenv("HTTPS_PROXY", None)

        if proxy_url is not None:

            refreshed_token = RefreshingToken(token_url=self.config.token_url,
                                              client_id=self.config.client_id,
                                              client_secret=self.config.client_secret,
                                              initial_access_token=original_token,
                                              initial_token_expiry=1,  # 1s expiry
                                              refresh_token=refresh_token,
                                              expiry_offset=3599,     # set to 1s expiry
                                              proxies={})

            self.assertIsNotNone(refreshed_token)
    def test_get_token_with_proxy(self):

        secrets = {
            "api": {
                config_keys[key]["config"]: value
                for key, value in source_config_details.items()
                if value is not None and "proxy" not in key
            },
            "proxy": {
                config_keys[key]["config"]: value
                for key, value in source_config_details.items()
                if value is not None and "proxy" in key
            }
        }

        secrets["api"].pop("clientCertificate", None)

        if secrets["proxy"].get("address", None) is None:
            self.skipTest(f"missing proxy configuration")

        TempFileManager.create_temp_file(secrets)

        proxy_config = ProxyConfig(address=secrets["proxy"]["address"],
                                   username=secrets["proxy"]["username"],
                                   password=secrets["proxy"]["password"])

        proxies = proxy_config.format_proxy_schema()

        with patch.dict('os.environ', {"HTTPS_PROXY": proxies["https"]},
                        clear=True):
            proxy_url = os.getenv("HTTPS_PROXY", None)

        if proxy_url is not None:

            refreshed_token = RefreshingToken(api_configuration=self.config,
                                              expiry_offset=3599)

            self.assertIsNotNone(refreshed_token)
    def __init__(self, **kwargs):
        """
        Iniitalise an ApiClientFactory by passing the token, api_url and app_name, or by
        passing in the api_secrets_filename

        :param str token: Bearer token used to initialise the API
        :param str api_secrets_filename: Name of secrets file (including full path)
        :param str api_url: LUSID API url
        :param str app_name: Application name (optional)
        :param str certificate_filename: Name of the certificate file (.pem, .cer or .crt)
        :param str proxy_url: The url of the proxy to use including the port e.g. http://myproxy.com:8888
        :param str proxy_username: The username for the proxy to use
        :param str proxy_password: The password for the proxy to use
        :param str correlation_id: Correlation id for all calls made from the returned LUSID API instances
        :param bool tcp_keep_alive: A flag for controlling if the API client uses TCP keep-alive probes
        """

        builder_kwargs = {}

        if "token" in kwargs and str(kwargs["token"]) != "None":

            # If there is a token use it along with the specified proxy details if specified
            config = ApiConfiguration(
                api_url=kwargs.get("api_url", None),
                certificate_filename=kwargs.get("certificate_filename", None),
                proxy_config=ProxyConfig(
                    address=kwargs.get("proxy_url", None),
                    username=kwargs.get("proxy_username", None),
                    password=kwargs.get("proxy_password", None),
                ) if kwargs.get("proxy_url", None) is not None else None,
                app_name=kwargs.get("app_name", None))

            builder_kwargs["api_configuration"] = config
            builder_kwargs["token"] = kwargs["token"]

        # Otherwise use a secrets file if it exists
        builder_kwargs["api_secrets_filename"] = kwargs.get(
            "api_secrets_filename", None)

        # add the correlation id if specified
        builder_kwargs["correlation_id"] = kwargs.get("correlation_id", None)

        # add the id provider response handler if specified
        builder_kwargs["id_provider_response_handler"] = kwargs.get(
            "id_provider_response_handler", None)

        builder_kwargs["tcp_keep_alive"] = kwargs.get("tcp_keep_alive", False)

        # Call the client builder, this will result in using either a token, secrets file or environment variables
        self.api_client = ApiClientBuilder.build(**builder_kwargs)
    def __init__(self, **kwargs):
        """
        Iniitalise an ApiClientFactory by passing the token, api_url and app_name, or by
        passing in the api_secrets_filename

        :param str token: Bearer token used to initialise the API
        :param str api_secrets_filename: Name of secrets file (including full path)
        :param str api_url: LUSID API url
        :param str app_name: Application name (optional)
        :param str certificate_filename: Name of the certificate file (.pem, .cer or .crt)
        :param str proxy_url: The url of the proxy to use including the port e.g. http://myproxy.com:8888
        :param str proxy_username: The username for the proxy to use
        :param str proxy_password: The password for the proxy to use
        """

        builder_kwargs = {}

        if "token" in kwargs and str(kwargs["token"]) != "None":
            # If there is a token use it along with the specified proxy details if specified
            config = ApiConfiguration(
                api_url=kwargs.get("api_url", None),
                certificate_filename=kwargs.get("certificate_filename", None),
                proxy_config=ProxyConfig(
                    address=kwargs.get("proxy_url", None),
                    username=kwargs.get("proxy_username", None),
                    password=kwargs.get("proxy_password", None),
                ) if kwargs.get("proxy_url", None) is not None else None,
                app_name=kwargs.get("app_name", None))

            builder_kwargs["api_configuration"] = config
            builder_kwargs["token"] = kwargs["token"]

        # Otherwise use a secrets file if it exists
        builder_kwargs["api_secrets_filename"] = kwargs.get(
            "api_secrets_filename", None)

        # Call the client builder, this will result in using either a token, secrets file or environment variables
        self.api_client = ApiClientBuilder.build(**builder_kwargs)
예제 #6
0
    def load(api_secrets_filename=None):
        """
        :param str api_secrets_filename: The full path to the JSON file containing the API credentials and optional proxy details

        :return: lusid.utilities.ApiConfiguration: The populated ApiConfiguration
        """

        # Get the config keys which contain the mapping between the ApiConfiguration attributes and the variable names
        # in the secrets.json file and environment variables e.g. token_url is tokenUrl (secrets.json) and
        # FBN_TOKEN_URL (env variable)
        with open(Path(__file__).parent.joinpath(
                'config_keys.json')) as json_file:
            config_keys = json.load(json_file)

        # The secrets file is a nested dictionary, set the names of the top level keys
        api_config_key = "api"
        proxy_config_key = "proxy"

        def _load_config_from_secrets_file():

            # If there is a secrets file specified and it exists get the details from it
            if api_secrets_filename is not None and os.path.exists(
                    api_secrets_filename) and os.path.isfile(
                        api_secrets_filename):
                with open(api_secrets_filename, "r") as secrets:
                    config = json.load(secrets)

            # If there is a secrets file specified and it does not exist log a warning to indicate that the specified file
            # could not be found and create an empty config
            elif api_secrets_filename is not None and (
                    not os.path.exists(api_secrets_filename)
                    or not os.path.isfile(api_secrets_filename)):
                logging.debug(
                    f"Provided secrets file of {api_secrets_filename} can not be found, please ensure you "
                    f"have correctly specified the full path to the file or don't provide a secrets file to use "
                    f"environment variables instead.")
                config = {}
            # If no secrets file is specified just create an empty config
            else:
                config = {}

            return config

        def _get_access_api_config():

            config = _load_config_from_secrets_file()

            # Populate the values for the api configuration preferring the secrets file over the environment variables
            populated_api_config_values = {
                key: config.get(api_config_key,
                                {}).get(value["config"],
                                        os.getenv(value["env"], None))
                for key, value in config_keys.items() if "proxy" not in key
            }

            return populated_api_config_values

        def _get_proxy_api_config():

            config = _load_config_from_secrets_file()

            # Populate the values for the proxy preferring the secrets file over the environment variables
            populated_proxy_values = {
                key.replace("proxy_", ""):
                config.get(proxy_config_key,
                           {}).get(value["config"],
                                   os.getenv(value["env"], None))
                for key, value in config_keys.items() if "proxy" in key
            }

            return populated_proxy_values

        populated_api_config_values = _get_access_api_config()
        populated_proxy_values = _get_proxy_api_config()

        # If the proxy address is missing ensure that no proxy is used in the ApiConfiguration
        if populated_proxy_values.get("address", None) is None:
            populated_api_config_values["proxy_config"] = None
        # Otherwise create a ProxyConfig to use
        else:
            populated_api_config_values["proxy_config"] = ProxyConfig(
                **populated_proxy_values)
        # Create and return the ApiConfiguration
        return ApiConfiguration(**populated_api_config_values)