def test_called_with_alt_file(self, mock_open, mock_load):
        cfg = ("[smc]\n" "smc_address=1.1.1.1\n" "smc_apikey=12345abcdef")

        mock_open.return_value = io.StringIO(u'{}'.format(cfg))
        load_from_file(alt_filepath='/Users/myfile')
        mock_open.assert_called_once_with('/Users/myfile',
                                          'rt',
                                          encoding='UTF-8')
 def test_missing_credential_file_in_home_directory(self, mock_open):
     """
     Raises IOError because ~/.smcrc not found and alt_filepath not
     specified during login.
     """
     mock_open.side_effect = IOError()
     self.assertRaises(ConfigLoadError, lambda: load_from_file())
    def test_missing_section(self, mock_open):
        """
        Raises NoSectionError when missing main section [smc]
        """
        cfg = ("[foo]\n" "smc_address=1.1.1.1")

        mock_open.return_value = io.StringIO(u'{}'.format(cfg))
        self.assertRaises(ConfigLoadError, lambda: load_from_file())
    def test_missing_field_for_section(self, mock_open):
        """
        Raises NoOptionError when [smc] section is present but
        credential information is not complete
        """
        cfg = ("[smc]\n" "smc_address=1.1.1.1")

        mock_open.return_value = io.StringIO(u'{}'.format(cfg))
        self.assertRaises(ConfigLoadError, lambda: load_from_file())
 def test_ssl_enabled_settings(self, mock_open):
     """
     SSL specified, but verify disabled
     """
     cfg = ("[smc]\n"
            "smc_address=1.1.1.1\n"
            "smc_apikey=12345\n"
            "smc_ssl=True\n")
     mock_open.return_value = io.StringIO(u'{}'.format(cfg))
     login_dict = load_from_file()
     self.assertTrue(login_dict.get('verify') == False)
 def test_ssl_with_no_cert_file_and_ssl_enabled(self, mock_open):
     """
     SSL specified, verify enabled, not cert to verify against,
     verify will be disabled
     """
     cfg = ("[smc]\n"
            "smc_address=1.1.1.1\n"
            "smc_apikey=12345\n"
            "smc_ssl=True\n"
            "verify_ssl=True")
     mock_open.return_value = io.StringIO(u'{}'.format(cfg))
     login_dict = load_from_file()
     self.assertTrue(login_dict.get('verify') == False)
    def test_bogus_entries_are_ignored(self, mock_open):
        cfg = ("[smc]\n"
               "smc_address=1.1.1.1\n"
               "smc_apikey=12345abcdef\n"
               "foo=bar\n"
               "bar=foo")

        mock_open.return_value = io.StringIO(u'{}'.format(cfg))
        # This will fall down to transform_login to build the structure to call
        # login. This should not have unknown attributes in the dict
        login_dict = load_from_file()
        self.assertNotIn('foo', login_dict)
        self.assertNotIn('bar', login_dict)
 def test_invalid_timeout_and_api_version(self, mock_open):
     """
     If invalid timeout setting provided, i.e. 10a, 20b, etc,
     timeout is disabled
     """
     cfg = ("[smc]\n"
            "smc_address=1.1.1.1\n"
            "smc_apikey=12345\n"
            "timeout=60a\n"
            "api_version=abc")
     mock_open.return_value = io.StringIO(u'{}'.format(cfg))
     login_dict = load_from_file()
     self.assertIsNone(login_dict.get('timeout'))
     self.assertIsNone(login_dict.get('api_version'))
Beispiel #9
0
    def login(self, **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.qpi.session import session   
            session.login(url='http://1.1.1.1:8082', api_key='SomeSMCG3ener@t3dPwd')
            .....do stuff.....
            session.logout()
            
        :param url: ip of SMC management server
        :param api_key: API key created for api client in SMC
        :param api_version (optional): specify api version

        Logout should be called to remove the session immediately from the
        SMC server.
        #TODO: Implement SSL tracking
        """
        if kwargs:
            for key, value in kwargs.items():
                setattr(self, key, value)
        else:
            try:
                self.login(**load_from_file())
            except ConfigLoadError:
                raise
                    
        self.cache = SessionCache()
        self.cache.get_api_entry(self.url, self.api_version)
        self.api_version = self.cache.api_version

        s = requests.session() #no session yet
        r = s.post(self.cache.get_entry_href('login'),
                   json={'authenticationkey': self.api_key},
                   headers={'content-type': 'application/json'}
                   )
        if r.status_code == 200:
            self.session = s #session creation was successful
            self.cookies = self.session.cookies.items()
            logger.debug("Login succeeded and session retrieved: %s", \
                         self.cookies)
            self.connection = SMCAPIConnection(self)

        else:
            raise SMCConnectionError("Login failed, HTTP status code: %s" \
                                     % r.status_code)
    def test_valid_timeout_and_apiversion(self, mock_open):
        """
        Test the timeout field as valid value
        """
        cfg = ("[smc]\n"
               "smc_address=1.1.1.1\n"
               "smc_apikey=12345\n"
               "timeout=60\n"
               "api_version=6.1\n"
               "domain=mydomain")
        mock_open.return_value = io.StringIO(u'{}'.format(cfg))
        login_dict = load_from_file()

        self.assertEqual(login_dict.get('timeout'), 60)
        self.assertEqual(login_dict.get('api_version'), 6.1)
        self.assertEqual(login_dict.get('domain'), 'mydomain')
 def test_ssl_enabled_with_cert_verify(self, mock_open):
     """
     SSL specified, verification enabled and cert file provided
     """
     cfg = ("[smc]\n"
            "smc_address=1.1.1.1\n"
            "smc_apikey=12345\n"
            "smc_ssl=True\n"
            "verify_ssl=True\n"
            "ssl_cert_file=/usr/local/cert.pem")
     mock_open.return_value = io.StringIO(u'{}'.format(cfg))
     login_dict = load_from_file()
     self.assertEqual(login_dict.get('verify'), '/usr/local/cert.pem')
     # Transformed out of the final configuration
     self.assertNotIn('smc_ssl', login_dict)
     self.assertNotIn('verify_ssl', login_dict)
Beispiel #12
0
    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
Beispiel #13
0
    def login(self,
              url=None,
              api_key=None,
              api_version=None,
              timeout=None,
              verify=True,
              alt_filepath=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 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)
        :param str alt_filepath: If using .smcrc, alternate file+path

        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.
        """
        if url and api_key:
            self._url = url
            self._api_key = api_key
            if timeout:
                self._timeout = timeout
        else:
            try:
                cfg = load_from_file(alt_filepath) if alt_filepath\
                    is not None else load_from_file()
                logger.debug("Config read has data: %s", cfg)
                self._url = cfg.get('url')
                self._api_key = cfg.get('api_key')
                api_version = cfg.get('api_version')
                verify = cfg.get('verify')
                timeout = cfg.get('timeout')
                if timeout:
                    self._timeout = timeout
            except ConfigLoadError:
                raise

        self.cache.get_api_entry(self.url,
                                 api_version,
                                 timeout=self.timeout,
                                 verify=verify)
        s = requests.session()  #no session yet

        r = s.post(self.cache.get_entry_href('login'),
                   json={'authenticationkey': self.api_key},
                   headers={'content-type': 'application/json'},
                   verify=verify)

        if r.status_code == 200:
            self._session = s  #session creation was successful
            self._session.verify = verify  #make verify setting persistent
            logger.debug("Login succeeded and session retrieved: %s", \
                         self.session_id)
            self._connection = smc.api.web.SMCAPIConnection(self)
        else:
            raise SMCConnectionError("Login failed, HTTP status code: %s" \
                                     % r.status_code)
Beispiel #14
0
    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