def test_load_from_environ(self): # No environ set import os with self.assertRaises(ConfigLoadError): load_from_environ() os.environ['SMC_ADDRESS'] = 'http://1.1.1.1' with self.assertRaises(ConfigLoadError): load_from_environ() os.environ['SMC_API_KEY'] = 'abc123' data = load_from_environ() self.assertEqual(data['api_key'], 'abc123') self.assertEqual(data['url'], 'http://1.1.1.1:8082') # HTTPS os.environ['SMC_ADDRESS'] = 'https://2.1.1.1' data = load_from_environ() self.assertEqual(data['url'], 'https://2.1.1.1:8082') self.assertFalse(data['verify']) # No cert provided # HTTPS with client cert os.environ['SMC_ADDRESS'] = 'https://2.1.1.1' os.environ['SMC_CLIENT_CERT'] = 'mycert' data = load_from_environ() self.assertEqual(data['verify'], 'mycert') # No cert provided # Unique port os.environ['SMC_ADDRESS'] = 'https://2.1.1.1:8888' data = load_from_environ() self.assertEqual(data['url'], 'https://2.1.1.1:8888') # Timeout and API Version os.environ['SMC_TIMEOUT'] = '30' os.environ['SMC_API_VERSION'] = '6.2' os.environ['SMC_DOMAIN'] = 'mydomain' data = load_from_environ() self.assertEqual(data['timeout'], 30) self.assertEqual(data['domain'], 'mydomain') for var in [ 'SMC_TIMEOUT', 'SMC_API_VERSION', 'SMC_DOMAIN', 'SMC_ADDRESS', 'SMC_API_KEY' ]: del os.environ[var]
def login(self, url=None, api_key=None, login=None, pwd=None, api_version=None, timeout=None, verify=True, alt_filepath=None, domain=None, **kwargs): """ Login to SMC API and retrieve a valid session. Session will be re-used when multiple queries are required. An example login and logout session:: from smc import session session.login(url='http://1.1.1.1:8082', api_key='SomeSMCG3ener@t3dPwd') .....do stuff..... session.logout() :param str url: ip of SMC management server :param str api_key: API key created for api client in SMC :param str login: Administrator user in SMC that has privilege to SMC API. :param str pwd: Password for user login. :param api_version (optional): specify api version :param int timeout: (optional): specify a timeout for initial connect; (default 10) :param str|boolean verify: verify SSL connections using cert (default: verify=True) You can pass verify the path to a CA_BUNDLE file or directory with certificates of trusted CAs :param str alt_filepath: If using .smcrc, alternate file+path :param str domain: domain to log in to. If domains are not configured, this field will be ignored and api client logged in to 'Shared Domain'. :raises ConfigLoadError: loading cfg from ~.smcrc fails For SSL connections, you can disable validation of the SMC SSL certificate by setting verify=False, however this is not a recommended practice. If you want to use the SSL certificate generated and used by the SMC API server for validation, set verify='path_to_my_dot_pem'. It is also recommended that your certificate has subjectAltName defined per RFC 2818 If SSL warnings are thrown in debug output, see: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings Logout should be called to remove the session immediately from the SMC server. .. note:: As of SMC 6.4 it is possible to give a standard Administrative user access to the SMC API. It is still possible to use an API Client by providing the api_key in the login call. """ if not url or (not api_key and not (login and pwd)): # First try load from file try: cfg = load_from_file(alt_filepath) if alt_filepath\ is not None else load_from_file() logger.debug('Read config data from file: %s', cfg) except ConfigLoadError: # Last ditch effort, try to load from environment cfg = load_from_environ() logger.debug('Read config data from environ: %s', cfg) url = cfg.get('url') api_key = cfg.get('api_key') api_version = cfg.get('api_version') verify = cfg.get('verify') timeout = cfg.get('timeout') domain = cfg.get('domain') kwargs = cfg.get('kwargs') if timeout: self._timeout = timeout self._api_version = get_api_version(url, api_version, timeout, verify) base = get_api_base(url, self.api_version, verify=verify) self._resource.add(get_entry_points(base, timeout, verify)) s = requests.session() # empty session json = {'domain': domain} if api_key: json.update(authenticationkey=api_key) if kwargs: json.update(**kwargs) self._extra_args.update(**kwargs) params = dict(login=login, pwd=pwd) if login and pwd else None req = dict( url=self.entry_points.get('login') if api_key else \ '{}/{}/lms_login'.format(url, self._api_version), json=json, params=params, headers={'content-type': 'application/json'}, verify=verify) r = s.post(**req) logger.info('Using SMC API version: %s', self.api_version) if r.status_code == 200: self._session = s # session creation was successful self._session.verify = verify # make verify setting persistent self._url = url self.credential.set_credentials(api_key, login, pwd) if domain: self._domain = domain self._sessions[self.domain] = self.session if self.connection is None: self._connection = smc.api.web.SMCAPIConnection(self) logger.debug( 'Login succeeded and session retrieved: %s, domain: %s', self.session_id, self.domain) # Reload entry points self.entry_points.clear() self._resource.add(reload_entry_points(self)) else: raise SMCConnectionError( 'Login failed, HTTP status code: %s and reason: %s' % (r.status_code, r.reason)) if not self._MODS_LOADED: logger.debug('Registering class mappings.') # Load the modules to register needed classes for pkg in ('smc.policy', 'smc.elements', 'smc.routing', 'smc.vpn', 'smc.administration', 'smc.core', 'smc.administration.user_auth'): import_submodules(pkg, recursive=False) self._MODS_LOADED = True
def login(self, url=None, api_key=None, login=None, pwd=None, api_version=None, timeout=None, verify=True, alt_filepath=None, domain=None, **kwargs): """ Login to SMC API and retrieve a valid session. Session will be re-used when multiple queries are required. An example login and logout session:: from smc import session session.login(url='http://1.1.1.1:8082', api_key='SomeSMCG3ener@t3dPwd') .....do stuff..... session.logout() :param str url: ip of SMC management server :param str api_key: API key created for api client in SMC :param str login: Administrator user in SMC that has privilege to SMC API. :param str pwd: Password for user login. :param api_version (optional): specify api version :param int timeout: (optional): specify a timeout for initial connect; (default 10) :param str|boolean verify: verify SSL connections using cert (default: verify=True) You can pass verify the path to a CA_BUNDLE file or directory with certificates of trusted CAs :param str alt_filepath: If using .smcrc, alternate file+path :param str domain: domain to log in to. If domains are not configured, this field will be ignored and api client logged in to 'Shared Domain'. :param bool retry_on_busy: pass as kwarg with boolean if you want to add retries if the SMC returns HTTP 503 error during operation. You can also optionally customize this behavior and call :meth:`.set_retry_on_busy` :raises ConfigLoadError: loading cfg from ~.smcrc fails For SSL connections, you can disable validation of the SMC SSL certificate by setting verify=False, however this is not a recommended practice. If you want to use the SSL certificate generated and used by the SMC API server for validation, set verify='path_to_my_dot_pem'. It is also recommended that your certificate has subjectAltName defined per RFC 2818 If SSL warnings are thrown in debug output, see: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings Logout should be called to remove the session immediately from the SMC server. .. note:: As of SMC 6.4 it is possible to give a standard Administrative user access to the SMC API. It is still possible to use an API Client by providing the api_key in the login call. """ if not url or (not api_key and not (login and pwd)): # First try load from file try: cfg = load_from_file(alt_filepath) if alt_filepath\ is not None else load_from_file() logger.debug('Read config data from file: %s', cfg) except ConfigLoadError: # Last ditch effort, try to load from environment cfg = load_from_environ() logger.debug('Read config data from environ: %s', cfg) url = cfg.get('url') api_key = cfg.get('api_key') api_version = cfg.get('api_version') verify = cfg.get('verify') timeout = cfg.get('timeout') domain = cfg.get('domain') kwargs = cfg.get('kwargs', {}) self._timeout = timeout or self._timeout self._domain = domain or self._domain self._url = url # Determine and set the API version we will use. self._api_version = get_api_version(url, api_version, timeout, verify) # Set the auth provider which will determine what type of login this is self.credential = Credential(api_key, login, pwd) # Retries configured generically retry_on_busy = kwargs.pop('retry_on_busy', False) request = self._build_auth_request(verify=verify, **kwargs) # This will raise if session login fails... self._session = self._get_session(request) self.session.verify = verify logger.debug('Login succeeded and session retrieved: %s, domain: %s', self.session_id, self.domain) if retry_on_busy: self.set_retry_on_busy() self._sessions[self.domain] = self.session if self.connection is None: self._connection = smc.api.web.SMCAPIConnection(self) # Load entry points load_entry_points(self) if not self._MODS_LOADED: logger.debug('Registering class mappings.') # Load the modules to register needed classes for pkg in ('smc.policy', 'smc.elements', 'smc.routing', 'smc.vpn', 'smc.administration', 'smc.core', 'smc.administration.user_auth'): import_submodules(pkg, recursive=False) self._MODS_LOADED = True